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;
14  
15  import java.util.ArrayList;
16  import java.util.Arrays;
17  import java.util.HashMap;
18  import java.util.HashSet;
19  import java.util.Iterator;
20  import java.util.List;
21  import java.util.Map;
22  import java.util.Set;
23  
24  import javax.wsdl.Binding;
25  import javax.wsdl.BindingOperation;
26  import javax.wsdl.Definition;
27  import javax.wsdl.Port;
28  import javax.wsdl.Service;
29  import javax.xml.namespace.QName;
30  
31  import org.apache.log4j.Logger;
32  
33  import com.eviware.soapui.SoapUI;
34  import com.eviware.soapui.config.DefinitionCacheConfig;
35  import com.eviware.soapui.config.EndpointConfig;
36  import com.eviware.soapui.config.EndpointsConfig;
37  import com.eviware.soapui.config.InterfaceConfig;
38  import com.eviware.soapui.config.OperationConfig;
39  import com.eviware.soapui.config.SoapVersionTypesConfig;
40  import com.eviware.soapui.impl.wsdl.support.soap.SoapMessageBuilder;
41  import com.eviware.soapui.impl.wsdl.support.soap.SoapVersion;
42  import com.eviware.soapui.impl.wsdl.support.wsdl.CachedWsdlLoader;
43  import com.eviware.soapui.impl.wsdl.support.wsdl.UrlWsdlLoader;
44  import com.eviware.soapui.impl.wsdl.support.wsdl.WsdlContext;
45  import com.eviware.soapui.impl.wsdl.support.wsdl.WsdlLoader;
46  import com.eviware.soapui.impl.wsdl.support.wsdl.WsdlUtils;
47  import com.eviware.soapui.model.iface.Interface;
48  import com.eviware.soapui.model.iface.InterfaceListener;
49  import com.eviware.soapui.model.iface.Operation;
50  import com.eviware.soapui.settings.WsdlSettings;
51  import com.eviware.soapui.support.UISupport;
52  import com.eviware.soapui.support.action.swing.DefaultActionList;
53  import com.eviware.soapui.support.types.StringList;
54  
55  /***
56   * WSDL implementation of Interface, maps to a WSDL Binding
57   * 
58   * @author Ole.Matzura
59   */
60  
61  public class WsdlInterface extends AbstractWsdlModelItem<InterfaceConfig> implements Interface
62  {
63  	public static final String STYLE_DOCUMENT = "Document";
64  	public static final String STYLE_RPC = "RPC";
65  
66     public static final String JBOSSWS_ACTIONS = "jbossws";
67     public static final String WSTOOLS_ACTIONS = "wstools";
68     public static final String XML_ACTIONS = "xml";
69  
70  	private final static Logger log = Logger.getLogger( WsdlInterface.class );
71  	
72     private List<WsdlOperation> operations = new ArrayList<WsdlOperation>();
73     private WsdlProject project;
74     private SoapMessageBuilder soapMessageBuilder;
75     private WsdlContext wsdlContext;
76     private Set<InterfaceListener> listeners = new HashSet<InterfaceListener>();
77     private DefaultActionList generateActions;
78     
79     public WsdlInterface( WsdlProject project, InterfaceConfig interfaceConfig )
80     {
81     	super( interfaceConfig, project, "/interface2.gif" );
82     	
83        this.project = project;
84        
85        if( interfaceConfig.getEndpoints() == null )
86           interfaceConfig.addNewEndpoints();
87        
88        List<OperationConfig> operationConfigs = interfaceConfig.getOperationList();
89        for (int i = 0; i < operationConfigs.size(); i++)
90        {
91           operations.add( new WsdlOperation( this, operationConfigs.get(i) ));
92        }
93        
94        buildActions();
95     }
96  
97  	private void buildActions()
98  	{
99  		generateActions = new DefaultActionList( "Generate" );
100 //      generateActions.addAction( new ActionExtensionPoint( this, WSTOOLS_ACTIONS ) );
101 //		generateActions.addAction( new WSToolsWsdl2JavaAction( this ));
102 //		generateActions.addAction( new JBossWSConsumeAction( this ));
103 //      generateActions.addAction( ActionSupport.SEPARATOR_ACTION );
104 //      generateActions.addAction( new ActionExtensionPoint( this, JBOSSWS_ACTIONS ) );
105 //      generateActions.addAction( new WSCompileAction( this ));
106 //      generateActions.addAction( new WSImportAction( this ));
107 //      generateActions.addAction( ActionSupport.SEPARATOR_ACTION );
108 //      generateActions.addAction( new Axis1XWSDL2JavaAction( this ));
109 //      generateActions.addAction( new Axis2WSDL2CodeAction( this ));
110 //      generateActions.addAction( new XFireAction( this ));
111 //      generateActions.addAction( new OracleWsaGenProxyAction( this ));
112 //      generateActions.addAction( ActionSupport.SEPARATOR_ACTION );
113 //      generateActions.addAction( new ActionExtensionPoint( this, XML_ACTIONS ) );
114 //      generateActions.addAction( new JaxbXjcAction( this ));
115 //      generateActions.addAction( new XmlBeans2Action( this ));
116 //      generateActions.addAction( ActionSupport.SEPARATOR_ACTION );
117 //      generateActions.addAction( new DotNetWsdlAction( this ));
118 //      generateActions.addAction( new GSoapAction( this ));
119       
120 //      addAction( new ShowDesktopPanelAction( "Open Interface Viewer", "Opens the Interface Viewer for this Interface", this ));
121 //      addAction( ActionSupport.SEPARATOR_ACTION );
122 //      addAction( new ActionSupport.ActionListAction( generateActions ));
123 //      addAction( new WSToolsRegenerateJava2WsdlAction( this ));
124 //      addAction( ActionSupport.SEPARATOR_ACTION );
125 //      addAction( new WSIAnalyzeAction( this ));
126 //      addAction( new TcpMonAction( this ));
127 //      addAction( ActionSupport.SEPARATOR_ACTION );
128 //      addAction( new GenerateTestSuiteAction( this ));
129 //      addAction( new GenerateMockServiceAction( this ));
130 //      addAction( ActionSupport.SEPARATOR_ACTION );
131 //      addAction( new InterfaceEndpointsAction( this ) );
132 //      addAction( new UpdateInterfaceAction( this ) );
133 //      addAction( new ExportDefinitionAction( this ) );
134 //      addAction( ActionSupport.SEPARATOR_ACTION );
135 //      addAction( new RemoveInterfaceAction( this ) );
136 //      addAction( new ShowOnlineHelpAction( HelpUrls.INTERFACE_HELP_URL ));
137 	}
138 
139    public DefaultActionList getGenerateActions()
140    {
141       return generateActions;
142    }
143 
144 	public String[] getEndpoints()
145    {
146       EndpointsConfig endpoints = getConfig().getEndpoints();
147       List<EndpointConfig> endpointArray = endpoints.getEndpointList();
148       
149       String [] result = new String[endpointArray.size()];
150       
151       for( int c = 0; c < result.length; c++ )
152       {
153       	EndpointConfig endpoint = endpointArray.get(c);
154       	if( endpoint.isSetLabel() )
155       		result[c] = endpoint.getLabel();
156       	else
157       		result[c] = endpoint.getStringValue();
158       }
159       
160 		return result; 
161    }
162 
163    public WsdlOperation getOperationAt(int index)
164    {
165       return operations.get(index);
166    }
167 
168    public int getOperationCount()
169    {
170       return operations.size();
171    }
172 
173    public WsdlOperation addNewOperation(BindingOperation operation)
174    {
175       WsdlOperation operationImpl = new WsdlOperation( this, getConfig().addNewOperation() );
176       operations.add( operationImpl );
177 
178       operationImpl.initFromBindingOperation( operation, false );
179       fireOperationAdded( operationImpl );
180       return operationImpl;
181    }
182 
183    public WsdlProject getProject()
184    {
185       return project;
186    }
187 
188    public void addEndpoint(String endpoint)
189    {
190       if( endpoint == null || endpoint.trim().length() == 0 ) return;
191       
192       endpoint = endpoint.trim();
193       String[] endpoints = getEndpoints();
194       
195       // dont add the same endpoint twice
196       if( Arrays.asList( endpoints ).contains( endpoint )) return;
197       
198       getConfig().getEndpoints().addNewEndpoint().setStringValue(endpoint);
199 		
200 		notifyPropertyChanged(ENDPOINT_PROPERTY, null, endpoint);
201    }
202    
203    public void changeEndpoint(String oldEndpoint, String newEndpoint)
204 	{
205    	if( oldEndpoint == null || oldEndpoint.trim().length() == 0 ) return;
206    	if( newEndpoint == null || newEndpoint.trim().length() == 0 ) return;
207    	
208    	EndpointsConfig endpoints = getConfig().getEndpoints();
209       List<EndpointConfig> endpointArray = endpoints.getEndpointList();
210       
211       String [] result = new String[endpointArray.size()];
212       
213       for( int c = 0; c < result.length; c++ )
214       {
215       	EndpointConfig endpoint = endpointArray.get( c );
216       	if( endpoint.getStringValue().equals( oldEndpoint ) )
217       	{
218       		endpoint.setStringValue( newEndpoint );
219          	notifyPropertyChanged(ENDPOINT_PROPERTY, oldEndpoint, newEndpoint);
220          	break;
221       	}
222       }
223 	}
224 
225 	public void removeEndpoint(String endpoint)
226 	{
227 		EndpointsConfig endpoints = getConfig().getEndpoints();
228       List<EndpointConfig> endpointArray = endpoints.getEndpointList();
229       
230       String [] result = new String[endpointArray.size()];
231       
232       for( int c = 0; c < result.length; c++ )
233       {
234       	EndpointConfig ep = endpointArray.get(c);
235       	if( ep.getStringValue().equals( endpoint ) )
236       	{
237       		endpoints.removeEndpoint( c );
238          	notifyPropertyChanged(ENDPOINT_PROPERTY, endpoint, null );
239          	break;
240       	}
241       }
242 	}
243 
244 	public void setDefinition( String wsdlUrl, boolean cache )
245    {
246       String old = getDefinition();
247       
248       getConfig().setDefinition( wsdlUrl );
249       
250       if( wsdlContext != null )
251       {
252       	wsdlContext.setDefinition( wsdlUrl, getConfig().getDefinitionCache() );
253       	wsdlContext.setSoapVersion( getSoapVersion() );
254       }
255       
256       notifyPropertyChanged( DEFINITION_PROPERTY, old, wsdlUrl );
257    }
258 
259 	public DefinitionCacheConfig cacheDefinition( WsdlLoader loader ) throws Exception
260 	{
261 		log.debug( "Caching definition for [" + loader.getBaseURI() + "]" );
262       if( getConfig().isSetDefinitionCache() )
263       	getConfig().unsetDefinitionCache();
264 
265 		DefinitionCacheConfig definitionCache = getConfig().addNewDefinitionCache();
266 		definitionCache.set( WsdlLoader.cacheWsdl( loader  ) );
267 		return definitionCache;
268 	}
269    
270    public String getDefinition()
271    {
272       return getConfig().isSetDefinition() ? getConfig().getDefinition() : null;
273    }
274    
275    public synchronized WsdlContext getWsdlContext()
276    {
277       if( wsdlContext == null )
278       {
279       	wsdlContext = new WsdlContext( getDefinition(), getSoapVersion(), getConfig().getDefinitionCache(), this );
280       }  
281       
282       return wsdlContext;
283    }
284    
285    /***
286     * Used by importer so we dont need to reload the context after importing..
287     * @param wsdlContext
288     */
289    
290    public void setWsdlContext( WsdlContext wsdlContext )
291    {
292    	this.wsdlContext = wsdlContext;
293    	this.wsdlContext.setSoapVersion( getSoapVersion() );
294    	
295    	if( !getConfig().isSetDefinitionCache() )
296 			getConfig().addNewDefinitionCache();
297    	
298    	if( wsdlContext.getCacheConfig() != null )
299    	{
300    		// use cache from context
301    		getConfig().setDefinitionCache( wsdlContext.getCacheConfig() );
302    	}
303    }
304 
305    public SoapMessageBuilder getMessageBuilder()
306    {
307       if( soapMessageBuilder == null )
308       {
309          try
310          {
311             soapMessageBuilder = new SoapMessageBuilder( this );
312          }
313          catch (Exception e)
314          {
315             SoapUI.logError( e );
316          }
317       }
318       return soapMessageBuilder;
319    }
320 
321    public void setSoapMessageBuilder(SoapMessageBuilder builder)
322    {
323       soapMessageBuilder = builder;
324       soapMessageBuilder.setInterface( this );
325    }
326 
327    public QName getBindingName()
328    {
329       return getConfig().getBindingName() == null ? null : QName.valueOf(getConfig().getBindingName());
330    }
331 
332    public void setBindingName(QName name)
333    {
334    	getConfig().setBindingName( name.toString() );
335    }
336    
337    public SoapVersion getSoapVersion()
338    {
339    	if( getConfig().getSoapVersion() == SoapVersionTypesConfig.X_1_2  )
340    		return SoapVersion.Soap12;
341    	
342    	return SoapVersion.Soap11;
343    }
344    
345    public void setSoapVersion( SoapVersion version )
346    {
347    	if( version == SoapVersion.Soap11 )
348    		getConfig().setSoapVersion( SoapVersionTypesConfig.X_1_1 );
349    	else if( version == SoapVersion.Soap12 )
350    		getConfig().setSoapVersion( SoapVersionTypesConfig.X_1_2 );
351    	else 
352    		throw new RuntimeException( "Unknown soapVersion [" + version + "], must be 1.1 or 1.2");
353    	
354    	getWsdlContext().setSoapVersion( version );
355    }
356 
357 	@SuppressWarnings("unchecked")
358 	public boolean updateDefinition(String url, boolean createRequests) throws Exception
359 	{
360 		WsdlContext newContext = null;
361 		
362 		if( getConfig().isSetDefinitionCache() )
363 			getConfig().unsetDefinitionCache();
364 		
365 		if( !getSettings().getBoolean( WsdlSettings.CACHE_WSDLS ) )
366 		{
367 			newContext = new WsdlContext( url, getSoapVersion(), null, null );
368 		}
369 		else
370 		{
371 			newContext = new WsdlContext( url, getSoapVersion(), null, this );	
372 		}
373 		
374 		if( !newContext.load() )
375 		{
376 			return false;
377 		}
378 		
379 		Definition definition = newContext.getDefinition();
380 		Service service = null;
381 		Port port = null;
382 		Binding binding = null;
383 		
384 		// start by finding the old binding in the new definition
385 		Map serviceMap = definition.getAllServices();
386 		Iterator<String> i = serviceMap.keySet().iterator();
387 		while( i.hasNext() )
388 		{
389 			service = (Service) serviceMap.get( i.next() );
390 			Map portMap = service.getPorts();
391 			
392 			Iterator i2 = portMap.keySet().iterator();
393 			while( i2.hasNext() )
394 			{
395 				port = (Port) portMap.get( i2.next() );
396 				if( port.getBinding().getQName().equals( getBindingName() ))
397 				{
398 					binding = port.getBinding();
399 				}
400 			}
401 			
402 			if( binding != null ) break;
403 			service = null;
404 		}
405 		
406 		if( service == null && binding == null )
407 		{
408 			binding = definition.getBinding( getBindingName() );
409 		}
410 
411 		// missing matching binding, prompt for new one to use instead (will happen if binding has been renamed)
412 		if( binding == null )
413 		{
414 			Map bindings = definition.getAllBindings();
415 			
416 			Object retval = UISupport.prompt(  
417 					"Missing matching binding [" + getBindingName() + "] in definition, select new\nbinding to map to", 
418 					"Map Binding", bindings.keySet().toArray() );
419 			
420 			if( retval == null )
421 				return false;
422 			
423 			binding = (Binding) bindings.get( retval );
424 			setBindingName( binding.getQName() );
425 		}
426 		
427 		// update name
428 		if( getSettings().getBoolean( WsdlSettings.NAME_WITH_BINDING ))
429 			setName( binding.getQName().getLocalPart() );
430 		
431 		// prepare for transfer of operations/requests
432 		List<BindingOperation> newOperations = new ArrayList<BindingOperation>( binding.getBindingOperations() );
433 		Map<String,WsdlOperation> oldOperations = new HashMap<String,WsdlOperation>();
434 		for( int c = 0; c < operations.size(); c++ )
435 			oldOperations.put( operations.get( c ).getBindingOperationName(), operations.get( c ) );
436 		
437 		// clear existing from both collections
438 		for( int c = 0; c < newOperations.size(); c++ )
439 		{
440 			BindingOperation newOperation = newOperations.get( c );
441 			String bindingOperationName = newOperation.getName();
442 			if( oldOperations.containsKey( bindingOperationName) )
443 			{
444 				log.info( "Synchronizing existing operation [" + bindingOperationName + "]" );
445 				WsdlOperation wsdlOperation = oldOperations.get( bindingOperationName );
446 				wsdlOperation.initFromBindingOperation( newOperation, true );
447 				
448 				oldOperations.remove( bindingOperationName );
449 				newOperations.remove( c );
450 				c--;
451 			}
452 		}
453 		
454 		//	remove leftover operations
455 		i = oldOperations.keySet().iterator();
456 		while( i.hasNext())
457 		{
458 			String name = i.next();
459 			
460 			if( newOperations.size() > 0 )
461 		   {
462 				List<String> list = new ArrayList<String>();
463 				list.add( "none - delete operation" );
464 				for( int c = 0; c < newOperations.size(); c++ )
465 					list.add( newOperations.get( c ).getName() );
466 				
467 				String retval = (String) UISupport.prompt( 
468 						"Binding operation [" + name + "] not found in new interface, select new\nbinding operation to map to", 
469 						"Map Operation", list.toArray(), "none - delete operation" );
470 				
471 				if( retval == null )
472 				{
473 				   UISupport.showErrorMessage( "Aborting update of interface" );
474 				   return false;
475 				}
476 				
477 				int ix = list.indexOf( retval)-1;
478 				
479 				// delete operation?
480 				if( ix < 0 )
481 				{
482 					deleteOperation( name );
483 				}
484 				// change operation?
485 				else
486 				{
487 					BindingOperation newOperation = newOperations.get( ix );
488 					WsdlOperation wsdlOperation = oldOperations.get( name );
489 					wsdlOperation.initFromBindingOperation( newOperation, true );
490 					newOperations.remove( ix );
491 				}
492 
493 				oldOperations.remove( name );
494 		   }
495 			else 
496 			{
497 				deleteOperation( name );
498 				oldOperations.remove( name );
499 			}
500 			
501 			i = oldOperations.keySet().iterator();
502 		}
503 		
504 		wsdlContext = newContext;
505 		if( soapMessageBuilder != null )
506 			soapMessageBuilder.setWsdlContext( wsdlContext );
507 		
508 		// add leftover new operations
509 		if( newOperations.size() > 0 )
510 		{
511 			for( int c = 0; c < newOperations.size(); c++ )
512 			{
513 				BindingOperation newOperation = newOperations.get( c );
514 				WsdlOperation wsdlOperation = addNewOperation( newOperation );
515 				
516 				if( createRequests )
517 				{
518 					WsdlRequest request = wsdlOperation.addNewRequest( "Request 1");
519                try
520                {
521                   request.setRequestContent( wsdlOperation.createRequest( true ));
522                }
523                catch (Exception e)
524                {
525                   SoapUI.logError( e );
526                }
527 				}
528 			}
529 		}
530 		
531     	setDefinition( url, false );
532 
533 		if( port != null )
534 		{
535 			String endpoint = WsdlUtils.getSoapEndpoint( port );
536 	      if( endpoint != null )
537 	      {
538 	      	StringList list = new StringList( getEndpoints() );
539 	      	if( !list.contains( endpoint ))
540 	      	{
541 	      		if( UISupport.confirm( "Update existing requests with new endpoint\n[" + endpoint + "]", "Update Definition" ))
542 	      		{
543 	      			for( int c = 0; c < getOperationCount(); c++ )
544 	               {
545 	               	Operation operation = getOperationAt( c );
546 
547 	               	for( int ix = 0; ix < operation.getRequestCount(); ix++ )
548 	               	{
549 	               		operation.getRequestAt( ix ).setEndpoint( endpoint );
550 	               	}
551 	               }
552 	      		}
553 
554 	      		getConfig().getEndpoints().insertNewEndpoint( 0 ).setStringValue(endpoint);
555 		   		notifyPropertyChanged(ENDPOINT_PROPERTY, null, endpoint);
556 	      	}
557 	      }
558 		}
559 		
560 		return true;
561 	}
562 
563 	private void deleteOperation(String bindingOperationName)
564 	{
565 		for( int c = 0; c < operations.size(); c++ )
566 		{
567 			WsdlOperation wsdlOperation = operations.get( c );
568 			if( wsdlOperation.getBindingOperationName().equals( bindingOperationName ))
569 			{
570 				log.info( "deleting operation [" + bindingOperationName + "]" );
571 				
572 				// remove requests first (should this be done by some listener?)
573 				while( wsdlOperation.getRequestCount() > 0 )
574 					wsdlOperation.removeRequest( (WsdlRequest) wsdlOperation.getRequestAt( 0 ));
575 				
576 				operations.remove( c );
577 
578 				try
579 				{
580 					fireOperationRemoved( wsdlOperation );
581 				}
582 				finally
583 				{
584 					wsdlOperation.release();
585 					getConfig().removeOperation( c );
586 				}
587 				
588 				return;
589 			}
590 		}
591 	}
592 	
593 	public void fireOperationAdded( WsdlOperation operation )
594    {
595       InterfaceListener[] a = listeners.toArray( new InterfaceListener[listeners.size()] );
596       
597       for (int c = 0; c < a.length; c++ )
598       {
599          a[c].operationAdded( operation );
600       }
601    }
602 	
603 	public void fireOperationUpdated( WsdlOperation operation )
604    {
605       InterfaceListener[] a = listeners.toArray( new InterfaceListener[listeners.size()] );
606       
607       for (int c = 0; c < a.length; c++ )
608       {
609          a[c].operationUpdated( operation );
610       }
611    }
612    
613    public void fireOperationRemoved( WsdlOperation operation )
614    {
615    	InterfaceListener[] a = listeners.toArray( new InterfaceListener[listeners.size()] );
616       
617       for (int c = 0; c < a.length; c++ )
618       {
619          a[c].operationRemoved( operation );
620       }
621    }
622    
623    public void fireRequestAdded( WsdlRequest request )
624    {
625    	InterfaceListener[] a = listeners.toArray( new InterfaceListener[listeners.size()] );
626       
627       for (int c = 0; c < a.length; c++ )
628       {
629          a[c].requestAdded( request );
630       }
631    }
632    
633    public void fireRequestRemoved( WsdlRequest request )
634    {
635    	InterfaceListener[] a = listeners.toArray( new InterfaceListener[listeners.size()] );
636       
637       for (int c = 0; c < a.length; c++ )
638       {
639          a[c].requestRemoved( request );
640       }
641    }
642 
643 	public void addInterfaceListener(InterfaceListener listener)
644 	{
645 		listeners.add( listener );
646 	}
647 
648 	public void removeInterfaceListener(InterfaceListener listener)
649 	{
650 		listeners.remove( listener );
651 	}
652 
653 	/***
654 	 * Gets the endpoint url for the specified endpoint (which may be a label)
655 	 * 
656 	 * @param endpoint the endpoint to get for
657 	 * @return the endpoints url
658 	 */
659 	
660 	public String getEndpointURL(String endpoint)
661 	{
662 		List<EndpointConfig> endpointArray = getConfig().getEndpoints().getEndpointList();
663 		for( EndpointConfig endpointConfig : endpointArray )
664 		{
665 			if( endpointConfig.isSetLabel() && endpointConfig.getLabel().equals( endpoint ))
666 				return endpointConfig.getStringValue();
667 		}
668 		
669 		return endpoint;
670 	}
671 
672 	public WsdlOperation getOperationByName(String name)
673 	{
674 		return (WsdlOperation) getWsdlModelItemByName( operations, name );
675 	}
676 	
677 	public boolean isCached()
678 	{
679 		return getConfig().isSetDefinitionCache();
680 	}
681 
682 	public WsdlLoader createWsdlLoader()
683 	{
684 		return isCached() ? new CachedWsdlLoader( getConfig().getDefinitionCache() ) : 
685 			new UrlWsdlLoader( getDefinition() );
686 	}
687 	
688 	public void clearCache()
689 	{
690 		if( wsdlContext != null )
691 			wsdlContext.setDefinitionCache( null );
692 		
693 		if( getConfig().isSetDefinitionCache() )
694 			getConfig().unsetDefinitionCache();
695 	}
696 	
697 	public String getStyle()
698 	{
699 		if( wsdlContext == null || !wsdlContext.isLoaded() )
700 			return "<not loaded>";
701 		
702 		try
703 		{
704 			Binding binding = wsdlContext.getDefinition().getBinding( getBindingName() );
705 			if( binding == null )
706 				return "<missing binding>";
707 			
708 			if( WsdlUtils.isRpc( binding))
709 			{
710 				return STYLE_RPC;
711 			}
712 			else
713 			{
714 				return STYLE_DOCUMENT;
715 			}
716 		}
717 		catch (Exception e)
718 		{
719 			SoapUI.logError( e );
720 			return "<error>";
721 		}
722 	}
723 
724 	public void release()
725 	{
726 		super.release();
727 		
728 		for( WsdlOperation operation : operations )
729 			operation.release();
730 	}
731 
732 	public List<Operation> getOperations()
733 	{
734 		return new ArrayList<Operation>( operations );
735 	}
736 
737 	@Override
738 	public void onSave()
739 	{
740 		for( WsdlOperation operation : operations )
741 			operation.onSave();
742 	}
743 }