001: /*
002: * soapUI, copyright (C) 2004-2007 eviware.com
003: *
004: * soapUI is free software; you can redistribute it and/or modify it under the
005: * terms of version 2.1 of the GNU Lesser General Public License as published by
006: * the Free Software Foundation.
007: *
008: * soapUI is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
009: * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
010: * See the GNU Lesser General Public License for more details at gnu.org.
011: */
012:
013: package com.eviware.soapui.impl.wsdl;
014:
015: import java.util.ArrayList;
016: import java.util.Arrays;
017: import java.util.HashMap;
018: import java.util.HashSet;
019: import java.util.Iterator;
020: import java.util.List;
021: import java.util.Map;
022: import java.util.Set;
023:
024: import javax.wsdl.Binding;
025: import javax.wsdl.BindingOperation;
026: import javax.wsdl.Definition;
027: import javax.wsdl.Port;
028: import javax.wsdl.Service;
029: import javax.xml.namespace.QName;
030:
031: import org.apache.log4j.Logger;
032:
033: import com.eviware.soapui.SoapUI;
034: import com.eviware.soapui.config.DefinitionCacheConfig;
035: import com.eviware.soapui.config.EndpointConfig;
036: import com.eviware.soapui.config.EndpointsConfig;
037: import com.eviware.soapui.config.InterfaceConfig;
038: import com.eviware.soapui.config.OperationConfig;
039: import com.eviware.soapui.config.SoapVersionTypesConfig;
040: import com.eviware.soapui.impl.wsdl.support.soap.SoapMessageBuilder;
041: import com.eviware.soapui.impl.wsdl.support.soap.SoapVersion;
042: import com.eviware.soapui.impl.wsdl.support.wsdl.CachedWsdlLoader;
043: import com.eviware.soapui.impl.wsdl.support.wsdl.UrlWsdlLoader;
044: import com.eviware.soapui.impl.wsdl.support.wsdl.WsdlContext;
045: import com.eviware.soapui.impl.wsdl.support.wsdl.WsdlLoader;
046: import com.eviware.soapui.impl.wsdl.support.wsdl.WsdlUtils;
047: import com.eviware.soapui.model.iface.Interface;
048: import com.eviware.soapui.model.iface.InterfaceListener;
049: import com.eviware.soapui.model.iface.Operation;
050: import com.eviware.soapui.settings.WsdlSettings;
051: import com.eviware.soapui.support.UISupport;
052: import com.eviware.soapui.support.action.swing.DefaultActionList;
053: import com.eviware.soapui.support.types.StringList;
054:
055: /**
056: * WSDL implementation of Interface, maps to a WSDL Binding
057: *
058: * @author Ole.Matzura
059: */
060:
061: public class WsdlInterface extends
062: AbstractWsdlModelItem<InterfaceConfig> implements Interface {
063: public static final String STYLE_DOCUMENT = "Document";
064: public static final String STYLE_RPC = "RPC";
065:
066: public static final String JBOSSWS_ACTIONS = "jbossws";
067: public static final String WSTOOLS_ACTIONS = "wstools";
068: public static final String XML_ACTIONS = "xml";
069:
070: private final static Logger log = Logger
071: .getLogger(WsdlInterface.class);
072:
073: private List<WsdlOperation> operations = new ArrayList<WsdlOperation>();
074: private WsdlProject project;
075: private SoapMessageBuilder soapMessageBuilder;
076: private WsdlContext wsdlContext;
077: private Set<InterfaceListener> listeners = new HashSet<InterfaceListener>();
078: private DefaultActionList generateActions;
079:
080: public WsdlInterface(WsdlProject project,
081: InterfaceConfig interfaceConfig) {
082: super (interfaceConfig, project, "/interface2.gif");
083:
084: this .project = project;
085:
086: if (interfaceConfig.getEndpoints() == null)
087: interfaceConfig.addNewEndpoints();
088:
089: List<OperationConfig> operationConfigs = interfaceConfig
090: .getOperationList();
091: for (int i = 0; i < operationConfigs.size(); i++) {
092: operations.add(new WsdlOperation(this , operationConfigs
093: .get(i)));
094: }
095:
096: buildActions();
097: }
098:
099: private void buildActions() {
100: generateActions = new DefaultActionList("Generate");
101: // generateActions.addAction( new ActionExtensionPoint( this, WSTOOLS_ACTIONS ) );
102: // generateActions.addAction( new WSToolsWsdl2JavaAction( this ));
103: // generateActions.addAction( new JBossWSConsumeAction( this ));
104: // generateActions.addAction( ActionSupport.SEPARATOR_ACTION );
105: // generateActions.addAction( new ActionExtensionPoint( this, JBOSSWS_ACTIONS ) );
106: // generateActions.addAction( new WSCompileAction( this ));
107: // generateActions.addAction( new WSImportAction( this ));
108: // generateActions.addAction( ActionSupport.SEPARATOR_ACTION );
109: // generateActions.addAction( new Axis1XWSDL2JavaAction( this ));
110: // generateActions.addAction( new Axis2WSDL2CodeAction( this ));
111: // generateActions.addAction( new XFireAction( this ));
112: // generateActions.addAction( new OracleWsaGenProxyAction( this ));
113: // generateActions.addAction( ActionSupport.SEPARATOR_ACTION );
114: // generateActions.addAction( new ActionExtensionPoint( this, XML_ACTIONS ) );
115: // generateActions.addAction( new JaxbXjcAction( this ));
116: // generateActions.addAction( new XmlBeans2Action( this ));
117: // generateActions.addAction( ActionSupport.SEPARATOR_ACTION );
118: // generateActions.addAction( new DotNetWsdlAction( this ));
119: // generateActions.addAction( new GSoapAction( this ));
120:
121: // addAction( new ShowDesktopPanelAction( "Open Interface Viewer", "Opens the Interface Viewer for this Interface", this ));
122: // addAction( ActionSupport.SEPARATOR_ACTION );
123: // addAction( new ActionSupport.ActionListAction( generateActions ));
124: // addAction( new WSToolsRegenerateJava2WsdlAction( this ));
125: // addAction( ActionSupport.SEPARATOR_ACTION );
126: // addAction( new WSIAnalyzeAction( this ));
127: // addAction( new TcpMonAction( this ));
128: // addAction( ActionSupport.SEPARATOR_ACTION );
129: // addAction( new GenerateTestSuiteAction( this ));
130: // addAction( new GenerateMockServiceAction( this ));
131: // addAction( ActionSupport.SEPARATOR_ACTION );
132: // addAction( new InterfaceEndpointsAction( this ) );
133: // addAction( new UpdateInterfaceAction( this ) );
134: // addAction( new ExportDefinitionAction( this ) );
135: // addAction( ActionSupport.SEPARATOR_ACTION );
136: // addAction( new RemoveInterfaceAction( this ) );
137: // addAction( new ShowOnlineHelpAction( HelpUrls.INTERFACE_HELP_URL ));
138: }
139:
140: public DefaultActionList getGenerateActions() {
141: return generateActions;
142: }
143:
144: public String[] getEndpoints() {
145: EndpointsConfig endpoints = getConfig().getEndpoints();
146: List<EndpointConfig> endpointArray = endpoints
147: .getEndpointList();
148:
149: String[] result = new String[endpointArray.size()];
150:
151: for (int c = 0; c < result.length; c++) {
152: EndpointConfig endpoint = endpointArray.get(c);
153: if (endpoint.isSetLabel())
154: result[c] = endpoint.getLabel();
155: else
156: result[c] = endpoint.getStringValue();
157: }
158:
159: return result;
160: }
161:
162: public WsdlOperation getOperationAt(int index) {
163: return operations.get(index);
164: }
165:
166: public int getOperationCount() {
167: return operations.size();
168: }
169:
170: public WsdlOperation addNewOperation(BindingOperation operation) {
171: WsdlOperation operationImpl = new WsdlOperation(this ,
172: getConfig().addNewOperation());
173: operations.add(operationImpl);
174:
175: operationImpl.initFromBindingOperation(operation, false);
176: fireOperationAdded(operationImpl);
177: return operationImpl;
178: }
179:
180: public WsdlProject getProject() {
181: return project;
182: }
183:
184: public void addEndpoint(String endpoint) {
185: if (endpoint == null || endpoint.trim().length() == 0)
186: return;
187:
188: endpoint = endpoint.trim();
189: String[] endpoints = getEndpoints();
190:
191: // dont add the same endpoint twice
192: if (Arrays.asList(endpoints).contains(endpoint))
193: return;
194:
195: getConfig().getEndpoints().addNewEndpoint().setStringValue(
196: endpoint);
197:
198: notifyPropertyChanged(ENDPOINT_PROPERTY, null, endpoint);
199: }
200:
201: public void changeEndpoint(String oldEndpoint, String newEndpoint) {
202: if (oldEndpoint == null || oldEndpoint.trim().length() == 0)
203: return;
204: if (newEndpoint == null || newEndpoint.trim().length() == 0)
205: return;
206:
207: EndpointsConfig endpoints = getConfig().getEndpoints();
208: List<EndpointConfig> endpointArray = endpoints
209: .getEndpointList();
210:
211: String[] result = new String[endpointArray.size()];
212:
213: for (int c = 0; c < result.length; c++) {
214: EndpointConfig endpoint = endpointArray.get(c);
215: if (endpoint.getStringValue().equals(oldEndpoint)) {
216: endpoint.setStringValue(newEndpoint);
217: notifyPropertyChanged(ENDPOINT_PROPERTY, oldEndpoint,
218: newEndpoint);
219: break;
220: }
221: }
222: }
223:
224: public void removeEndpoint(String endpoint) {
225: EndpointsConfig endpoints = getConfig().getEndpoints();
226: List<EndpointConfig> endpointArray = endpoints
227: .getEndpointList();
228:
229: String[] result = new String[endpointArray.size()];
230:
231: for (int c = 0; c < result.length; c++) {
232: EndpointConfig ep = endpointArray.get(c);
233: if (ep.getStringValue().equals(endpoint)) {
234: endpoints.removeEndpoint(c);
235: notifyPropertyChanged(ENDPOINT_PROPERTY, endpoint, null);
236: break;
237: }
238: }
239: }
240:
241: public void setDefinition(String wsdlUrl, boolean cache) {
242: String old = getDefinition();
243:
244: getConfig().setDefinition(wsdlUrl);
245:
246: if (wsdlContext != null) {
247: wsdlContext.setDefinition(wsdlUrl, getConfig()
248: .getDefinitionCache());
249: wsdlContext.setSoapVersion(getSoapVersion());
250: }
251:
252: notifyPropertyChanged(DEFINITION_PROPERTY, old, wsdlUrl);
253: }
254:
255: public DefinitionCacheConfig cacheDefinition(WsdlLoader loader)
256: throws Exception {
257: log.debug("Caching definition for [" + loader.getBaseURI()
258: + "]");
259: if (getConfig().isSetDefinitionCache())
260: getConfig().unsetDefinitionCache();
261:
262: DefinitionCacheConfig definitionCache = getConfig()
263: .addNewDefinitionCache();
264: definitionCache.set(WsdlLoader.cacheWsdl(loader));
265: return definitionCache;
266: }
267:
268: public String getDefinition() {
269: return getConfig().isSetDefinition() ? getConfig()
270: .getDefinition() : null;
271: }
272:
273: public synchronized WsdlContext getWsdlContext() {
274: if (wsdlContext == null) {
275: wsdlContext = new WsdlContext(getDefinition(),
276: getSoapVersion(), getConfig().getDefinitionCache(),
277: this );
278: }
279:
280: return wsdlContext;
281: }
282:
283: /**
284: * Used by importer so we dont need to reload the context after importing..
285: * @param wsdlContext
286: */
287:
288: public void setWsdlContext(WsdlContext wsdlContext) {
289: this .wsdlContext = wsdlContext;
290: this .wsdlContext.setSoapVersion(getSoapVersion());
291:
292: if (!getConfig().isSetDefinitionCache())
293: getConfig().addNewDefinitionCache();
294:
295: if (wsdlContext.getCacheConfig() != null) {
296: // use cache from context
297: getConfig()
298: .setDefinitionCache(wsdlContext.getCacheConfig());
299: }
300: }
301:
302: public SoapMessageBuilder getMessageBuilder() {
303: if (soapMessageBuilder == null) {
304: try {
305: soapMessageBuilder = new SoapMessageBuilder(this );
306: } catch (Exception e) {
307: SoapUI.logError(e);
308: }
309: }
310: return soapMessageBuilder;
311: }
312:
313: public void setSoapMessageBuilder(SoapMessageBuilder builder) {
314: soapMessageBuilder = builder;
315: soapMessageBuilder.setInterface(this );
316: }
317:
318: public QName getBindingName() {
319: return getConfig().getBindingName() == null ? null : QName
320: .valueOf(getConfig().getBindingName());
321: }
322:
323: public void setBindingName(QName name) {
324: getConfig().setBindingName(name.toString());
325: }
326:
327: public SoapVersion getSoapVersion() {
328: if (getConfig().getSoapVersion() == SoapVersionTypesConfig.X_1_2)
329: return SoapVersion.Soap12;
330:
331: return SoapVersion.Soap11;
332: }
333:
334: public void setSoapVersion(SoapVersion version) {
335: if (version == SoapVersion.Soap11)
336: getConfig().setSoapVersion(SoapVersionTypesConfig.X_1_1);
337: else if (version == SoapVersion.Soap12)
338: getConfig().setSoapVersion(SoapVersionTypesConfig.X_1_2);
339: else
340: throw new RuntimeException("Unknown soapVersion ["
341: + version + "], must be 1.1 or 1.2");
342:
343: getWsdlContext().setSoapVersion(version);
344: }
345:
346: @SuppressWarnings("unchecked")
347: public boolean updateDefinition(String url, boolean createRequests)
348: throws Exception {
349: WsdlContext newContext = null;
350:
351: if (getConfig().isSetDefinitionCache())
352: getConfig().unsetDefinitionCache();
353:
354: if (!getSettings().getBoolean(WsdlSettings.CACHE_WSDLS)) {
355: newContext = new WsdlContext(url, getSoapVersion(), null,
356: null);
357: } else {
358: newContext = new WsdlContext(url, getSoapVersion(), null,
359: this );
360: }
361:
362: if (!newContext.load()) {
363: return false;
364: }
365:
366: Definition definition = newContext.getDefinition();
367: Service service = null;
368: Port port = null;
369: Binding binding = null;
370:
371: // start by finding the old binding in the new definition
372: Map serviceMap = definition.getAllServices();
373: Iterator<String> i = serviceMap.keySet().iterator();
374: while (i.hasNext()) {
375: service = (Service) serviceMap.get(i.next());
376: Map portMap = service.getPorts();
377:
378: Iterator i2 = portMap.keySet().iterator();
379: while (i2.hasNext()) {
380: port = (Port) portMap.get(i2.next());
381: if (port.getBinding().getQName().equals(
382: getBindingName())) {
383: binding = port.getBinding();
384: }
385: }
386:
387: if (binding != null)
388: break;
389: service = null;
390: }
391:
392: if (service == null && binding == null) {
393: binding = definition.getBinding(getBindingName());
394: }
395:
396: // missing matching binding, prompt for new one to use instead (will happen if binding has been renamed)
397: if (binding == null) {
398: Map bindings = definition.getAllBindings();
399:
400: Object retval = UISupport
401: .prompt(
402: "Missing matching binding ["
403: + getBindingName()
404: + "] in definition, select new\nbinding to map to",
405: "Map Binding", bindings.keySet().toArray());
406:
407: if (retval == null)
408: return false;
409:
410: binding = (Binding) bindings.get(retval);
411: setBindingName(binding.getQName());
412: }
413:
414: // update name
415: if (getSettings().getBoolean(WsdlSettings.NAME_WITH_BINDING))
416: setName(binding.getQName().getLocalPart());
417:
418: // prepare for transfer of operations/requests
419: List<BindingOperation> newOperations = new ArrayList<BindingOperation>(
420: binding.getBindingOperations());
421: Map<String, WsdlOperation> oldOperations = new HashMap<String, WsdlOperation>();
422: for (int c = 0; c < operations.size(); c++)
423: oldOperations.put(operations.get(c)
424: .getBindingOperationName(), operations.get(c));
425:
426: // clear existing from both collections
427: for (int c = 0; c < newOperations.size(); c++) {
428: BindingOperation newOperation = newOperations.get(c);
429: String bindingOperationName = newOperation.getName();
430: if (oldOperations.containsKey(bindingOperationName)) {
431: log.info("Synchronizing existing operation ["
432: + bindingOperationName + "]");
433: WsdlOperation wsdlOperation = oldOperations
434: .get(bindingOperationName);
435: wsdlOperation.initFromBindingOperation(newOperation,
436: true);
437:
438: oldOperations.remove(bindingOperationName);
439: newOperations.remove(c);
440: c--;
441: }
442: }
443:
444: // remove leftover operations
445: i = oldOperations.keySet().iterator();
446: while (i.hasNext()) {
447: String name = i.next();
448:
449: if (newOperations.size() > 0) {
450: List<String> list = new ArrayList<String>();
451: list.add("none - delete operation");
452: for (int c = 0; c < newOperations.size(); c++)
453: list.add(newOperations.get(c).getName());
454:
455: String retval = (String) UISupport
456: .prompt(
457: "Binding operation ["
458: + name
459: + "] not found in new interface, select new\nbinding operation to map to",
460: "Map Operation", list.toArray(),
461: "none - delete operation");
462:
463: if (retval == null) {
464: UISupport
465: .showErrorMessage("Aborting update of interface");
466: return false;
467: }
468:
469: int ix = list.indexOf(retval) - 1;
470:
471: // delete operation?
472: if (ix < 0) {
473: deleteOperation(name);
474: }
475: // change operation?
476: else {
477: BindingOperation newOperation = newOperations
478: .get(ix);
479: WsdlOperation wsdlOperation = oldOperations
480: .get(name);
481: wsdlOperation.initFromBindingOperation(
482: newOperation, true);
483: newOperations.remove(ix);
484: }
485:
486: oldOperations.remove(name);
487: } else {
488: deleteOperation(name);
489: oldOperations.remove(name);
490: }
491:
492: i = oldOperations.keySet().iterator();
493: }
494:
495: wsdlContext = newContext;
496: if (soapMessageBuilder != null)
497: soapMessageBuilder.setWsdlContext(wsdlContext);
498:
499: // add leftover new operations
500: if (newOperations.size() > 0) {
501: for (int c = 0; c < newOperations.size(); c++) {
502: BindingOperation newOperation = newOperations.get(c);
503: WsdlOperation wsdlOperation = addNewOperation(newOperation);
504:
505: if (createRequests) {
506: WsdlRequest request = wsdlOperation
507: .addNewRequest("Request 1");
508: try {
509: request.setRequestContent(wsdlOperation
510: .createRequest(true));
511: } catch (Exception e) {
512: SoapUI.logError(e);
513: }
514: }
515: }
516: }
517:
518: setDefinition(url, false);
519:
520: if (port != null) {
521: String endpoint = WsdlUtils.getSoapEndpoint(port);
522: if (endpoint != null) {
523: StringList list = new StringList(getEndpoints());
524: if (!list.contains(endpoint)) {
525: if (UISupport.confirm(
526: "Update existing requests with new endpoint\n["
527: + endpoint + "]",
528: "Update Definition")) {
529: for (int c = 0; c < getOperationCount(); c++) {
530: Operation operation = getOperationAt(c);
531:
532: for (int ix = 0; ix < operation
533: .getRequestCount(); ix++) {
534: operation.getRequestAt(ix).setEndpoint(
535: endpoint);
536: }
537: }
538: }
539:
540: getConfig().getEndpoints().insertNewEndpoint(0)
541: .setStringValue(endpoint);
542: notifyPropertyChanged(ENDPOINT_PROPERTY, null,
543: endpoint);
544: }
545: }
546: }
547:
548: return true;
549: }
550:
551: private void deleteOperation(String bindingOperationName) {
552: for (int c = 0; c < operations.size(); c++) {
553: WsdlOperation wsdlOperation = operations.get(c);
554: if (wsdlOperation.getBindingOperationName().equals(
555: bindingOperationName)) {
556: log.info("deleting operation [" + bindingOperationName
557: + "]");
558:
559: // remove requests first (should this be done by some listener?)
560: while (wsdlOperation.getRequestCount() > 0)
561: wsdlOperation
562: .removeRequest((WsdlRequest) wsdlOperation
563: .getRequestAt(0));
564:
565: operations.remove(c);
566:
567: try {
568: fireOperationRemoved(wsdlOperation);
569: } finally {
570: wsdlOperation.release();
571: getConfig().removeOperation(c);
572: }
573:
574: return;
575: }
576: }
577: }
578:
579: public void fireOperationAdded(WsdlOperation operation) {
580: InterfaceListener[] a = listeners
581: .toArray(new InterfaceListener[listeners.size()]);
582:
583: for (int c = 0; c < a.length; c++) {
584: a[c].operationAdded(operation);
585: }
586: }
587:
588: public void fireOperationUpdated(WsdlOperation operation) {
589: InterfaceListener[] a = listeners
590: .toArray(new InterfaceListener[listeners.size()]);
591:
592: for (int c = 0; c < a.length; c++) {
593: a[c].operationUpdated(operation);
594: }
595: }
596:
597: public void fireOperationRemoved(WsdlOperation operation) {
598: InterfaceListener[] a = listeners
599: .toArray(new InterfaceListener[listeners.size()]);
600:
601: for (int c = 0; c < a.length; c++) {
602: a[c].operationRemoved(operation);
603: }
604: }
605:
606: public void fireRequestAdded(WsdlRequest request) {
607: InterfaceListener[] a = listeners
608: .toArray(new InterfaceListener[listeners.size()]);
609:
610: for (int c = 0; c < a.length; c++) {
611: a[c].requestAdded(request);
612: }
613: }
614:
615: public void fireRequestRemoved(WsdlRequest request) {
616: InterfaceListener[] a = listeners
617: .toArray(new InterfaceListener[listeners.size()]);
618:
619: for (int c = 0; c < a.length; c++) {
620: a[c].requestRemoved(request);
621: }
622: }
623:
624: public void addInterfaceListener(InterfaceListener listener) {
625: listeners.add(listener);
626: }
627:
628: public void removeInterfaceListener(InterfaceListener listener) {
629: listeners.remove(listener);
630: }
631:
632: /**
633: * Gets the endpoint url for the specified endpoint (which may be a label)
634: *
635: * @param endpoint the endpoint to get for
636: * @return the endpoints url
637: */
638:
639: public String getEndpointURL(String endpoint) {
640: List<EndpointConfig> endpointArray = getConfig().getEndpoints()
641: .getEndpointList();
642: for (EndpointConfig endpointConfig : endpointArray) {
643: if (endpointConfig.isSetLabel()
644: && endpointConfig.getLabel().equals(endpoint))
645: return endpointConfig.getStringValue();
646: }
647:
648: return endpoint;
649: }
650:
651: public WsdlOperation getOperationByName(String name) {
652: return (WsdlOperation) getWsdlModelItemByName(operations, name);
653: }
654:
655: public boolean isCached() {
656: return getConfig().isSetDefinitionCache();
657: }
658:
659: public WsdlLoader createWsdlLoader() {
660: return isCached() ? new CachedWsdlLoader(getConfig()
661: .getDefinitionCache()) : new UrlWsdlLoader(
662: getDefinition());
663: }
664:
665: public void clearCache() {
666: if (wsdlContext != null)
667: wsdlContext.setDefinitionCache(null);
668:
669: if (getConfig().isSetDefinitionCache())
670: getConfig().unsetDefinitionCache();
671: }
672:
673: public String getStyle() {
674: if (wsdlContext == null || !wsdlContext.isLoaded())
675: return "<not loaded>";
676:
677: try {
678: Binding binding = wsdlContext.getDefinition().getBinding(
679: getBindingName());
680: if (binding == null)
681: return "<missing binding>";
682:
683: if (WsdlUtils.isRpc(binding)) {
684: return STYLE_RPC;
685: } else {
686: return STYLE_DOCUMENT;
687: }
688: } catch (Exception e) {
689: SoapUI.logError(e);
690: return "<error>";
691: }
692: }
693:
694: public void release() {
695: super .release();
696:
697: for (WsdlOperation operation : operations)
698: operation.release();
699: }
700:
701: public List<Operation> getOperations() {
702: return new ArrayList<Operation>(operations);
703: }
704:
705: @Override
706: public void onSave() {
707: for (WsdlOperation operation : operations)
708: operation.onSave();
709: }
710: }
|