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() ));
    331
    332       	namespaces.remove( "http://www.w3.org/2005/05/xmlmime" );
    333       	namespaces.remove( "http://ws-i.org/profiles/basic/1.1/xsd" );
    334       	namespaces.remove( "http://www.w3.org/2004/08/xop/include" );
    335       }
    336
    337       if( definition != null )
    338       	namespaces.add( definition.getTargetNamespace() );
    339
    340       return namespaces;
    341 	}
    342
    343 	public SoapVersion getSoapVersion()
    344 	{
    345 		return soapVersion;
    346 	}
    347
    348 	public void setSoapVersion(SoapVersion soapVersion)
    349 	{
    350 		this.soapVersion = soapVersion;
    351 	}
    352
    353 	public Map<String, XmlObject> getDefinitionParts() throws Exception
    354 	{
    355 		Map<String,XmlObject> result = new HashMap<String,XmlObject>();
    356
    357 		if( cache == null )
    358 			return SchemaUtils.getDefinitionParts( new UrlWsdlLoader( url ));
    359
    360 		List<DefintionPartConfig> partList = cache.getPartList();
    361 		for( DefintionPartConfig part : partList )
    362 		{
    363 			String str = part.getContent().toString();
    364 			result.put( part.getUrl(), XmlObject.Factory.parse( str, new XmlOptions().setLoadLineNumbers() ) );
    365 		}
    366
    367 		return result;
    368 	}
    369
    370 	public void setDefinitionCache(DefinitionCacheConfig definitionCache)
    371 	{
    372 		this.cache = definitionCache;
    373 	}
    374 }