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 boolean isLoaded()
94     {
95     	return loaded;
96     }
97     
98     public synchronized boolean loadIfNecessary() throws Exception
99     {
100    	if( !loaded )
101          load();
102    	return loaded;
103    }
104    
105    public synchronized void setDefinition( String url, DefinitionCacheConfig cache ) 
106    {
107    	this.url = url;
108 		this.cache = null;
109    	loaded = false;
110    }
111      
112    public synchronized boolean load() throws Exception
113    {
114    	return load( null );
115    }
116    
117    public synchronized boolean load( WsdlLoader wsdlLoader ) throws Exception
118    {
119    	if( loaded )
120    		return true;
121    	
122       XProgressDialog progressDialog;
123       if( url.startsWith("file:") )
124       {
125          progressDialog = new NullProgressDialog();
126       }
127       else
128       {
129          progressDialog = UISupport.getDialogs().createProgressDialog(
130                "Loading WSDL", 3, "Loading definition..", true );
131       }
132       
133    	Loader loader = new Loader( wsdlLoader );
134       progressDialog.run( loader);
135       
136       // Get the value. It is the responsibility of the progressDialog to
137       // wait for the other thread to finish.
138       if( loader.hasError() )
139       {
140          if( loader.getError() instanceof SchemaException )
141          {
142          	schemaException = (SchemaException) loader.getError();
143          	ArrayList errorList = schemaException.getErrorList();
144          	
145          	if( errorList != null )
146          	{
147 	         	log.error( "Error loading schema types from " + url + ", see log for details" );
148 	         	for( int c = 0; c < errorList.size(); c++ )
149 	         	{
150 	         		log.error( errorList.get( c ).toString() );
151 	         	}
152          	}
153          	
154          	UISupport.showErrorMessage( "Error loading schema types from " + url + ", see log for details" );
155          }
156          else throw loader.getError();
157       }
158       else loaded = true;
159       
160       return loaded;
161    }
162 
163    public SchemaTypeLoader getSchemaTypeLoader() throws Exception
164    {
165       loadIfNecessary();
166       return schemaTypes;
167    }
168    
169    public SchemaException getSchemaException()
170    {
171    	return schemaException;
172    }
173 
174    private class Loader extends Worker.WorkerAdapter
175    {
176       private Exception error;
177       private WsdlLoader wsdlLoader;
178 
179       public Loader(WsdlLoader wsdlLoader) 
180       {
181           super();
182           this.wsdlLoader = wsdlLoader;
183       }
184 
185       private WsdlLoader getWsdlLoader() 
186       {
187           if(wsdlLoader != null) {
188               return wsdlLoader;
189           } else {
190               return new UrlWsdlLoader( url );
191           }
192       }
193       
194       public boolean hasError()
195 		{
196 			return error != null;
197 		}
198 
199 		public Object construct(XProgressMonitor monitor)
200       {
201       	try
202       	{
203 				if( !validateCache( cache ) )
204 				{
205 				   monitor.setProgress( 1, "Caching definition from url [" + url + "]" ); 
206 				   
207 				   currentLoader = getWsdlLoader();
208 				   cache = iface == null ? WsdlLoader.cacheWsdl( currentLoader ) : 
209 				   		iface.cacheDefinition( currentLoader );
210 				   
211 				   if( currentLoader.isAborted() )
212 				   	throw new Exception( "Loading of WSDL from [" + url + "] was aborted" );
213 				}
214       		 
215             monitor.setProgress( 1, "Loading definition from " + (cache == null ? "url" : "cache") );
216             
217             log.debug( "Loading definition from " + (cache == null ? "url" : "cache") );
218             currentLoader = cache == null ? getWsdlLoader() : new CachedWsdlLoader( cache );
219 				loadDefinitions( currentLoader);
220             return null;
221          }
222          catch (Exception e)
223          {
224          	log.error( "Loading of definition failed for [" + url + "]; " + e );
225          	SoapUI.logError( e );
226             this.error = e;
227             return e;
228          }
229          finally
230          {
231             currentLoader = null;
232          }
233       }
234       
235       public Exception getError()
236       {
237          return error;
238       }
239       
240    	public boolean onCancel()
241    	{
242    		if( currentLoader == null )
243    			return false;
244 
245    		return currentLoader.abort();
246    	}
247    }
248 
249    private void loadDefinitions( WsdlLoader loader ) throws Exception
250    {
251    	currentLoader = loader;
252    	
253    	if( factory == null )
254    	{
255 	      factory = WSDLFactory.newInstance();
256 			wsdlReader = factory.newWSDLReader();
257 			wsdlReader.setFeature("javax.wsdl.verbose", true);
258 	      wsdlReader.setFeature("javax.wsdl.importDocuments", true);
259    	}
260 
261       definition = wsdlReader.readWSDL( loader );
262       log.debug( "Loaded definition: " + (definition != null ? "ok" : "null") );
263 
264       if( !currentLoader.isAborted() )
265       	schemaTypes = SchemaUtils.loadSchemaTypes(url, soapVersion, loader);
266       else 
267       	throw new Exception( "Loading of WSDL from [" + url + "] was aborted" );
268    }
269    
270 	public boolean validateCache(DefinitionCacheConfig cache)
271 	{
272 		if( cache == null )
273 			return false;
274 		
275 		if( cache.getRootPart() == null )
276 			return false;
277 		
278 		if( cache.sizeOfPartArray() == 0 )
279 			return false;
280 		
281 		return true;
282 	}
283 
284 	public SchemaTypeSystem getSchemaTypeSystem() throws Exception
285 	{
286       if( !loaded )
287          load();
288 		
289 		if( schemaTypes == null )
290 			return null;
291 		
292 		return schemaTypes.findElement( soapVersion.getEnvelopeQName() ).getTypeSystem();
293 	}
294    
295    public boolean hasSchemaTypes() throws Exception
296    {
297       loadIfNecessary();
298       return schemaTypes != null;
299    }
300 
301    public SchemaType findType(QName typeName) throws Exception
302    {
303       loadIfNecessary();
304       return schemaTypes == null ? null : schemaTypes.findType( typeName );
305    }
306 
307    public String getUrl()
308    {
309       return url;
310    }
311 
312 	public Collection<String> getDefinedNamespaces() throws Exception
313 	{
314       loadIfNecessary();
315       Set<String> namespaces = new HashSet<String>();
316       
317       if( schemaTypes != null )
318       {
319       	namespaces.addAll( SchemaUtils.extractNamespaces( getSchemaTypeSystem(), true ));
320       }
321       
322       if( definition != null )
323       	namespaces.add( definition.getTargetNamespace() );
324       
325       return namespaces;
326 	}
327 
328 	public SoapVersion getSoapVersion()
329 	{
330 		return soapVersion;
331 	}
332 
333 	public void setSoapVersion(SoapVersion soapVersion)
334 	{
335 		this.soapVersion = soapVersion;
336 	}
337 
338 	public Map<String, XmlObject> getDefinitionParts() throws Exception
339 	{
340 		Map<String,XmlObject> result = new HashMap<String,XmlObject>();
341 		
342 		if( cache == null )
343 			return SchemaUtils.getDefinitionParts( new UrlWsdlLoader( url ));
344 		
345 		List<DefintionPartConfig> partList = cache.getPartList();
346 		for( DefintionPartConfig part : partList )
347 		{
348 			result.put( part.getUrl(), CachedWsdlLoader.getPartContent( cache, part ) );
349 		}
350 		
351 		return result;
352 	}
353 
354 	public void setDefinitionCache(DefinitionCacheConfig definitionCache)
355 	{
356 		this.cache = definitionCache;
357 	}
358 
359 	public void setInterface( WsdlInterface iface )
360 	{
361 		this.iface = iface;
362 	}
363 }