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.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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
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
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
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
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
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
428 if( getSettings().getBoolean( WsdlSettings.NAME_WITH_BINDING ))
429 setName( binding.getQName().getLocalPart() );
430
431
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
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
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
480 if( ix < 0 )
481 {
482 deleteOperation( name );
483 }
484
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
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
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 }