View Javadoc

1    /****************************************************************************
2    * Copyright (c) 2005, 2006, 2007, 2008, 2009 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   
9   package it.imolinfo.jbi4corba.jbi.processor;
10  
11  import it.imolinfo.jbi4corba.Logger;
12  import it.imolinfo.jbi4corba.LoggerFactory;
13  import it.imolinfo.jbi4corba.exception.Jbi4CorbaException;
14  import it.imolinfo.jbi4corba.jbi.Messages;
15  import it.imolinfo.jbi4corba.jbi.endpoint.Jbi4CorbaEndpoint;
16  
17  import java.util.Iterator;
18  
19  import javax.jbi.messaging.NormalizedMessage;
20  import javax.wsdl.Definition;
21  import javax.wsdl.Message;
22  import javax.wsdl.Operation;
23  import javax.wsdl.Port;
24  import javax.wsdl.PortType;
25  import javax.wsdl.Service;
26  import javax.xml.namespace.QName;
27  import javax.xml.transform.Source;
28  import javax.xml.transform.Transformer;
29  import javax.xml.transform.TransformerConfigurationException;
30  import javax.xml.transform.TransformerException;
31  import javax.xml.transform.TransformerFactory;
32  import javax.xml.transform.TransformerFactoryConfigurationError;
33  import javax.xml.transform.dom.DOMResult;
34  import javax.xml.transform.dom.DOMSource;
35  
36  import org.w3c.dom.Document;
37  import org.w3c.dom.Element;
38  import org.w3c.dom.Node;
39  import org.w3c.dom.NodeList;
40  
41  import com.sun.jbi.nms.wsdl11wrapper.HelperFactory;
42  import com.sun.jbi.nms.wsdl11wrapper.WrapperParser;
43  import com.sun.jbi.nms.wsdl11wrapper.WrapperProcessingException;
44  
45  /**
46   *  Message denormalizer class. Extract from the NRM message the message part.
47   * 
48   * @author <a href="mailto:mpiraccini@imolinfo.it">Marco Piraccini</a>
49   */
50  @SuppressWarnings("unchecked")
51  public class MessageDenormalizer {
52  
53      /** The Constant LOG. */
54      private static final Logger LOG
55          = LoggerFactory.getLogger(MessageDenormalizer.class);
56  
57      /** The wrapper parser. */
58      private WrapperParser wrapperParser = null;
59      
60      /** The m trans. */
61      private Transformer mTrans = null;   
62      
63  	/**
64  	 * The responsible to translate localized messages.
65  	 */
66  	private static final Messages MESSAGES = Messages
67  			.getMessages(MessageDenormalizer.class);
68      
69      /**
70       * Instantiates a new denormalizer.
71       *             
72       * @throws Jbi4corbaException
73       *                       if some problem occurs in denormalizing 
74       */
75      public MessageDenormalizer() throws Jbi4CorbaException {
76          
77          try {
78              wrapperParser = HelperFactory.createParser();
79          } catch (WrapperProcessingException ex) {
80              throw new Jbi4CorbaException("Failed to create WrapperParser", ex);
81          }
82          
83          try {        
84              TransformerFactory factory = TransformerFactory.newInstance();
85              mTrans = factory.newTransformer();            
86          } catch (TransformerFactoryConfigurationError ex) {
87  			String msg = MESSAGES.getString("CRB000805_Unable_to_instantiate_denormalizer");
88  			LOG.error(msg, ex.getMessage());
89              throw new Jbi4CorbaException(ex);
90          } catch (TransformerConfigurationException e) {
91  			String msg = MESSAGES.getString("CRB000805_Unable_to_instantiate_denormalizer");
92  			LOG.error(msg, e.getMessage());
93              throw new Jbi4CorbaException(e);
94          }                        
95    
96      }
97      
98          
99      /**
100      * Denormalize the message to the source. This implementation takes the
101      * first (should be the only) part
102      * 
103      * @param normalizedMessage the message to denormalize
104      * @param endpoint the endpoint invoked
105      * @param operation the opration invoked
106      * @param isInput if it's an input message
107      * @param isFault if it's a fault message
108      * 
109      * @return the <code>Jbi4corbaMessage containing the source.
110      * 
111      * @throws Jbi4CorbaException if some problem occurs in message denormalizing
112      */    
113 	public JbiMessage denormalize(NormalizedMessage normalizedMessage, 
114             Jbi4CorbaEndpoint endpoint,
115             QName operation, boolean isInput, boolean isFault) throws Jbi4CorbaException {
116 
117         try {
118             // Gets the WSDL data
119             final Service service  = endpoint.getDefinition().getService(endpoint.getServiceName());
120             final Port port = service.getPort(QName.valueOf(endpoint.getEndpointName()).getLocalPart());
121             final PortType portType = port.getBinding().getPortType();
122 
123             // Grab the operation that matches the operationName.  There actually may
124             // be more than one operation with the same name (but different input/output)
125             // names.  We need to fix this so that we uniquely identify which operation we're
126             // going after
127             final Iterator it = portType.getOperations().iterator();
128             Message wsdlMessage = null;
129             while (it.hasNext()) {
130                 final Operation op = (Operation)it.next();
131                 if (op.getName().equals(operation.toString()) ||
132                         op.getName().equals(operation.getLocalPart())) {
133                     if (!isFault) {
134                         if (isInput) {
135                             wsdlMessage = op.getInput().getMessage();
136                         } else {
137                             wsdlMessage = op.getOutput().getMessage();
138                         }
139                     } 
140                 }
141             }
142 
143             // Convert the normalizedMessage into a DOM object
144             final DOMResult result = new DOMResult();
145             final Source src = normalizedMessage.getContent();
146             if (src != null) {
147                 final TransformerFactory fact = TransformerFactory.newInstance();
148                 final Transformer transformer = fact.newTransformer();
149                 transformer.transform( src, result );
150             }
151             Node node = result.getNode();
152             Document normalizedDoc = null;
153             if (node instanceof Document) {
154                 normalizedDoc = (Document) node;
155             } else {
156                 normalizedDoc = ((Element) node).getOwnerDocument();
157             }
158 
159             // Use the WrapperParser to help in parsing out the Parts
160             if (LOG.isDebugEnabled()){
161             LOG.debug("About to denormalize: "+normalizedDoc +" for endpoint: "+endpoint+" and definition: "+endpoint.getDefinition());
162             }
163             wrapperParser.parse(normalizedDoc, endpoint.getDefinition());
164                         
165             // use helper class to parse wrapped msg
166 
167             Source source = normalizedMessage.getContent();
168 
169             if (source instanceof DOMSource) {
170                 // saves a transformation
171                 node = ((DOMSource) source).getNode();
172             } else {
173                 DOMResult domResult = new DOMResult();
174                 mTrans.transform(source, domResult);
175                 node = domResult.getNode();
176             }
177             
178             JbiMessage jbiMessage = null;
179             // Gets the JbiMessage (if input or output)
180             if (!isFault) {
181                 jbiMessage = denormalizeNode(node, wsdlMessage);
182             } else {
183                 // Gets the wrapped exception message from the definition
184                 // TODO: Verify if this is possible even for the  input/output messages. 
185                 jbiMessage = denormalizeFaultNode(node, endpoint.getDefinition());
186             }
187             
188             return jbiMessage;                    
189 
190         } catch (TransformerException ex) {
191 			String msg = MESSAGES.getString("CRB000806_Error_in_denormalizing_the_message");
192 			LOG.error(msg, ex.getMessage());
193             throw new Jbi4CorbaException(ex);
194         }
195         catch (WrapperProcessingException ex) {
196 			String msg = MESSAGES.getString("CRB000806_Error_in_denormalizing_the_message");
197 			LOG.error(msg, ex.getMessage());
198             throw new Jbi4CorbaException(ex);
199         }
200     }
201     
202     /**
203      * Denormalizes the message (DOM version). This implementation takes the
204      * first (should be the only) part
205      * 
206      * @param endpoint the endpoint invoked
207      * @param node the node
208      * @param operation
209      * @param isInput if it's an input message
210      * 
211      * @return the <code>Jbi4corbaMessage containing the source.
212      * 
213      * @throws Jbi4CorbaException if some problem occurs in message denormalizing
214      */
215 	public JbiMessage denormalize(Node node, 
216                                   Jbi4CorbaEndpoint endpoint,
217                                   QName operation, boolean isInput) throws Jbi4CorbaException {
218 
219         // Gets the WSDL data
220         final Service service  = endpoint.getDefinition().getService(endpoint.getServiceName());
221         final Port port = service.getPort(QName.valueOf(endpoint.getEndpointName()).getLocalPart());
222         final PortType portType = port.getBinding().getPortType();
223 
224         // Grab the operation that matches the operationName.  There actually may
225         // be more than one operation with the same name (but different input/output)
226         // names.  We need to fix this so that we uniquely identify which operation we're
227         // going after
228         final Iterator it = portType.getOperations().iterator();
229         Message wsdlMessage = null;
230         while (it.hasNext()) {
231             final Operation op = (Operation)it.next();
232             if (op.getName().equals(operation.toString()) ||
233                 op.getName().equals(operation.getLocalPart())) {
234                 if (isInput) {
235                     wsdlMessage = op.getInput().getMessage();
236                 } else {
237                     wsdlMessage = op.getOutput().getMessage();
238                 }
239             }
240         }
241         // Gets the JbiMessage
242         JbiMessage jbiMessage = denormalizeNode(node, wsdlMessage);
243         return jbiMessage;                    
244     }    
245     
246     /**
247      * Denormalizes the message (DOM version). 
248      * This implementation takes the first (should be the only) part
249      * 
250      * @param endpoint the endpoint invoked
251      * @param node the node
252      * @param wsdlMessage the message
253      * 
254      * @return the <code>Jbi4corbaMessage containing the source.
255      * 
256      * @throws Jbi4corbaException if some problem occurs in message denormalizing
257      * @throws Jbi4CorbaException
258      */
259     private JbiMessage denormalizeNode(Node node, Message wsdlMessage) throws Jbi4CorbaException {
260 
261         try {           
262             if (node instanceof Document) {
263                 wrapperParser.parse((Document) node, wsdlMessage);
264             } else {
265                 wrapperParser.parse(node.getOwnerDocument(), wsdlMessage);
266             }
267 
268             if (wrapperParser.getNoOfParts() != 0) {
269             // Take ALWAYS the first part
270                 String[] partNames = wrapperParser.getPartNames(); 
271                 NodeList nodes = wrapperParser.getPartNodes(partNames[0]);
272 
273                 if (nodes == null || nodes.getLength() == 0) {
274                     throw new Jbi4CorbaException("Unable to find valid part during denormalization");
275                 }
276                 // return the first node
277                 return new JbiMessage(new DOMSource(nodes.item(0)), true);
278             } else {
279                 // Support if no parts are found
280                 return new JbiMessage(new DOMSource((Document) node), false); 
281             }           
282 
283         } catch (WrapperProcessingException ex) {
284 			String msg = MESSAGES.getString("CRB000806_Error_in_denormalizing_the_message");
285 			LOG.error(msg, ex.getMessage());
286             throw new Jbi4CorbaException(ex);
287         }
288     }    
289     
290     /**
291      * Denormalizes the message (DOM version), trying the wsdl messages decription passed.
292      * This implementation takes the first (should be the only) part
293      * 
294      * @param endpoint the endpoint invoked
295      * @param node the node
296      * @param wsdlMessage the message
297      * 
298      * @return the <code>Jbi4corbaMessage containing the source.
299      * 
300      * @throws Jbi4corbaException if some problem occurs in message denormalizing
301      * @throws Jbi4CorbaException
302      */
303     private JbiMessage denormalizeFaultNode(Node node, Definition wsdlDef) throws Jbi4CorbaException {
304 
305         try {           
306             if (node instanceof Document) {
307                 wrapperParser.parse((Document) node, wsdlDef);
308             } else {
309                 wrapperParser.parse(node.getOwnerDocument(), wsdlDef);
310             }
311             if (wrapperParser.getNoOfParts() != 0) {
312                 // Message fault found.
313                 // Take ALWAYS the first part
314                 String[] partNames = wrapperParser.getPartNames(); 
315                 NodeList nodes = wrapperParser.getPartNodes(partNames[0]);                   
316                 if ((nodes != null) && (nodes.getLength() != 0)) {
317                     return new JbiMessage(new DOMSource(nodes.item(0)), true);
318                 }                    
319             }    
320 
321         } catch (WrapperProcessingException ex) {
322 			String msg = MESSAGES.getString("CRB000806_Error_in_denormalizing_the_message");
323 			LOG.error(msg, ex.getMessage());
324             throw new Jbi4CorbaException(ex);
325         }
326 
327         // If no wrap is found, returns the node
328         return new JbiMessage(new DOMSource((Document) node), false);
329     }    
330 
331 
332 }
333