View Javadoc

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