View Javadoc

1   package it.imolinfo.jbi4cics.jbi.processor.wsdl11wrapper;
2   
3   import it.imolinfo.jbi4cics.Logger;
4   import it.imolinfo.jbi4cics.LoggerFactory;
5   
6   import java.io.ByteArrayOutputStream;
7   import java.io.IOException;
8   import java.io.StringReader;
9   import java.io.UnsupportedEncodingException;
10  
11  import javax.xml.namespace.QName;
12  import javax.xml.parsers.DocumentBuilder;
13  import javax.xml.parsers.DocumentBuilderFactory;
14  import javax.xml.parsers.ParserConfigurationException;
15  import javax.xml.stream.XMLInputFactory;
16  import javax.xml.stream.XMLStreamException;
17  import javax.xml.stream.XMLStreamReader;
18  import javax.xml.transform.OutputKeys;
19  import javax.xml.transform.Source;
20  import javax.xml.transform.Transformer;
21  import javax.xml.transform.TransformerException;
22  import javax.xml.transform.TransformerFactory;
23  import javax.xml.transform.TransformerFactoryConfigurationError;
24  import javax.xml.transform.dom.DOMSource;
25  import javax.xml.transform.stream.StreamResult;
26  
27  import org.apache.servicemix.jbi.jaxp.StringSource;
28  import org.codehaus.xfire.util.STAXUtils;
29  import org.w3c.dom.Document;
30  import org.w3c.dom.Element;
31  import org.w3c.dom.Node;
32  import org.w3c.dom.NodeList;
33  import org.xml.sax.InputSource;
34  import org.xml.sax.SAXException;
35  
36  /*
37   * WrapperUtil.java
38   *
39   * Created on August 12, 2005, 2:00 PM
40   *
41   * @author Sun Microsystems
42   */
43  public class WrapperUtil {
44  	
45  	/**
46       * The logger for this class and its instances.
47       */
48      private static final Logger LOG
49              = LoggerFactory.getLogger(WrapperUtil.class);
50      
51      /**
52       * Constants to build wsdl 1.1 wrapper, e.g. along the lines of <jbi:message
53       * version="1.0" type="wsdl:input wsdl:output or wsdl:fault message
54       * attribute value QNAME" name="optional name attribute from wsdl:input
55       * etc." xmlns:jbi="http://java.sun.com/xml/ns/jbi/wsdl-11-wrapper">
56       * <jbi:part> </jbi:part> <jbi:part> </jbi:part> </jbi:message>
57       */
58      public static final String WRAPPER_DEFAULT_NAMESPACE_PREFIX = "jbi";
59  
60      public static final String WRAPPER_DEFAULT_NAMESPACE = "http://java.sun.com/xml/ns/jbi/wsdl-11-wrapper";
61  
62      public static final String WRAPPER_MESSAGE = "jbi:message";
63  
64      public static final String WRAPPER_ATTRIBUTE_VERSION = "version";
65  
66      public static final String WRAPPER_ATTRIBUTE_VERSION_VALUE = "1.0";
67  
68      public static final String WRAPPER_ATTRIBUTE_TYPE = "type";
69  
70      public static final String WRAPPER_ATTRIBUTE_NAME = "name";
71  
72      public static final String WRAPPER_PART = "jbi:part";
73  
74  	
75  	/**
76  	 * void constructor.
77  	 */
78  	  public WrapperUtil(){
79  	  }
80  
81      
82      /**
83       * Creates and returns a JBI message wrapper element. Does NOT add the
84       * created element to the normalDoc - nor does it popluate the wrapper
85       * element with a payload
86       *
87       * @param normalDoc
88       *            The target document of the normalization
89       * @param type
90       *            qualified message name defined in the portmap definition for a
91       *            given message
92       * @param name
93       *            optional name attribute defined in the portmap definition for
94       *            a given message
95       * @return the jbi message wrapper element
96       */
97      public static Element createJBIMessageWrapper(Document normalDoc,
98              QName type, String name) {
99  
100         Element msgWrapper = normalDoc.createElementNS(
101                 WRAPPER_DEFAULT_NAMESPACE, WRAPPER_MESSAGE);
102         msgWrapper.setAttribute(WRAPPER_ATTRIBUTE_VERSION,
103                 WRAPPER_ATTRIBUTE_VERSION_VALUE);
104         String prefix = type.getPrefix();
105         if (prefix == null || prefix.length() == 0) {
106             prefix = "msgns";
107         }
108         msgWrapper.setAttribute(WRAPPER_ATTRIBUTE_TYPE, prefix + ":"
109                 + type.getLocalPart());
110         msgWrapper.setAttribute("xmlns:" + prefix, type.getNamespaceURI());
111         if (name != null) {
112             msgWrapper.setAttribute(WRAPPER_ATTRIBUTE_NAME, name);
113         }
114 
115         return msgWrapper;
116     }
117 
118     /**
119      * Creates and returns a JBI part wrapper element. Does NOT add the created
120      * element to the normalDoc.
121      *
122      * @param normalDoc
123      *            The target document of the normalization
124      * @param part
125      *            the part payload which must be created by normalDoc
126      * @return wrapperElem     
127      *            The craeted JBI wrapped part
128      */
129     public static Element createJBIWrappedPart(Document normalDoc, Node part) {
130         Element wrapperElem = normalDoc.createElementNS(
131                 WRAPPER_DEFAULT_NAMESPACE, WRAPPER_PART);
132         if (part != null) {
133             wrapperElem.appendChild(part);
134         }
135         return wrapperElem;
136     }
137 
138     /**
139      * Creates and returns a JBI part wrapper element. Does NOT add the created
140      * element to the normalDoc.
141      *
142      * @param normalDoc
143      *            The target document of the normalization
144      * @param part
145      *            the part payload which must be created by normalDoc
146      * @return wrapperElem
147      *            the created JBI wrapped part
148      */
149     public static Element createJBIWrappedPart(Document normalDoc, NodeList part) {
150         Element wrapperElem = normalDoc.createElementNS(
151                 WRAPPER_DEFAULT_NAMESPACE, WRAPPER_PART);
152         if (part != null) {
153             int noOfNodes = part.getLength();
154             for (int nodeCount = 0; nodeCount < noOfNodes; nodeCount++) {
155                 wrapperElem.appendChild(part.item(nodeCount));
156             }
157         }
158         return wrapperElem;
159     }
160 
161     /**
162      * Creates and returns a JBI part wrapper element. Does NOT add the created
163      * element to the normalDoc.
164      *
165      * @param normalDoc
166      *            The target document of the normalization
167      * @param part
168      *            the part payload which need not be created by normalDoc
169      * @return wrapperElem
170      *            the created JBI wrapped part
171      */
172     public static Element importJBIWrappedPart(Document normalDoc, Node part) {
173         Element wrapperElem = normalDoc.createElementNS(
174                 WRAPPER_DEFAULT_NAMESPACE, WRAPPER_PART);
175         if (part != null) {
176             Node importedPartNode = normalDoc.importNode(part, true);
177             wrapperElem.appendChild(importedPartNode);
178         }
179         return wrapperElem;
180     }
181 
182     /**
183      * Creates and returns a JBI part wrapper element. Does NOT add the created
184      * element to the normalDoc.
185      *
186      * @param normalDoc
187      *            The target document of the normalization
188      * @param part
189      *            the part payload which need not be created by normalDoc
190      * @return wrapperElem
191      *            the created JBI wrapped part
192      */
193     public static Element importJBIWrappedPart(Document normalDoc, NodeList part) {
194         Element wrapperElem = normalDoc.createElementNS(
195                 WRAPPER_DEFAULT_NAMESPACE, WRAPPER_PART);
196         if (part != null) {
197             int noOfNodes = part.getLength();
198             for (int nodeCount = 0; nodeCount < noOfNodes; nodeCount++) {
199                 Node aNode = part.item(nodeCount);
200                 if (aNode != null) {
201                     Node importedPartNode = normalDoc.importNode(aNode, true);
202                     wrapperElem.appendChild(importedPartNode);
203                 }
204             }
205         }
206         return wrapperElem;
207     }
208 
209     /**
210      * @param doc
211      *            the message to determine whether it has a normalized WSDL 1.1
212      *            wrapper
213      * @return true if the message passed in has a WSDL 1.1 wrapper element,
214      *         false if it does not
215      */
216     public static boolean isMessageWrapped(Document doc) {
217         boolean wrapperDetected = false;
218         if (doc != null) {
219             Element jbiMessageWrapper = doc.getDocumentElement();
220             if (jbiMessageWrapper != null) {
221                 String nsURI = jbiMessageWrapper.getNamespaceURI();
222                 if (nsURI != null && nsURI.equals(WRAPPER_DEFAULT_NAMESPACE)) {
223                     wrapperDetected = true;
224                 }
225             }
226         }
227         return wrapperDetected;
228     }
229 
230     /**
231      * Gets a JBI wrapper. See JBI specs, 5.5.1.1.4
232      * TODO :CLEAN!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
233      *
234      * @param msgContent
235      *            the content message
236      * @param qName
237      *            the message namespace
238      * @param name
239      *            the message name
240      * @throws WrapperProcessingException 
241      *            the wrapper processing exception
242      * @return ret
243      *            the created JBI wrapped message
244      */
245     public static Source jbiMessageWrapper(String msgContent, QName qName,
246             String name) throws WrapperProcessingException {
247 
248         if (qName == null) {
249             throw new WrapperProcessingException("messageqName is null");
250         }
251 
252         DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
253         DocumentBuilder mBuilder;
254         try {
255             factory.isNamespaceAware();
256             mBuilder = factory.newDocumentBuilder();
257         } catch (ParserConfigurationException ex) {
258             LOG.error(ex.getMessage(), ex);
259             throw new WrapperProcessingException(ex.getMessage(), ex);
260         }
261 
262         Document normalDoc = mBuilder.newDocument();
263         Element normalRoot = null;
264 
265         // Create the jbi message wrapper
266         Element jbiMessageWrapper = WrapperUtil.createJBIMessageWrapper(
267                 normalDoc, qName, name);
268         normalDoc.appendChild(jbiMessageWrapper);
269 
270         Document msgDoc;
271         try {
272             // TODO: There must be a better way...
273             msgDoc = mBuilder.parse(new InputSource(new java.io.StringReader(
274                     msgContent)));
275 
276         } catch (IOException ex) {
277             LOG.error(ex.getMessage(), ex);
278             throw new WrapperProcessingException(ex.getMessage(), ex);
279         } catch (SAXException ex) {
280             LOG.error(ex.getMessage(), ex);
281             throw new WrapperProcessingException(ex.getMessage(), ex);
282         }
283 
284         Element jbiMessagePart = WrapperUtil.importJBIWrappedPart(normalDoc,
285                 msgDoc.getDocumentElement());
286         jbiMessageWrapper.appendChild(jbiMessagePart);
287 
288         // TODO: To test with more than one part.
289 //                if (partDef.getElement() != null) {
290 //                    Element wrapperElem = WrapperUtil.importJBIWrappedPart(
291 //                            jbiWMDoc, doc.getDocumentElement());
292 //                    jbiWMDoc.getDocumentElement().appendChild(wrapperElem);
293 //                } else {
294 //                    Element wrapperElem = WrapperUtil.importJBIWrappedPart(
295 //                            jbiWMDoc, doc.getDocumentElement().getChildNodes());
296 //                    jbiWMDoc.getDocumentElement().appendChild(wrapperElem);
297 //                }
298 
299         try {
300             LOG.debug(toXml(normalDoc, "UTF-8", false));
301         } catch (Exception ex) {
302             LOG.error(ex.getMessage(), ex);
303             throw new WrapperProcessingException(ex.getMessage(), ex);
304         }
305 
306         return new StringSource(toXml(normalDoc, "UTF-8", false));
307     }
308 
309     /**
310      * Converts the xml documet to a String. Useful for logging.
311      *
312      * @param node    The node
313      * @param encoding    The encoding
314      * @param omitXMLDeclaration   The omit XML declaration
315      * @throws WrapperProcessingException    The wrapper processing exception
316      * @return ret
317      *            the created string to Xml
318      */
319     public static String toXml(Node node, String encoding,
320             boolean omitXMLDeclaration) throws WrapperProcessingException {
321         String ret = null;
322         ByteArrayOutputStream baos = new ByteArrayOutputStream();
323         Transformer trans;
324         try {
325             trans = TransformerFactory.newInstance().newTransformer();
326 
327             trans.setOutputProperty(OutputKeys.ENCODING, encoding);
328             trans.setOutputProperty(OutputKeys.INDENT, "yes");
329             trans.setOutputProperty(
330                     "{http://xml.apache.org/xslt}indent-amount", "4");
331             trans.setOutputProperty(OutputKeys.METHOD, "xml");
332             trans.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION,
333                     omitXMLDeclaration ? "yes" : "no");
334             trans.transform(new DOMSource(node), new StreamResult(baos));
335             ret = baos.toString(encoding);
336         } catch (TransformerException ex) {
337             LOG.warn(ex.getMessage(), ex);
338         } catch (UnsupportedEncodingException ex) {
339             LOG.error(ex.getMessage(), ex);
340             throw new WrapperProcessingException(ex.getMessage(), ex);
341         } catch (TransformerFactoryConfigurationError ex) {
342             LOG.error(ex.getMessage(), ex);
343             new WrapperProcessingException(ex.getMessage(), ex);
344         }
345         return ret;
346     }
347 
348     /**
349      * @param docReader    the message to determine whether it has a normalized WSDL 1.1
350      *                     wrapper
351      * @return    true if the message passed in has a WSDL 1.1 wrapper element,
352      *            false if it does not
353      * @throws WrapperProcessingException    The wrapper processing exception
354      */
355     public static boolean isMessageWrapped(XMLStreamReader docReader)
356     throws WrapperProcessingException {
357         boolean wrapperDetected = false;
358         if (docReader != null) {
359             try {
360                 String nsURI = docReader.getNamespaceURI();
361                 if (nsURI != null && nsURI.equals(WRAPPER_DEFAULT_NAMESPACE)) {
362                     wrapperDetected = true;
363                 }
364             } catch (java.lang.IllegalStateException illex) {
365                 LOG.warn("CIC001201_IO_exception", new Object[] {illex.getMessage()}, illex);
366             }
367         }
368         return wrapperDetected;
369     }
370 
371     /**
372      * UnWraps a normalized WSDL 1.1 message
373      * TODO: Verify message parts: there must be a part element for each message part,
374      * "All logical parts of the message must appear here, in the same order as defined in the WSDL 1.1 message
375      * description referred to by the type attribute" (jbi specs - 5.5.1.1.4)
376      *
377      * TODO :CLEAN!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
378      *
379      * @param docReader
380      *            the message to determine whether it has a
381      *            wrapper
382      * @return true if the message passed in has a WSDL 1.1 wrapper element,
383      *         false if it does not
384      * @throws WrapperProcessingException The warepper process exception
385      */
386     public static XMLStreamReader unWrapMessage(XMLStreamReader docReader)
387     throws WrapperProcessingException {
388 
389         DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
390         DocumentBuilder mBuilder;
391 
392         try {
393             factory.isNamespaceAware();
394             mBuilder = factory.newDocumentBuilder();
395         } catch (ParserConfigurationException ex) {
396             ex.printStackTrace();
397             throw new WrapperProcessingException(ex);
398         }
399         Document wrappedDoc = mBuilder.newDocument();
400         try {
401             STAXUtils.readDocElements(wrappedDoc, docReader, true);
402         } catch (XMLStreamException ex) {
403             LOG.error(ex.getMessage(), ex);
404             throw new WrapperProcessingException(ex.getMessage(), ex);
405         }
406 
407         Document returnedDoc = mBuilder.newDocument();
408 
409         // Get the jbi message wrapper element
410         Element jbiMessageWrapper = wrappedDoc.getDocumentElement();
411 
412         //  Gets the wrapeed part
413         NodeList childNodes = jbiMessageWrapper.getChildNodes();
414 
415         // Extract all JBI part wrapped elements
416         for (int childCount = 0; childCount < childNodes.getLength(); childCount++) {
417             Node currNode = childNodes.item(childCount);
418             if (currNode.getNodeType() == Node.ELEMENT_NODE) {
419                 Element jbiPartWrapper = (Element) currNode;
420                 NodeList partChildNodes = jbiPartWrapper.getChildNodes();
421                 for (int i = 0; i < partChildNodes.getLength(); i++) {
422                     Node partChildNode = (Node) partChildNodes.item(i);
423                     Node importedElement = returnedDoc.importNode(partChildNode, true);
424                     returnedDoc.appendChild(importedElement);
425                 }
426             }
427         }
428 
429         // Logs the unwrapped message
430         try {
431             LOG.debug(toXml(returnedDoc, "UTF-8", false));
432         } catch (Exception ex) {
433             ex.printStackTrace();
434             throw new WrapperProcessingException(ex);
435         }
436         XMLInputFactory saxFactory = XMLInputFactory.newInstance();
437         XMLStreamReader unwrappedReader;
438         try {
439             // Temporary...
440             String xml = toXml(returnedDoc, "UTF-8", false);
441             unwrappedReader = saxFactory.createXMLStreamReader(new StringReader(xml));
442         } catch (XMLStreamException ex) {
443             ex.printStackTrace();
444             throw new WrapperProcessingException(ex);
445         }
446 
447         return unwrappedReader;
448     }
449 
450 }