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