View Javadoc

1   /*******************************************************************************
2    *  Copyright (c) 2005, 2006, 2007 Imola Informatica.
3    *  All rights reserved. This program and the accompanying materials
4    *  are made available under the terms of the LGPL License v2.1
5    *  which accompanies this distribution, and is available at
6    *  http://www.gnu.org/licenses/lgpl.html
7    *******************************************************************************/
8   package it.imolinfo.jbi4ejb.jbi.wsdl;
9   
10  import it.imolinfo.jbi4ejb.Logger;
11  import it.imolinfo.jbi4ejb.LoggerFactory;
12  import it.imolinfo.jbi4ejb.exception.EJBDeployException;
13  import it.imolinfo.jbi4ejb.jbi.Messages;
14  import it.imolinfo.jbi4ejb.jbi.component.runtime.DefaultMessageExchangeHandler;
15  import it.imolinfo.jbi4ejb.runtime.ejbproxy.EJBProxyUtils;
16  
17  import java.io.File;
18  import java.io.FileWriter;
19  import java.io.IOException;
20  
21  import javax.wsdl.Binding;
22  import javax.wsdl.BindingInput;
23  import javax.wsdl.BindingOperation;
24  import javax.wsdl.BindingOutput;
25  import javax.wsdl.Definition;
26  import javax.wsdl.Port;
27  import javax.wsdl.Service;
28  import javax.wsdl.WSDLException;
29  import javax.wsdl.extensions.ExtensionRegistry;
30  import javax.wsdl.extensions.soap.SOAPAddress;
31  import javax.wsdl.extensions.soap.SOAPBinding;
32  import javax.wsdl.extensions.soap.SOAPBody;
33  import javax.wsdl.extensions.soap.SOAPOperation;
34  import javax.wsdl.factory.WSDLFactory;
35  import javax.wsdl.xml.WSDLReader;
36  import javax.wsdl.xml.WSDLWriter;
37  import javax.xml.namespace.QName;
38  
39  import com.ibm.wsdl.Constants;
40  import com.ibm.wsdl.factory.WSDLFactoryImpl;
41  
42  /**
43   * Utility class to add the SOAP extensions (needed by xfire to correctly generate the sources).
44   * 
45   * @author <a href="mailto:mpiraccini@imolinfo.it">Marco Piraccini</a>s
46   */
47  public final class Jbi4EjbSOAPExtensionsUtils {      
48  
49      /** The logger. */
50      private static final Logger LOG
51      = LoggerFactory.getLogger(EJBProxyUtils.class);    
52      private static final Messages MESSAGES 
53      = Messages.getMessages(Jbi4EjbSOAPExtensionsUtils.class);   
54  
55      /**
56       * The standard SOAP namespace URI used in WSDL files.
57       */
58      private static final String SOAP_NAMESPACE_URI
59      = "http://schemas.xmlsoap.org/wsdl/soap/";
60  
61      /**
62       * The standard SOAP address element name used in WSDL files.
63       */
64      private static final QName SOAP_ADDRESS_QNAME
65      = new QName(SOAP_NAMESPACE_URI, "address");
66  
67      /**
68       * The standard SOAP binding element name used in WSDL files.
69       */
70      private static final QName SOAP_BINDING_QNAME
71      = new QName(SOAP_NAMESPACE_URI, "binding");
72  
73      /**
74       * The standard SOAP body element name used in WSDL files.
75       */
76      private static final QName SOAP_BODY_QNAME
77      = new QName(SOAP_NAMESPACE_URI, "body");
78  
79      /**
80       * The standard SOAP operation element name used in WSDL files.
81       */
82      private static final QName SOAP_OPERATION_QNAME
83      = new QName(SOAP_NAMESPACE_URI, "operation");
84  
85      /**
86       * Instantiates a new jbi4 ejb SOAP extensions utils.
87       */
88      private Jbi4EjbSOAPExtensionsUtils() {}
89  
90      
91      /**
92       * Creates a wsdl file, adding the SOAP extension elements.
93       * 
94       * @param wsdl the wsdl file
95       * 
96       * @return the file
97       * 
98       * @throws EJBDeployException if some problem occurs
99       */
100     public static File addSoapElements(final File wsdl) throws EJBDeployException {
101         
102         File wsdlWithSoap = new File(wsdl.getAbsolutePath()+"_soap_");       
103 
104         Definition wsdlDef = null;
105         try {
106             // Reads the definition
107             wsdlDef = readWsdl(wsdl);
108 
109             // Adds the SOAP elements
110             addSoapElements(wsdlDef);
111 
112             // Wrotes the definition on the file
113             writeWsdl(wsdlDef, wsdlWithSoap);
114 
115 
116         } catch (WSDLException wex) {
117         	String msg=MESSAGES.getString("EJB000402_Jbi4EjbSOAPExtensionsUtils", new Object[]{wex.getMessage()});
118             LOG.error(msg);
119             throw new EJBDeployException(msg);   
120 
121         }        
122 
123         return wsdlWithSoap;
124     }
125 
126 
127     /**
128      * Adds SOAP elements to the specified WSDL if they are not present.
129      *
130      * @param   def            the WSDL to add SOAP elements. Must be not
131      *                         <code>null</code>.
132      * @throws  WSDLException  in case of error manipulating the
133      *                         <code>Definition</code>.
134      */
135     public static void addSoapElements(final Definition def)
136     throws WSDLException {
137         boolean soapFound = false;
138         Port port = null;
139         WSDLFactory factory = WSDLFactory.newInstance();        
140 
141         for (Object service : def.getServices().values()) {
142             for (Object obj : ((Service) service).getPorts().values()) {
143                 port = (Port) obj;
144                 for (Object element : port.getExtensibilityElements()) {
145                     if (element instanceof SOAPAddress) {
146                         soapFound = true;
147                         break;
148                     }
149                 }
150             }
151         }
152 
153         if (!soapFound) {
154             ExtensionRegistry registry
155             = factory.newPopulatedExtensionRegistry();
156             SOAPAddress soapAddress = (SOAPAddress)
157             registry.createExtension(Port.class, SOAP_ADDRESS_QNAME);
158             SOAPBinding soapBinding = (SOAPBinding)
159             registry.createExtension(Binding.class, SOAP_BINDING_QNAME);
160             SOAPBody inputBody = (SOAPBody) registry.createExtension(
161                     BindingInput.class, SOAP_BODY_QNAME);
162             SOAPOperation soapOperation
163             = (SOAPOperation) registry.createExtension(
164                     BindingOperation.class, SOAP_OPERATION_QNAME);
165             
166             // XXX Take first BindingOperation: what if they're more than one?
167             BindingOperation bo = (BindingOperation)
168             port.getBinding().getBindingOperations().get(0);
169 
170             soapAddress.setLocationURI("http://localhost/fake_location");
171             port.addExtensibilityElement(soapAddress);
172 
173             soapBinding.setTransportURI("http://schemas.xmlsoap.org/soap/http");
174             soapBinding.setStyle("document");
175             port.getBinding().addExtensibilityElement(soapBinding);
176 
177             soapOperation.setSoapActionURI("");
178             bo.addExtensibilityElement(soapOperation);
179 
180             inputBody.setUse("literal");
181             addSoapBodyIfNotPresent(bo.getBindingInput(), inputBody);
182             addSoapBodyIfNotPresent(bo.getBindingOutput(), inputBody);
183         }
184 
185     }
186 
187     /**
188      * Adds the SOAP body if not present.
189      * @param bindingInput the binding input
190      * @param soapBody the soap body
191      */
192     private static void addSoapBodyIfNotPresent(
193             final BindingInput bindingInput, final SOAPBody soapBody) {
194         for (Object obj : bindingInput.getExtensibilityElements()) {
195             if (obj instanceof SOAPBody) {
196                 return;
197             }
198         }
199         bindingInput.addExtensibilityElement(soapBody);
200     }
201 
202     /**
203      * Adds the SOAP body if not present.
204      * @param bindingOutput the binding output
205      * @param soapBody the soap body
206      */
207     private static void addSoapBodyIfNotPresent(
208             final BindingOutput bindingOutput, final SOAPBody soapBody) {
209         for (Object obj : bindingOutput.getExtensibilityElements()) {
210             if (obj instanceof SOAPBody) {
211                 return;
212             }
213         }
214         bindingOutput.addExtensibilityElement(soapBody);
215     }    
216 
217     /**
218      * Reads a <code>Definition</code> from a <code>File</code>.
219      * @param wsdlFile the WSDL file
220      * @throws javax.wsdl.WSDLException if some problem occurs
221      * @return the WSDL Definitions
222      */
223     private static Definition readWsdl(final File wsdlFile) throws WSDLException {
224         final WSDLFactory wsdlFactory = WSDLFactory.newInstance();
225         ExtensionRegistry registry = wsdlFactory
226             .newPopulatedExtensionRegistry();
227         final WSDLReader reader = ((WSDLFactoryImpl) wsdlFactory)
228         .newWSDLReader();
229         reader.setFeature(Constants.FEATURE_VERBOSE, false);
230         reader.setFeature(Constants.FEATURE_IMPORT_DOCUMENTS, true);
231         Jbi4EjbExtension.register(registry);
232         LOG.debug("Extension QName: " + Jbi4EjbExtension.NS_URI_JBI4EJB);
233         reader.setExtensionRegistry(registry);
234         final Definition def = reader.readWSDL(wsdlFile.getAbsolutePath());
235         return def;
236     }
237     
238     /**
239      * Writes a <code>Definition</code> to a <code>File</code>.
240      * @param def the WSDL definition
241      * @param wsdlFile the file  where the WSDL is written
242      * @return
243      * @throws javax.wsdl.WSDLException if soem problem occurs in reading the WSDL definition
244      * @throws EJBDeployException if some generic problem occurs
245      */
246     private static void writeWsdl(Definition def, final File wsdlFile) throws WSDLException, EJBDeployException {
247         
248         FileWriter fr = null;
249         try {
250             fr = new FileWriter(wsdlFile);
251         } catch (IOException e) {
252         	String msg=MESSAGES.getString("EJB000402_Jbi4EjbSOAPExtensionsUtils", new Object[]{e.getMessage()});
253             LOG.error(msg);
254             throw new EJBDeployException(msg); 
255         }
256         final WSDLFactory wsdlFactory = WSDLFactory.newInstance();
257         ExtensionRegistry registry = wsdlFactory
258             .newPopulatedExtensionRegistry();
259         final WSDLReader reader = ((WSDLFactoryImpl) wsdlFactory)
260             .newWSDLReader();
261         reader.setFeature(Constants.FEATURE_VERBOSE, false);
262         reader.setFeature(Constants.FEATURE_IMPORT_DOCUMENTS, true);
263         Jbi4EjbExtension.register(registry);
264         LOG.debug("Extension QName: " + Jbi4EjbExtension.NS_URI_JBI4EJB);
265         reader.setExtensionRegistry(registry);               
266         
267         WSDLWriter writer = wsdlFactory.newWSDLWriter();
268         LOG.debug("Writing WSDL: " + wsdlFile.getAbsolutePath());
269         writer.writeWSDL(def, fr);
270         try {
271             fr.flush();
272         } catch (IOException e) {
273         	String msg=MESSAGES.getString("EJB000402_Jbi4EjbSOAPExtensionsUtils", new Object[]{e.getMessage()});
274             LOG.error(msg);
275             throw new EJBDeployException(msg); 
276         }
277         
278     }
279 
280 }