View Javadoc

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