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