View Javadoc

1   /*
2    *  soapUI, copyright (C) 2004-2010 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.support.wsdl;
14  
15  import java.util.ArrayList;
16  import java.util.HashMap;
17  import java.util.Iterator;
18  import java.util.List;
19  import java.util.Map;
20  
21  import javax.wsdl.Binding;
22  import javax.wsdl.Definition;
23  import javax.wsdl.Port;
24  import javax.wsdl.PortType;
25  import javax.wsdl.Service;
26  import javax.xml.namespace.QName;
27  
28  import org.apache.log4j.Logger;
29  
30  import com.eviware.soapui.SoapUI;
31  import com.eviware.soapui.config.WsaVersionTypeConfig;
32  import com.eviware.soapui.impl.wsdl.WsdlInterface;
33  import com.eviware.soapui.impl.wsdl.WsdlProject;
34  import com.eviware.soapui.impl.wsdl.support.BindingImporter;
35  import com.eviware.soapui.impl.wsdl.support.policy.PolicyUtils;
36  import com.eviware.soapui.impl.wsdl.support.soap.Soap11HttpBindingImporter;
37  import com.eviware.soapui.impl.wsdl.support.soap.Soap12HttpBindingImporter;
38  import com.eviware.soapui.impl.wsdl.support.soap.SoapJMSBindingImporter;
39  import com.eviware.soapui.impl.wsdl.support.soap.TibcoSoapJMSBindingImporter;
40  import com.eviware.soapui.settings.WsdlSettings;
41  import com.eviware.soapui.support.UISupport;
42  
43  /***
44   * Importer for WsdlInterfaces from WSDL urls / files
45   * 
46   * @author Ole.Matzura
47   */
48  
49  public class WsdlImporter
50  {
51  	private static List<BindingImporter> bindingImporters = new ArrayList<BindingImporter>();
52  	@SuppressWarnings( "unused" )
53  	private static WsdlImporter instance;
54  
55  	private final static Logger log = Logger.getLogger( WsdlImporter.class );
56  
57  	static
58  	{
59  		try
60  		{
61  			bindingImporters.add( new Soap11HttpBindingImporter() );
62  			bindingImporters.add( new Soap12HttpBindingImporter() );
63  			bindingImporters.add( new SoapJMSBindingImporter() );
64  			bindingImporters.add( new TibcoSoapJMSBindingImporter() );
65  		}
66  		catch( Exception e )
67  		{
68  			SoapUI.logError( e );
69  		}
70  	}
71  
72  	public static WsdlInterface[] importWsdl( WsdlProject project, String wsdlUrl ) throws Exception
73  	{
74  		return importWsdl( project, wsdlUrl, null );
75  	}
76  
77  	public static WsdlInterface[] importWsdl( WsdlProject project, String wsdlUrl, QName bindingName ) throws Exception
78  	{
79  		return importWsdl( project, wsdlUrl, bindingName, null );
80  	}
81  
82  	public static WsdlInterface[] importWsdl( WsdlProject project, String wsdlUrl, QName bindingName,
83  			WsdlLoader wsdlLoader ) throws Exception
84  	{
85  		WsdlContext wsdlContext = new WsdlContext( wsdlUrl );
86  		if( !wsdlContext.load( wsdlLoader ) )
87  		{
88  			UISupport.showErrorMessage( "Failed to import WSDL" );
89  			return null;
90  		}
91  
92  		Definition definition = wsdlContext.getDefinition();
93  		List<WsdlInterface> result = new ArrayList<WsdlInterface>();
94  		if( bindingName != null )
95  		{
96  			WsdlInterface iface = importBinding( project, wsdlContext, ( Binding )definition.getAllBindings().get(
97  					bindingName ) );
98  			return iface == null ? new WsdlInterface[0] : new WsdlInterface[] { iface };
99  		}
100 
101 		Map<Binding, WsdlInterface> importedBindings = new HashMap<Binding, WsdlInterface>();
102 
103 		Map<?, ?> serviceMap = definition.getAllServices();
104 		if( serviceMap.isEmpty() )
105 			log.info( "Missing services in [" + wsdlUrl + "], check for bindings" );
106 		else
107 		{
108 			Iterator<?> i = serviceMap.values().iterator();
109 			while( i.hasNext() )
110 			{
111 				Service service = ( Service )i.next();
112 				Map<?, ?> portMap = service.getPorts();
113 				Iterator<?> i2 = portMap.values().iterator();
114 				while( i2.hasNext() )
115 				{
116 					Port port = ( Port )i2.next();
117 
118 					Binding binding = port.getBinding();
119 					if( importedBindings.containsKey( binding ) )
120 					{
121 						// add endpoint since it could differ from already imported
122 						// one..
123 						String endpoint = WsdlUtils.getSoapEndpoint( port );
124 						if( endpoint != null )
125 							importedBindings.get( binding ).addEndpoint( endpoint );
126 
127 						continue;
128 					}
129 
130 					String ifaceName = getInterfaceNameForBinding( binding );
131 					WsdlInterface ifc = ( WsdlInterface )project.getInterfaceByName( ifaceName );
132 					if( ifc != null )
133 					{
134 						Boolean res = UISupport.confirmOrCancel( "Interface [" + ifc.getName()
135 								+ "] already exists in project, update instead?", "Import WSDL" );
136 						if( res == null )
137 							return new WsdlInterface[0];
138 
139 						if( res.booleanValue() )
140 						{
141 							if( ifc.updateDefinition( wsdlUrl, false ) )
142 							{
143 								importedBindings.put( binding, ifc );
144 								result.add( ifc );
145 							}
146 						}
147 
148 						continue;
149 					}
150 
151 					WsdlInterface iface = importBinding( project, wsdlContext, binding );
152 					if( iface != null )
153 					{
154 						String endpoint = WsdlUtils.getSoapEndpoint( port );
155 						if( endpoint != null )
156 							iface.addEndpoint( endpoint );
157 						// NOTE: question is what has priority wsaw:usingAddressing or
158 						// wsam:Addressing policy
159 						// in case addressing is defined both ways in the wsdl and
160 						// there is conflict
161 						// currently the first one that's set is final
162 						// first is checked wsdl binding and policy attachment
163 						// and then for port in the same order
164 
165 						if( iface.getWsaVersion().equals( WsaVersionTypeConfig.NONE.toString() ) )
166 							iface.setWsaVersion( WsdlUtils.getUsingAddressing( port ) );
167 						if( iface.getWsaVersion().equals( WsaVersionTypeConfig.NONE.toString() ) )
168 						{
169 							iface.processPolicy( PolicyUtils.getAttachedPolicy( port, wsdlContext.getDefinition() ) );
170 						}
171 
172 						result.add( iface );
173 						importedBindings.put( binding, iface );
174 					}
175 				}
176 			}
177 		}
178 
179 		Map<?, ?> bindingMap = definition.getAllBindings();
180 		if( !bindingMap.isEmpty() )
181 		{
182 			Iterator<?> i = bindingMap.values().iterator();
183 			while( i.hasNext() )
184 			{
185 				Binding binding = ( Binding )i.next();
186 				if( importedBindings.containsKey( binding ) )
187 				{
188 					continue;
189 				}
190 
191 				PortType portType = binding.getPortType();
192 				if( portType == null )
193 				{
194 					log.warn( "Missing portType for binding [" + binding.getQName().toString() + "]" );
195 				}
196 				else
197 				{
198 					String ifaceName = getInterfaceNameForBinding( binding );
199 					WsdlInterface ifc = ( WsdlInterface )project.getInterfaceByName( ifaceName );
200 					if( ifc != null && result.indexOf( ifc ) == -1 )
201 					{
202 						Boolean res = UISupport.confirmOrCancel( "Interface [" + ifc.getName()
203 								+ "] already exists in project, update instead?", "Import WSDL" );
204 						if( res == null )
205 							return new WsdlInterface[0];
206 
207 						if( res.booleanValue() )
208 						{
209 							if( ifc.updateDefinition( wsdlUrl, false ) )
210 							{
211 								importedBindings.put( binding, ifc );
212 								result.add( ifc );
213 							}
214 						}
215 
216 						continue;
217 					}
218 
219 					WsdlInterface iface = importBinding( project, wsdlContext, binding );
220 					if( iface != null )
221 					{
222 						result.add( iface );
223 						importedBindings.put( binding, ifc );
224 					}
225 				}
226 			}
227 		}
228 
229 		if( importedBindings.isEmpty() && serviceMap.isEmpty() && bindingMap.isEmpty() )
230 		{
231 			UISupport.showErrorMessage( "Found nothing to import in [" + wsdlUrl + "]" );
232 		}
233 
234 		// only the last gets the context
235 		if( result.size() > 0 )
236 		{
237 			result.get( result.size() - 1 ).setWsdlContext( wsdlContext );
238 		}
239 
240 		return result.toArray( new WsdlInterface[result.size()] );
241 	}
242 
243 	public final static String getInterfaceNameForBinding( Binding binding )
244 	{
245 		if( SoapUI.getSettings().getBoolean( WsdlSettings.NAME_WITH_BINDING ) )
246 			return binding.getQName().getLocalPart();
247 		else
248 			return binding.getPortType().getQName().getLocalPart();
249 	}
250 
251 	private static WsdlInterface importBinding( WsdlProject project, WsdlContext wsdlContext, Binding binding )
252 			throws Exception
253 	{
254 		log.info( "Finding importer for " + binding.getQName() );
255 		for( int c = 0; c < bindingImporters.size(); c++ )
256 		{
257 			BindingImporter importer = bindingImporters.get( c );
258 			if( importer.canImport( binding ) )
259 			{
260 				log.info( "Importing binding " + binding.getQName() );
261 				WsdlInterface iface = importer.importBinding( project, wsdlContext, binding );
262 
263 				String url = wsdlContext.getUrl();
264 				iface.setDefinition( url );
265 
266 				return iface;
267 			}
268 		}
269 		log.info( "Missing importer for " + binding.getQName() );
270 
271 		return null;
272 	}
273 }