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 }