1
2
3
4
5
6
7
8
9
10
11
12
13 package com.eviware.soapui.impl.wsdl.support.wsdl;
14
15 import java.io.ByteArrayInputStream;
16 import java.io.File;
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 org.apache.commons.httpclient.Credentials;
24 import org.apache.commons.httpclient.HostConfiguration;
25 import org.apache.commons.httpclient.HttpClient;
26 import org.apache.commons.httpclient.HttpState;
27 import org.apache.commons.httpclient.NTCredentials;
28 import org.apache.commons.httpclient.UsernamePasswordCredentials;
29 import org.apache.commons.httpclient.auth.AuthScheme;
30 import org.apache.commons.httpclient.auth.CredentialsNotAvailableException;
31 import org.apache.commons.httpclient.auth.CredentialsProvider;
32 import org.apache.commons.httpclient.auth.NTLMScheme;
33 import org.apache.commons.httpclient.auth.RFC2617Scheme;
34 import org.apache.commons.httpclient.methods.GetMethod;
35
36 import com.eviware.soapui.SoapUI;
37 import com.eviware.soapui.impl.support.definition.DefinitionLoader;
38 import com.eviware.soapui.impl.wsdl.support.CompressionSupport;
39 import com.eviware.soapui.impl.wsdl.support.PathUtils;
40 import com.eviware.soapui.impl.wsdl.support.http.HttpClientSupport;
41 import com.eviware.soapui.impl.wsdl.support.http.ProxyUtils;
42 import com.eviware.soapui.model.ModelItem;
43 import com.eviware.soapui.model.propertyexpansion.DefaultPropertyExpansionContext;
44 import com.eviware.soapui.model.settings.Settings;
45 import com.eviware.soapui.settings.HttpSettings;
46 import com.eviware.soapui.support.UISupport;
47 import com.eviware.soapui.support.swing.SwingWorker;
48 import com.eviware.soapui.support.types.StringToStringMap;
49 import com.eviware.x.form.XForm;
50 import com.eviware.x.form.XFormDialog;
51 import com.eviware.x.form.XFormDialogBuilder;
52 import com.eviware.x.form.XFormFactory;
53
54 /***
55 * WsdlLoader for URLs
56 *
57 * @author ole.matzura
58 */
59
60 public class UrlWsdlLoader extends WsdlLoader implements DefinitionLoader
61 {
62 private HttpState state;
63 protected GetMethod getMethod;
64 private boolean aborted;
65 protected Map<String, byte[]> urlCache = new HashMap<String, byte[]>();
66 protected boolean finished;
67 private boolean useWorker;
68 private ModelItem contextModelItem;
69
70 public UrlWsdlLoader( String url )
71 {
72 this( url, null );
73 }
74
75 public UrlWsdlLoader( String url, ModelItem contextModelItem )
76 {
77 super( url );
78 this.contextModelItem = contextModelItem;
79 state = new HttpState();
80 }
81
82 public boolean isUseWorker()
83 {
84 return useWorker;
85 }
86
87 public void setUseWorker( boolean useWorker )
88 {
89 this.useWorker = useWorker;
90 }
91
92 public InputStream load() throws Exception
93 {
94 return load( getBaseURI() );
95 }
96
97 public synchronized InputStream load( String url ) throws Exception
98 {
99 if( !PathUtils.isHttpPath( url ) )
100 {
101 try
102 {
103 File file = new File( url.replace( '/', File.separatorChar ) );
104 if( file.exists() )
105 url = file.toURI().toURL().toString();
106 }
107 catch( Exception e )
108 {
109 }
110 }
111
112 if( urlCache.containsKey( url ) )
113 {
114 setNewBaseURI( url );
115 return new ByteArrayInputStream( urlCache.get( url ) );
116 }
117
118 if( url.startsWith( "file:" ) )
119 {
120 return handleFile( url );
121 }
122
123 log.debug( "Getting wsdl component from [" + url + "]" );
124
125 createGetMethod( url );
126
127 if( aborted )
128 return null;
129
130 LoaderWorker worker = new LoaderWorker();
131 if( useWorker )
132 worker.start();
133 else
134 worker.construct();
135
136 while( !aborted && !finished )
137 {
138 Thread.sleep( 200 );
139 }
140
141
142 while( !aborted && getMethod.getResponseBody() == null )
143 {
144 Thread.sleep( 200 );
145 }
146
147 try
148 {
149 if( aborted )
150 {
151 throw new Exception( "Load of url [" + url + "] was aborted" );
152 }
153 else
154 {
155 byte[] content = getMethod.getResponseBody();
156 if( content != null )
157 {
158 String compressionAlg = HttpClientSupport.getResponseCompressionType( getMethod );
159 if( compressionAlg != null )
160 content = CompressionSupport.decompress( compressionAlg, content );
161
162 urlCache.put( url, content );
163 String newUrl = getMethod.getURI().getURI();
164 if( !url.equals( newUrl ) )
165 log.info( "BaseURI was redirected to [" + newUrl + "]" );
166 setNewBaseURI( newUrl );
167 urlCache.put( newUrl, content );
168 return new ByteArrayInputStream( content );
169 }
170 else
171 {
172 throw new Exception( "Failed to load url; " + getMethod.getStatusCode() + " - "
173 + getMethod.getStatusText() );
174 }
175 }
176 }
177
178 finally
179 {
180 getMethod.releaseConnection();
181 }
182 }
183
184 protected InputStream handleFile( String url ) throws IOException
185 {
186 setNewBaseURI( url );
187 return new URL( url ).openStream();
188 }
189
190 protected void createGetMethod( String url )
191 {
192 getMethod = new GetMethod( url );
193 getMethod.setFollowRedirects( true );
194 getMethod.setDoAuthentication( true );
195 getMethod.getParams().setParameter( CredentialsProvider.PROVIDER, new WsdlCredentialsProvider() );
196
197 if( SoapUI.getSettings().getBoolean( HttpSettings.AUTHENTICATE_PREEMPTIVELY ) )
198 {
199 HttpClientSupport.getHttpClient().getParams().setAuthenticationPreemptive( true );
200 }
201 else
202 {
203 HttpClientSupport.getHttpClient().getParams().setAuthenticationPreemptive( false );
204 }
205 }
206
207 public final class LoaderWorker extends SwingWorker
208 {
209 public Object construct()
210 {
211 HttpClient httpClient = HttpClientSupport.getHttpClient();
212 try
213 {
214 Settings soapuiSettings = SoapUI.getSettings();
215
216 HttpClientSupport.applyHttpSettings( getMethod, soapuiSettings );
217 HostConfiguration hostConfiguration = ProxyUtils.initProxySettings( soapuiSettings, state,
218 new HostConfiguration(), getMethod.getURI().toString(), contextModelItem == null ? null
219 : new DefaultPropertyExpansionContext( contextModelItem ) );
220
221 httpClient.executeMethod( hostConfiguration, getMethod, state );
222 }
223 catch( Exception e )
224 {
225 return e;
226 }
227 finally
228 {
229 finished = true;
230 }
231
232 return null;
233 }
234 }
235
236 public boolean abort()
237 {
238 if( getMethod != null )
239 getMethod.abort();
240
241 aborted = true;
242
243 return true;
244 }
245
246 public boolean isAborted()
247 {
248 return aborted;
249 }
250
251 /***
252 * CredentialsProvider for providing login information during WSDL loading
253 *
254 * @author ole.matzura
255 */
256
257 public final class WsdlCredentialsProvider implements CredentialsProvider
258 {
259 private XFormDialog basicDialog;
260 private XFormDialog ntDialog;
261
262 public WsdlCredentialsProvider()
263 {
264 }
265
266 public Credentials getCredentials( final AuthScheme authscheme, final String host, int port, boolean proxy )
267 throws CredentialsNotAvailableException
268 {
269 if( authscheme == null )
270 {
271 return null;
272 }
273 try
274 {
275 String pw = getPassword();
276 if( pw == null )
277 pw = "";
278
279 if( authscheme instanceof NTLMScheme )
280 {
281 if( hasCredentials() )
282 {
283 log.info( "Returning url credentials" );
284 return new NTCredentials( getUsername(), pw, host, null );
285 }
286
287 log.info( host + ":" + port + " requires Windows authentication" );
288 if( ntDialog == null )
289 {
290 buildNtDialog();
291 }
292
293 StringToStringMap values = new StringToStringMap();
294 values.put( "Info", "Authentication required for [" + host + ":" + port + "]" );
295 ntDialog.setValues( values );
296
297 if( ntDialog.show() )
298 {
299 values = ntDialog.getValues();
300 return new NTCredentials( values.get( "Username" ), values.get( "Password" ), host, values
301 .get( "Domain" ) );
302 }
303 else
304 throw new CredentialsNotAvailableException( "Operation cancelled" );
305 }
306 else if( authscheme instanceof RFC2617Scheme )
307 {
308 if( hasCredentials() )
309 {
310 log.info( "Returning url credentials" );
311 return new UsernamePasswordCredentials( getUsername(), pw );
312 }
313
314 log.info( host + ":" + port + " requires authentication with the realm '" + authscheme.getRealm() + "'" );
315 ShowDialog showDialog = new ShowDialog();
316 showDialog.values.put( "Info", "Authentication required for [" + host + ":" + port + "]" );
317
318 UISupport.getUIUtils().runInUIThreadIfSWT( showDialog );
319 if( showDialog.result )
320 {
321 return new UsernamePasswordCredentials( showDialog.values.get( "Username" ), showDialog.values
322 .get( "Password" ) );
323 }
324 else
325 throw new CredentialsNotAvailableException( "Operation cancelled" );
326
327 }
328 else
329 {
330 throw new CredentialsNotAvailableException( "Unsupported authentication scheme: "
331 + authscheme.getSchemeName() );
332 }
333 }
334 catch( IOException e )
335 {
336 throw new CredentialsNotAvailableException( e.getMessage(), e );
337 }
338 }
339
340 private void buildBasicDialog()
341 {
342 XFormDialogBuilder builder = XFormFactory.createDialogBuilder( "Basic Authentication" );
343 XForm mainForm = builder.createForm( "Basic" );
344 mainForm.addLabel( "Info", "" );
345 mainForm.addTextField( "Username", "Username for authentication", XForm.FieldType.TEXT );
346 mainForm.addTextField( "Password", "Password for authentication", XForm.FieldType.PASSWORD );
347
348 basicDialog = builder.buildDialog( builder.buildOkCancelActions(), "Specify Basic Authentication Credentials",
349 UISupport.OPTIONS_ICON );
350 }
351
352 private void buildNtDialog()
353 {
354 XFormDialogBuilder builder = XFormFactory.createDialogBuilder( "NT Authentication" );
355 XForm mainForm = builder.createForm( "Basic" );
356 mainForm.addLabel( "Info", "" );
357 mainForm.addTextField( "Username", "Username for authentication", XForm.FieldType.TEXT );
358 mainForm.addTextField( "Password", "Password for authentication", XForm.FieldType.PASSWORD );
359 mainForm.addTextField( "Domain", "NT Domain for authentication", XForm.FieldType.TEXT );
360
361 ntDialog = builder.buildDialog( builder.buildOkCancelActions(), "Specify NT Authentication Credentials",
362 UISupport.OPTIONS_ICON );
363 }
364
365 private class ShowDialog implements Runnable
366 {
367 StringToStringMap values = new StringToStringMap();
368 boolean result;
369
370 public void run()
371 {
372 if( basicDialog == null )
373 buildBasicDialog();
374
375 basicDialog.setValues( values );
376
377 result = basicDialog.show();
378 if( result )
379 {
380 values = basicDialog.getValues();
381 }
382 }
383 }
384 }
385
386 public void close()
387 {
388 }
389 }