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.util.ArrayList;
16  import java.util.Collection;
17  import java.util.HashMap;
18  import java.util.HashSet;
19  import java.util.List;
20  import java.util.Map;
21  import java.util.Set;
22  
23  import javax.wsdl.Definition;
24  import javax.wsdl.factory.WSDLFactory;
25  import javax.wsdl.xml.WSDLReader;
26  import javax.xml.namespace.QName;
27  
28  import org.apache.log4j.Logger;
29  import org.apache.xmlbeans.SchemaType;
30  import org.apache.xmlbeans.SchemaTypeLoader;
31  import org.apache.xmlbeans.SchemaTypeSystem;
32  import org.apache.xmlbeans.XmlObject;
33  
34  import com.eviware.soapui.SoapUI;
35  import com.eviware.soapui.config.DefinitionCacheConfig;
36  import com.eviware.soapui.config.DefintionPartConfig;
37  import com.eviware.soapui.impl.wsdl.WsdlInterface;
38  import com.eviware.soapui.impl.wsdl.support.soap.SoapVersion;
39  import com.eviware.soapui.impl.wsdl.support.xsd.SchemaException;
40  import com.eviware.soapui.impl.wsdl.support.xsd.SchemaUtils;
41  import com.eviware.soapui.support.NullProgressDialog;
42  import com.eviware.soapui.support.UISupport;
43  import com.eviware.x.dialogs.Worker;
44  import com.eviware.x.dialogs.XProgressDialog;
45  import com.eviware.x.dialogs.XProgressMonitor;
46  
47  /***
48   * Holder for WSDL4J Definitions and related SchemaTypeLoader types
49   * 
50   * @author Ole.Matzura
51   */
52  
53  public class WsdlContext 
54  {
55     private String url;
56     private Definition definition;
57     private SchemaTypeLoader schemaTypes;
58     private boolean loaded;
59  	private SchemaException schemaException;
60  	
61  	private final static Logger log = Logger.getLogger( WsdlContext.class );
62  	private SoapVersion soapVersion;
63  	private DefinitionCacheConfig cache;
64  	private WsdlLoader currentLoader;
65  	private WsdlInterface iface;
66  	private WSDLFactory factory;
67  	private WSDLReader wsdlReader;
68  
69     public WsdlContext( String url, SoapVersion soapVersion, DefinitionCacheConfig cache, WsdlInterface iface )
70     {
71     	this.url = url;
72  		this.soapVersion = soapVersion;
73  		this.cache = cache;
74  		this.iface = iface;
75     }
76     
77     public WsdlInterface getInterface()
78  	{
79  		return iface;
80  	}
81  
82  	public DefinitionCacheConfig getCacheConfig()
83     {
84     	return cache;
85     }
86     
87     public Definition getDefinition() throws Exception
88     {
89        loadIfNecessary();
90        return definition;
91     }
92     
93     public Definition getDefinitionSilently() throws Exception
94     {
95        if( load(true) )
96        {
97           return getDefinition();
98        }
99        else
100       {
101          return null;
102       }
103    }
104    
105    public boolean isLoaded()
106    {
107    	return loaded;
108    }
109    
110    public synchronized boolean loadIfNecessary() throws Exception
111    {
112    	return loadIfNecessary( false );
113    }
114    
115    public synchronized boolean loadIfNecessary( boolean silent ) throws Exception
116    {
117    	if( !loaded )
118          load( silent );
119    	
120    	return loaded;
121    }
122    
123    public synchronized void setDefinition( String url, DefinitionCacheConfig cache ) 
124    {
125    	this.url = url;
126 		this.cache = null;
127    	loaded = false;
128    }
129      
130    public synchronized boolean load() throws Exception
131    {
132    	return load( null, false );
133    }
134    
135    public synchronized boolean load(boolean silent) throws Exception
136    {
137    	return load( null, silent );
138    }
139    
140    public synchronized boolean load( WsdlLoader wsdlLoader ) throws Exception
141    {
142    	return load( wsdlLoader, false );
143    }
144    
145    public synchronized boolean load( WsdlLoader wsdlLoader, boolean silent ) throws Exception
146    {
147    	if( loaded )
148    		return true;
149    	
150       XProgressDialog progressDialog;
151       if( silent || url.startsWith("file:") )
152       {
153          progressDialog = new NullProgressDialog();
154       }
155       else
156       {
157          progressDialog = UISupport.getDialogs().createProgressDialog(
158                "Loading WSDL", 3, "Loading definition..", true );
159       }
160       
161    	Loader loader = new Loader( wsdlLoader );
162       progressDialog.run( loader);
163       
164       // Get the value. It is the responsibility of the progressDialog to
165       // wait for the other thread to finish.
166       if( loader.hasError() )
167       {
168          if( loader.getError() instanceof SchemaException )
169          {
170          	schemaException = (SchemaException) loader.getError();
171          	ArrayList errorList = schemaException.getErrorList();
172          	
173          	if( errorList != null )
174          	{
175 	         	log.error( "Error loading schema types from " + url + ", see log for details" );
176 	         	for( int c = 0; c < errorList.size(); c++ )
177 	         	{
178 	         		log.error( errorList.get( c ).toString() );
179 	         	}
180          	}
181          	
182          	if(!silent)
183         			UISupport.showErrorMessage( "Error loading schema types from " + url + ", see log for details" );
184          }
185          else throw loader.getError();
186       }
187       else loaded = true;
188       
189       return loaded;
190    }
191 
192    public SchemaTypeLoader getSchemaTypeLoader() throws Exception
193    {
194       loadIfNecessary();
195       return schemaTypes;
196    }
197    
198    public SchemaException getSchemaException()
199    {
200    	return schemaException;
201    }
202 
203    private class Loader extends Worker.WorkerAdapter
204    {
205       private Exception error;
206       private WsdlLoader wsdlLoader;
207 
208       public Loader(WsdlLoader wsdlLoader) 
209       {
210           super();
211           this.wsdlLoader = wsdlLoader;
212       }
213 
214       private WsdlLoader getWsdlLoader() 
215       {
216           if(wsdlLoader != null) {
217               return wsdlLoader;
218           } else {
219               return new UrlWsdlLoader( url );
220           }
221       }
222       
223       public boolean hasError()
224 		{
225 			return error != null;
226 		}
227 
228 		public Object construct(XProgressMonitor monitor)
229       {
230       	try
231       	{
232 				if( !validateCache( cache ) )
233 				{
234 				   monitor.setProgress( 1, "Caching definition from url [" + url + "]" ); 
235 				   
236 				   currentLoader = getWsdlLoader();
237 				   cache = iface == null ? WsdlLoader.cacheWsdl( currentLoader ) : 
238 				   		iface.cacheDefinition( currentLoader );
239 				   
240 				   if( currentLoader.isAborted() )
241 				   	throw new Exception( "Loading of WSDL from [" + url + "] was aborted" );
242 				}
243       		 
244             monitor.setProgress( 1, "Loading definition from " + (cache == null ? "url" : "cache") );
245             
246             log.debug( "Loading definition from " + (cache == null ? "url" : "cache") );
247             loadDefinitions( cache == null ? getWsdlLoader() : new CachedWsdlLoader( cache ));
248             return null;
249          }
250          catch (Exception e)
251          {
252          	log.error( "Loading of definition failed for [" + url + "]; " + e );
253          	SoapUI.logError( e );
254             this.error = e;
255             return e;
256          }
257          finally
258          {
259             currentLoader = null;
260          }
261       }
262       
263       public Exception getError()
264       {
265          return error;
266       }
267       
268    	public boolean onCancel()
269    	{
270    		if( currentLoader == null )
271    			return false;
272 
273    		return currentLoader.abort();
274    	}
275    }
276 
277    private void loadDefinitions( WsdlLoader loader ) throws Exception
278    {
279    	currentLoader = loader;
280    	
281    	if( factory == null )
282    	{
283 	      factory = WSDLFactory.newInstance();
284 			wsdlReader = factory.newWSDLReader();
285 			wsdlReader.setFeature("javax.wsdl.verbose", true);
286 	      wsdlReader.setFeature("javax.wsdl.importDocuments", true);
287    	}
288 
289       definition = wsdlReader.readWSDL( loader );
290       log.debug( "Loaded definition: " + (definition != null ? "ok" : "null") );
291 
292       if( !currentLoader.isAborted() )
293       	schemaTypes = SchemaUtils.loadSchemaTypes(url, soapVersion, loader);
294       else 
295       	throw new Exception( "Loading of WSDL from [" + url + "] was aborted" );
296    }
297    
298 	public boolean validateCache(DefinitionCacheConfig cache)
299 	{
300 		if( cache == null )
301 			return false;
302 		
303 		if( cache.getRootPart() == null )
304 			return false;
305 		
306 		if( cache.sizeOfPartArray() == 0 )
307 			return false;
308 		
309 		return true;
310 	}
311 
312 	public SchemaTypeSystem getSchemaTypeSystem() throws Exception
313 	{
314       if( !loaded )
315          load();
316 		
317 		if( schemaTypes == null )
318 			return null;
319 		
320 		return schemaTypes.findElement( soapVersion.getEnvelopeQName() ).getTypeSystem();
321 	}
322    
323    public boolean hasSchemaTypes() throws Exception
324    {
325       loadIfNecessary();
326       return schemaTypes != null;
327    }
328 
329    public SchemaType findType(QName typeName) throws Exception
330    {
331       loadIfNecessary();
332       return schemaTypes == null ? null : schemaTypes.findType( typeName );
333    }
334 
335    public String getUrl()
336    {
337       return url;
338    }
339 
340 	public Collection<String> getDefinedNamespaces() throws Exception
341 	{
342       loadIfNecessary();
343       Set<String> namespaces = new HashSet<String>();
344       
345       if( schemaTypes != null )
346       {
347       	namespaces.addAll( SchemaUtils.extractNamespaces( getSchemaTypeSystem(), true ));
348       }
349       
350       if( definition != null )
351       	namespaces.add( definition.getTargetNamespace() );
352       
353       return namespaces;
354 	}
355 
356 	public SoapVersion getSoapVersion()
357 	{
358 		return soapVersion;
359 	}
360 
361 	public void setSoapVersion(SoapVersion soapVersion)
362 	{
363 		this.soapVersion = soapVersion;
364 	}
365 
366 	public Map<String, XmlObject> getDefinitionParts() throws Exception
367 	{
368 		Map<String,XmlObject> result = new HashMap<String,XmlObject>();
369 		
370 		if( cache == null )
371 			return SchemaUtils.getDefinitionParts( new UrlWsdlLoader( url ));
372 		
373 		List<DefintionPartConfig> partList = cache.getPartList();
374 		for( DefintionPartConfig part : partList )
375 		{
376 			result.put( part.getUrl(), CachedWsdlLoader.getPartContent( cache, part ) );
377 		}
378 		
379 		return result;
380 	}
381 
382 	public void setDefinitionCache(DefinitionCacheConfig definitionCache)
383 	{
384 		this.cache = definitionCache;
385 	}
386 
387 	public void setInterface( WsdlInterface iface )
388 	{
389 		this.iface = iface;
390 	}
391 }