View Javadoc

    1   /*
    2    *  soapUI, copyright (C) 2004-2007 eviware.com
    3    *
    4    *  soapUI is free software; you can redistribute it and/or modify it under the
    5    *  terms of version 2.1 of the GNU Lesser General Public License as published by
    6    *  the Free Software Foundation.
    7    *
    8    *  soapUI is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
    9    *  even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    10   *  See the GNU Lesser General Public License for more details at gnu.org.
    11   */
    12
    13  package com.eviware.soapui.impl.wsdl.support.wsdl;
    14
    15  import java.io.ByteArrayInputStream;
    16  import java.io.IOException;
    17  import java.io.InputStream;
    18  import java.net.URL;
    19  import java.util.HashMap;
    20  import java.util.Map;
    21
    22  import org.apache.commons.httpclient.Credentials;
    23  import org.apache.commons.httpclient.HostConfiguration;
    24  import org.apache.commons.httpclient.HttpClient;
    25  import org.apache.commons.httpclient.HttpState;
    26  import org.apache.commons.httpclient.NTCredentials;
    27  import org.apache.commons.httpclient.UsernamePasswordCredentials;
    28  import org.apache.commons.httpclient.auth.AuthScheme;
    29  import org.apache.commons.httpclient.auth.CredentialsNotAvailableException;
    30  import org.apache.commons.httpclient.auth.CredentialsProvider;
    31  import org.apache.commons.httpclient.auth.NTLMScheme;
    32  import org.apache.commons.httpclient.auth.RFC2617Scheme;
    33  import org.apache.commons.httpclient.methods.GetMethod;
    34
    35  import com.eviware.soapui.SoapUI;
    36  import com.eviware.soapui.impl.wsdl.support.http.HttpClientSupport;
    37  import com.eviware.soapui.impl.wsdl.support.http.ProxyUtils;
    38  import com.eviware.soapui.model.settings.Settings;
    39  import com.eviware.soapui.settings.HttpSettings;
    40  import com.eviware.soapui.support.UISupport;
    41  import com.eviware.soapui.support.swing.SwingWorker;
    42  import com.eviware.soapui.support.types.StringToStringMap;
    43  import com.eviware.x.form.XForm;
    44  import com.eviware.x.form.XFormDialog;
    45  import com.eviware.x.form.XFormDialogBuilder;
    46  import com.eviware.x.form.XFormFactory;
    47
    48  /***
    49   * WsdlLoader for URLs
    50   *
    51   * @author ole.matzura
    52   */
    53
    54  public class UrlWsdlLoader extends WsdlLoader
    55  {
    56  	private HttpState state;
    57  	private GetMethod getMethod;
    58  	private boolean aborted;
    59  	private Map<String,byte[]> urlCache = new HashMap<String,byte[]>();
    60  	private boolean finished;
    61  	private boolean useWorker;
    62
    63  	public UrlWsdlLoader(String url)
    64  	{
    65  		super( url );
    66  		state = new HttpState();
    67  	}
    68
    69  	public boolean isUseWorker()
    70  	{
    71  		return useWorker;
    72  	}
    73
    74  	public void setUseWorker( boolean useWorker )
    75  	{
    76  		this.useWorker = useWorker;
    77  	}
    78
    79  	public InputStream load() throws Exception
    80  	{
    81  		return load( getBaseURI() );
    82  	}
    83
    84  	public synchronized InputStream load( String url ) throws Exception
    85  	{
    86  		if( urlCache.containsKey( url ))
    87  		{
    88  			return new ByteArrayInputStream( urlCache.get( url ) );
    89  		}
    90
    91  		if( url.startsWith( "file:" ))
    92  			return new URL( url ).openStream();
    93
    94  		log.debug( "Getting wsdl component from [" + url + "]" );
    95
    96  		createGetMethod(url);
    97
    98  		if( aborted )
    99  			return null;
    100
    101 		LoaderWorker worker = new LoaderWorker();
    102 		if( useWorker)
    103 			worker.start();
    104 		else
    105 			worker.construct();
    106
    107 		while( !aborted && !finished )
    108 		{
    109 			Thread.sleep( 200 );
    110 		}
    111
    112 		// wait for method to catch up - required in unit tests..
    113 		while( !aborted && getMethod.getResponseBody() == null )
    114 		{
    115 			Thread.sleep( 200 );
    116 		}
    117
    118 		try
    119 		{
    120 			if (aborted)
    121 			{
    122 				throw new Exception("Load of url [" + url + "] was aborted");
    123 			}
    124 			else
    125 			{
    126 				byte[] content = getMethod.getResponseBody();
    127 				if( content != null )
    128 				{
    129 					if (HttpClientSupport.isZippedResponse( getMethod ))
    130 					{
    131 						content = HttpClientSupport.decompress( content );
    132 					}
    133
    134 					urlCache.put(url, content);
    135 					return new ByteArrayInputStream(content);
    136 				}
    137 				else
    138 				{
    139 					throw new Exception("Failed to load url; " + getMethod.getStatusCode() + " - " + getMethod.getStatusText());
    140 				}
    141 			}
    142 		}
    143
    144 		finally
    145 		{
    146 			getMethod.releaseConnection();
    147 		}
    148 	}
    149
    150 	private void createGetMethod(String url)
    151 	{
    152 		getMethod = new GetMethod( url );
    153 		getMethod.setDoAuthentication(true);
    154 		getMethod.getParams().setParameter(CredentialsProvider.PROVIDER, new WsdlCredentialsProvider());
    155
    156 		if (SoapUI.getSettings().getBoolean(HttpSettings.AUTHENTICATE_PREEMPTIVELY))
    157 		{
    158 			HttpClientSupport.getHttpClient().getParams().setAuthenticationPreemptive(true);
    159 		}
    160 		else
    161 		{
    162 			HttpClientSupport.getHttpClient().getParams().setAuthenticationPreemptive(false);
    163 		}
    164 	}
    165
    166 	private final class LoaderWorker extends SwingWorker
    167 	{
    168 		public Object construct()
    169 		{
    170 			HttpClient httpClient = HttpClientSupport.getHttpClient();
    171 			try
    172 			{
    173 				Settings soapuiSettings = SoapUI.getSettings();
    174
    175 				HttpClientSupport.applyHttpSettings( getMethod, soapuiSettings );
    176 				HostConfiguration hostConfiguration = ProxyUtils.initProxySettings( soapuiSettings, state, new HostConfiguration(), getMethod.getURI().toString() );
    177 				httpClient.executeMethod( hostConfiguration,	getMethod, state );
    178 			}
    179 			catch (Exception e)
    180 			{
    181 				return e;
    182 			}
    183 			finally
    184 			{
    185 				finished = true;
    186 			}
    187
    188 			return null;
    189 		}
    190 	}
    191
    192 	public boolean abort()
    193 	{
    194 		if( getMethod != null )
    195 			getMethod.abort();
    196
    197 		aborted = true;
    198
    199 		return true;
    200 	}
    201
    202 	public boolean isAborted()
    203 	{
    204 		return aborted;
    205 	}
    206
    207 	/***
    208 	 * CredentialsProvider for providing login information during WSDL loading
    209 	 *
    210 	 * @author ole.matzura
    211 	 */
    212
    213 	public final class WsdlCredentialsProvider implements CredentialsProvider
    214 	{
    215 		private XFormDialog basicDialog;
    216 		private XFormDialog ntDialog;
    217
    218 		public WsdlCredentialsProvider()
    219 		{
    220 		}
    221
    222 		public Credentials getCredentials(final AuthScheme authscheme, final String host, int port, boolean proxy)
    223 		throws CredentialsNotAvailableException
    224 		{
    225 			if (authscheme == null)
    226 			{
    227 				return null;
    228 			}
    229 			try
    230 			{
    231 				if (authscheme instanceof NTLMScheme)
    232 				{
    233 					if( hasCredentials() )
    234 					{
    235 						log.info( "Returning url credentials" );
    236 						return new NTCredentials( getUsername(), getPassword(), host, null );
    237 					}
    238
    239 					log.info(host + ":" + port + " requires Windows authentication");
    240 					if( ntDialog == null )
    241 					{
    242 						buildNtDialog();
    243 					}
    244
    245 					StringToStringMap values = new StringToStringMap();
    246 					values.put( "Info", "Authentication required for [" + host + ":" + port + "]" );
    247 					ntDialog.setValues( values );
    248
    249 					if( ntDialog.show() )
    250 					{
    251 						values = ntDialog.getValues();
    252 						return new NTCredentials(values.get( "Username"), values.get( "Password"), host, values.get( "Domain"));
    253 					}
    254 					else
    255 						throw new CredentialsNotAvailableException("Operation cancelled");
    256 				}
    257 				else if (authscheme instanceof RFC2617Scheme)
    258 				{
    259 					if( hasCredentials() )
    260 					{
    261 						log.info( "Returning url credentials" );
    262 						return new UsernamePasswordCredentials( getUsername(), getPassword() );
    263 					}
    264
    265 					log.info(host + ":" + port + " requires authentication with the realm '" + authscheme.getRealm() + "'");
    266 					if( basicDialog == null )
    267 						buildBasicDialog();
    268
    269 					StringToStringMap values = new StringToStringMap();
    270 					values.put( "Info", "Authentication required for [" + host + ":" + port + "]" );
    271 					basicDialog.setValues( values );
    272 					if( basicDialog.show() )
    273 					{
    274 						values = basicDialog.getValues();
    275 						return new UsernamePasswordCredentials(values.get( "Username"), values.get( "Password"));
    276 					}
    277 					else
    278 						throw new CredentialsNotAvailableException("Operation cancelled");
    279
    280 				}
    281 				else
    282 				{
    283 					throw new CredentialsNotAvailableException("Unsupported authentication scheme: "
    284 							+ authscheme.getSchemeName());
    285 				}
    286 			}
    287 			catch (IOException e)
    288 			{
    289 				throw new CredentialsNotAvailableException(e.getMessage(), e);
    290 			}
    291 		}
    292
    293 		private void buildBasicDialog()
    294 		{
    295 			XFormDialogBuilder builder = XFormFactory.createDialogBuilder( "Basic Authentication" );
    296 			XForm mainForm = builder.createForm( "Basic" );
    297 			mainForm.addLabel( "Info", "" );
    298 			mainForm.addTextField( "Username", "Username for authentication", XForm.FieldType.TEXT );
    299 			mainForm.addTextField( "Password", "Password for authentication", XForm.FieldType.PASSWORD );
    300
    301 			basicDialog = builder.buildDialog( builder.buildOkCancelActions(),
    302 					"Specify Basic Authentication Credentials", UISupport.OPTIONS_ICON );
    303 		}
    304
    305 		private void buildNtDialog()
    306 		{
    307 			XFormDialogBuilder builder = XFormFactory.createDialogBuilder( "NT Authentication" );
    308 			XForm mainForm = builder.createForm( "Basic" );
    309 			mainForm.addLabel( "Info", "" );
    310 			mainForm.addTextField( "Username", "Username for authentication", XForm.FieldType.TEXT );
    311 			mainForm.addTextField( "Password", "Password for authentication", XForm.FieldType.PASSWORD );
    312 			mainForm.addTextField( "Domain", "NT Domain for authentication", XForm.FieldType.TEXT );
    313
    314 			ntDialog = builder.buildDialog( builder.buildOkCancelActions(),
    315 					"Specify NT Authentication Credentials", UISupport.OPTIONS_ICON );
    316 		}
    317 	}
    318
    319 	public void close()
    320 	{
    321 	}
    322 }