View Javadoc

1   /*
2    *  soapui, copyright (C) 2005 Ole Matzura / eviware.com 
3    *
4    *  SoapUI is free software; you can redistribute it and/or modify it under the 
5    *  terms of the GNU Lesser General Public License as published by the Free Software Foundation; 
6    *  either version 2.1 of the License, or (at your option) any later version.
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.swing.ImageIcon;
25  import javax.swing.JOptionPane;
26  import javax.wsdl.Binding;
27  import javax.wsdl.BindingOperation;
28  import javax.wsdl.Definition;
29  import javax.wsdl.Port;
30  import javax.wsdl.Service;
31  import javax.wsdl.extensions.soap.SOAPAddress;
32  import javax.xml.namespace.QName;
33  
34  import org.apache.log4j.Logger;
35  
36  import com.eviware.soapui.SoapUI;
37  import com.eviware.soapui.config.InterfaceConfig;
38  import com.eviware.soapui.config.OperationConfig;
39  import com.eviware.soapui.impl.wsdl.actions.iface.InterfaceEndpointsAction;
40  import com.eviware.soapui.impl.wsdl.actions.iface.RemoveInterfaceAction;
41  import com.eviware.soapui.impl.wsdl.actions.iface.UpdateInterfaceAction;
42  import com.eviware.soapui.impl.wsdl.panels.iface.WsdlInterfacePanelBuilder;
43  import com.eviware.soapui.impl.wsdl.support.SoapRequestBuilder;
44  import com.eviware.soapui.impl.wsdl.support.WsdlContext;
45  import com.eviware.soapui.impl.wsdl.support.WsdlUtils;
46  import com.eviware.soapui.model.PanelBuilder;
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.model.iface.RequestBuilder;
51  import com.eviware.soapui.model.project.Project;
52  import com.eviware.soapui.model.tree.SoapUITreeNode;
53  import com.eviware.soapui.model.tree.nodes.InterfaceTreeNode;
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 implements Interface
62  {
63  	private final static Logger log = Logger.getLogger( WsdlInterface.class );
64  	
65     private InterfaceConfig interfaceConfig;
66     private List<WsdlOperation> operations = new ArrayList<WsdlOperation>();
67     private final WsdlProject project;
68     private SoapRequestBuilder soapRequestBuilder;
69     private WsdlInterfacePanelBuilder wsdlInterfacePanelBuilder;
70     private WsdlContext wsdlContext;
71     private ImageIcon interfaceIcon;
72     private Set<InterfaceListener> listeners = new HashSet<InterfaceListener>();
73     
74     public WsdlInterface( WsdlProject project, InterfaceConfig interfaceConfig )
75     {
76        this.project = project;
77        this.interfaceConfig = interfaceConfig;
78        
79        if( interfaceConfig.getEndpoints() == null )
80           interfaceConfig.addNewEndpoints();
81        
82        OperationConfig [] operationConfigs = interfaceConfig.getOperationArray();
83        for (int i = 0; i < operationConfigs.length; i++)
84        {
85           operations.add( new WsdlOperation( this, operationConfigs[i] ));
86        }
87        
88        addAction( new InterfaceEndpointsAction( this ) );
89        addAction( new UpdateInterfaceAction( this ) );
90        addAction( new RemoveInterfaceAction( this ) );
91        
92        wsdlInterfacePanelBuilder = new WsdlInterfacePanelBuilder( this );
93        interfaceIcon = SoapUI.createImageIcon("/interface.gif");
94     }
95     
96     public PanelBuilder getPanelBuilder()
97     {
98        return wsdlInterfacePanelBuilder;
99     }
100    
101    public String[] getEndpoints()
102    {
103       return interfaceConfig.getEndpoints().getEndpointArray();
104    }
105 
106    public Operation getOperationAt(int index)
107    {
108       return operations.get(index);
109    }
110 
111    public int getOperationCount()
112    {
113       return operations.size();
114    }
115 
116    public String getName()
117    {
118       try
119       {
120          return interfaceConfig.getName();
121       }
122       catch( Exception e )
123       {
124          return null;
125       }
126    }
127    
128    public void setName( String name )
129    {
130       String oldName = getName();
131       interfaceConfig.setName( name );
132       notifyPropertyChanged( NAME_PROPERTY, oldName, name );
133    }
134 
135    public InterfaceConfig getInterfaceConfig()
136    {
137       return interfaceConfig;
138    }
139 
140    public WsdlOperation addNewOperation()
141    {
142       WsdlOperation operationImpl = new WsdlOperation( this, interfaceConfig.addNewOperation() );
143       operations.add( operationImpl );
144       return operationImpl;
145    }
146 
147    public Project getProject()
148    {
149       return project;
150    }
151 
152    public void addEndpoint(String endpoint)
153    {
154       if( endpoint == null || endpoint.trim().length() == 0 ) return;
155       
156       List l = Arrays.asList( interfaceConfig.getEndpoints().getEndpointArray() );
157       if( !l.contains( endpoint ))
158       { 
159          String [] endpoints = getEndpoints();
160          interfaceConfig.getEndpoints().addEndpoint( endpoint );
161          notifyPropertyChanged( ENDPOINTS_PROPERTY, endpoints, getEndpoints() );
162       }
163    }
164    
165    public void setDefinition( String wsdlUrl )
166    {
167       String old = getDefinition();
168       if( old != null && wsdlUrl.equals(old)) return;
169       
170       interfaceConfig.setDefinition( wsdlUrl );
171       if( wsdlContext != null )
172       	wsdlContext.setDefinition( wsdlUrl );
173       
174       notifyPropertyChanged( DEFINITION_PROPERTY, old, wsdlUrl );
175    }
176    
177    public String getDefinition()
178    {
179       try
180       {
181          return interfaceConfig.isSetDefinition() ? interfaceConfig.getDefinition() : null;
182       }
183       catch( Exception e )
184       {
185          return null;
186       }
187    }
188    
189    public WsdlContext getWsdlContext()
190    {
191       if( wsdlContext == null )
192          wsdlContext = new WsdlContext( getDefinition() );
193       
194       return wsdlContext;
195    }
196 
197    public void clearEndpoints()
198    {
199       String [] endpoints = getEndpoints();
200       interfaceConfig.getEndpoints().setEndpointArray( new String[] {} );
201       notifyPropertyChanged( ENDPOINTS_PROPERTY, endpoints, getEndpoints() );
202    }
203 
204    public RequestBuilder getRequestBuilder()
205    {
206       if( soapRequestBuilder == null )
207       {
208          try
209          {
210             soapRequestBuilder = new SoapRequestBuilder( this );
211          }
212          catch (Exception e)
213          {
214             e.printStackTrace();
215          }
216       }
217       return soapRequestBuilder;
218    }
219 
220    public void setSoapRequestBuilder(SoapRequestBuilder builder)
221    {
222       this.soapRequestBuilder = builder;
223    }
224 
225    public QName getBindingName()
226    {
227       return interfaceConfig.getBindingName() == null ? null : QName.valueOf(interfaceConfig.getBindingName());
228    }
229 
230    public void setBindingName(QName name)
231    {
232       interfaceConfig.setBindingName( name.toString() );
233    }
234 
235    public ImageIcon getIcon()
236    {
237       return interfaceIcon;
238    }
239 
240    protected SoapUITreeNode createTreeNode()
241    {
242       return new InterfaceTreeNode( this );
243    }
244 
245 	public void updateDefinition(String url) throws Exception
246 	{
247 		WsdlContext newContext = new WsdlContext( url );
248 		
249 		Definition definition = newContext.getDefinition();
250 		Service service = null;
251 		Port port = null;
252 		Binding binding = null;
253 		
254 		Map serviceMap = definition.getServices();
255 		Iterator<String> i = serviceMap.keySet().iterator();
256 		while( i.hasNext() )
257 		{
258 			service = (Service) serviceMap.get( i.next() );
259 			Map portMap = service.getPorts();
260 			
261 			Iterator i2 = portMap.keySet().iterator();
262 			while( i2.hasNext() )
263 			{
264 				port = (Port) portMap.get( i2.next() );
265 				if( port.getBinding().getQName().equals( getBindingName() ))
266 				{
267 					binding = port.getBinding();
268 				}
269 			}
270 			
271 			if( binding != null ) break;
272 			service = null;
273 		}
274 		
275 		if( service == null && binding == null )
276 		{
277 			binding = definition.getBinding( getBindingName() );
278 		}
279 		
280 		if( binding == null )
281 		{
282 			JOptionPane.showMessageDialog( SoapUI.getInstance().getFrame(), "Missing matching binding [" + 
283 					getBindingName() + "] in definition" );
284 			return;
285 		}
286 		
287 		List<BindingOperation> newOperations = new ArrayList<BindingOperation>( binding.getBindingOperations() );
288 		Map<String,WsdlOperation> oldOperations = new HashMap<String,WsdlOperation>();
289 		for( int c = 0; c < operations.size(); c++ )
290 			oldOperations.put( operations.get( c ).getBindingOperationName(), operations.get( c ) );
291 		
292 		// clear existing from both collections
293 		for( int c = 0; c < newOperations.size(); c++ )
294 		{
295 			BindingOperation newOperation = newOperations.get( c );
296 			String bindingOperationName = newOperation.getName();
297 			if( oldOperations.containsKey( bindingOperationName) )
298 			{
299 				log.info( "Synchronizing existing operation [" + bindingOperationName + "]" );
300 				WsdlOperation wsdlOperation = oldOperations.get( bindingOperationName );
301 				wsdlOperation.setAction( WsdlUtils.getSoapAction( newOperation));
302 				wsdlOperation.setName( newOperation.getOperation().getName() );
303 				
304 				oldOperations.remove( bindingOperationName );
305 				newOperations.remove( c );
306 				c--;
307 			}
308 		}
309 		
310 		//	remove leftover operations
311 		i = oldOperations.keySet().iterator();
312 		while( i.hasNext())
313 		{
314 			String name = i.next();
315 			
316 			if( newOperations.size() > 0 )
317 		   {
318 				List<String> list = new ArrayList<String>();
319 				list.add( "none - delete operation" );
320 				for( int c = 0; c < newOperations.size(); c++ )
321 					list.add( newOperations.get( c ).getName() );
322 				
323 				String retval = (String) JOptionPane.showInputDialog( SoapUI.getInstance().getFrame(), 
324 						"Binding operation [" + name + "] not found in new interface, select new\nbinding operation to map to", 
325 						"Map Operation", JOptionPane.QUESTION_MESSAGE, null, list.toArray(), "none - delete operation" );
326 				
327 				int ix = list.indexOf( retval)-1;
328 				
329 				// delete operation?
330 				if( ix < 0 )
331 				{
332 					deleteOperation( name );
333 				}
334 				// change operation?
335 				else
336 				{
337 					BindingOperation newOperation = newOperations.get( ix );
338 					WsdlOperation wsdlOperation = oldOperations.get( name );
339 					wsdlOperation.setAction( WsdlUtils.getSoapAction( newOperation));
340 					wsdlOperation.setName( newOperation.getOperation().getName() );
341 					wsdlOperation.setBindingOperationName( newOperation.getName() );
342 
343 					newOperations.remove( ix );
344 					oldOperations.remove( name );
345 				}
346 		   }
347 			else 
348 			{
349 				deleteOperation( name );
350 				oldOperations.remove( name );
351 			}
352 			
353 			i = oldOperations.keySet().iterator();
354 		}
355 		
356 		// add leftover new operations
357 		for( int c = 0; c < newOperations.size(); c++ )
358 		{
359 			BindingOperation newOperation = newOperations.get( c );
360 			WsdlOperation wsdlOperation = addNewOperation();
361 			wsdlOperation.setAction( WsdlUtils.getSoapAction( newOperation));
362 			wsdlOperation.setName( newOperation.getOperation().getName() );
363 			wsdlOperation.setBindingOperationName( newOperation.getName() );
364 			
365 			notifyOperationAdded( wsdlOperation );
366 		}
367 		
368 		wsdlContext = newContext;
369 		if( soapRequestBuilder != null )
370 			soapRequestBuilder.setWsdlContext( wsdlContext );
371 		
372     	setDefinition( url );
373 
374 		if( port != null )
375 		{
376 	      SOAPAddress address = (SOAPAddress) WsdlUtils.getExtensiblityElement( port.getExtensibilityElements(), SOAPAddress.class );
377 	      if( address != null )
378 	         addEndpoint( address.getLocationURI() );
379 		}
380 	}
381 
382 	private void deleteOperation(String bindingOperationName)
383 	{
384 		for( int c = 0; c < operations.size(); c++ )
385 		{
386 			WsdlOperation wsdlOperation = operations.get( c );
387 			if( wsdlOperation.getBindingOperationName().equals( bindingOperationName ))
388 			{
389 				log.info( "deleting operation [" + bindingOperationName + "]" ); 
390 				notifyOperationRemoved( wsdlOperation );
391 				wsdlOperation.release();
392 				
393 				operations.remove( c );
394 				interfaceConfig.removeOperation( c );
395 				
396 				return;
397 			}
398 		}
399 	}
400 	
401 	public void notifyOperationAdded( WsdlOperation operation )
402    {
403       InterfaceListener[] a = listeners.toArray( new InterfaceListener[listeners.size()] );
404       
405       for (int c = 0; c < a.length; c++ )
406       {
407          a[c].operationAdded( operation );
408       }
409    }
410    
411    public void notifyOperationRemoved( WsdlOperation operation )
412    {
413    	InterfaceListener[] a = listeners.toArray( new InterfaceListener[listeners.size()] );
414       
415       for (int c = 0; c < a.length; c++ )
416       {
417          a[c].operationRemoved( operation );
418       }
419    }
420    
421    public void notifyRequestAdded( WsdlRequest request )
422    {
423    	InterfaceListener[] a = listeners.toArray( new InterfaceListener[listeners.size()] );
424       
425       for (int c = 0; c < a.length; c++ )
426       {
427          a[c].requestAdded( request );
428       }
429    }
430    
431    public void notifyRequestRemoved( WsdlRequest request )
432    {
433    	InterfaceListener[] a = listeners.toArray( new InterfaceListener[listeners.size()] );
434       
435       for (int c = 0; c < a.length; c++ )
436       {
437          a[c].requestRemoved( request );
438       }
439    }
440 
441 	public void addInterfaceListener(InterfaceListener listener)
442 	{
443 		listeners.add( listener );
444 	}
445 
446 	public void removeInterfaceListener(InterfaceListener listener)
447 	{
448 		listeners.remove( listener );
449 	}
450 }