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