View Javadoc

1   /*******************************************************************************
2    *  Copyright (c) 2005, 2006 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.jbi4cics.jbi;
9   
10  import it.imolinfo.jbi4cics.Logger;
11  import it.imolinfo.jbi4cics.LoggerFactory;
12  import it.imolinfo.jbi4cics.jbi.processor.wsdl11wrapper.WrapperUtil;
13  import it.imolinfo.jbi4cics.jbi.xfire.JbiTransport;
14  
15  import java.io.ByteArrayOutputStream;
16  import java.io.StringWriter;
17  import java.util.Iterator;
18  import java.util.List;
19  
20  import javax.activation.DataHandler;
21  import javax.jbi.messaging.DeliveryChannel;
22  import javax.jbi.messaging.ExchangeStatus;
23  import javax.jbi.messaging.Fault;
24  import javax.jbi.messaging.InOptionalOut;
25  import javax.jbi.messaging.InOut;
26  import javax.jbi.messaging.MessageExchange;
27  import javax.jbi.messaging.NormalizedMessage;
28  import javax.xml.namespace.QName;
29  import javax.xml.stream.XMLOutputFactory;
30  import javax.xml.stream.XMLStreamException;
31  import javax.xml.stream.XMLStreamReader;
32  import javax.xml.stream.XMLStreamWriter;
33  import javax.xml.transform.Source;
34  import javax.xml.transform.TransformerException;
35  
36  import org.apache.servicemix.common.ExchangeProcessor;
37  import org.apache.servicemix.jbi.jaxp.SourceTransformer;
38  import org.apache.servicemix.jbi.jaxp.StAXSourceTransformer;
39  import org.apache.servicemix.jbi.jaxp.StringSource;
40  import org.codehaus.xfire.MessageContext;
41  import org.codehaus.xfire.XFire;
42  import org.codehaus.xfire.attachments.Attachment;
43  import org.codehaus.xfire.attachments.Attachments;
44  import org.codehaus.xfire.attachments.JavaMailAttachments;
45  import org.codehaus.xfire.attachments.SimpleAttachment;
46  import org.codehaus.xfire.exchange.InMessage;
47  import org.codehaus.xfire.fault.XFireFault;
48  import org.codehaus.xfire.service.OperationInfo;
49  import org.codehaus.xfire.service.Service;
50  import org.codehaus.xfire.transport.Channel;
51  import org.codehaus.xfire.transport.Transport;
52  import org.codehaus.xfire.util.jdom.StaxSerializer;
53  import org.jdom.Element;
54  
55  public class Jbi4cicsExchangeProcessor implements ExchangeProcessor {
56    
57    /**
58     * The logger for this class and its instances.
59     */
60    private static final Logger LOG
61            = LoggerFactory.getLogger(Jbi4cicsExchangeProcessor.class);
62    
63    /**
64     * The responsible to translate localized messages.
65     */
66    private static final Messages MESSAGES
67            = Messages.getMessages(Jbi4cicsExchangeProcessor.class);
68  
69    public static final String SOAP_FAULT_CODE = "org.apache.servicemix.soap.fault.code"; 
70    public static final String SOAP_FAULT_SUBCODE = "org.apache.servicemix.soap.fault.subcode";
71    public static final String SOAP_FAULT_REASON = "org.apache.servicemix.soap.fault.reason";
72    public static final String SOAP_FAULT_NODE = "org.apache.servicemix.soap.fault.node";
73    public static final String SOAP_FAULT_ROLE = "org.apache.servicemix.soap.fault.role";
74    
75    protected DeliveryChannel channel;
76    protected Jbi4cicsEndpoint endpoint;
77    protected StAXSourceTransformer transformer;
78    
79    public Jbi4cicsExchangeProcessor(Jbi4cicsEndpoint endpoint) {
80        this.endpoint = endpoint;
81        this.transformer = new StAXSourceTransformer();
82    }
83  
84    public void process(MessageExchange exchange) throws Exception {
85        
86        // true, if the recieved message is a wsdl-11-wrappedm message
87        boolean messageWrapped = false;
88        
89        if (exchange.getStatus() == ExchangeStatus.DONE) {
90            return;
91        } else if (exchange.getStatus() == ExchangeStatus.ERROR) {
92            return;
93        }
94  
95        // TODO: clean this code
96        XFire xfire = endpoint.getXFire();
97        Service service = endpoint.getXFireService();
98        Transport t = xfire.getTransportManager().getTransport(JbiTransport.JBI_BINDING);
99        ByteArrayOutputStream out = new ByteArrayOutputStream();
100       Channel c = t.createChannel();
101       MessageContext ctx = new MessageContext();
102       ctx.setXFire(xfire);
103       ctx.setService(service);
104       ctx.setProperty(Channel.BACKCHANNEL_URI, out);
105       ctx.setExchange(new org.codehaus.xfire.exchange.MessageExchange(ctx));
106       InMessage msg = new InMessage();
107       ctx.getExchange().setInMessage(msg);
108       if (exchange.getOperation() != null) {
109           OperationInfo op = service.getServiceInfo().getOperation(exchange.getOperation().getLocalPart());
110           if (op != null) {
111               ctx.getExchange().setOperation(op);
112           }
113       }
114       ctx.setCurrentMessage(msg);
115       NormalizedMessage in = exchange.getMessage("in");
116       
117       Source inStr = new StringSource(in.toString());
118     
119       LOG.debug("in.getContent:" + in.getContent().getClass().getName());
120       LOG.debug("inStr:" + inStr); 
121       
122       
123       SourceTransformer sourceTransformer = new SourceTransformer();
124       String receivedMessage = sourceTransformer.contentToString(in);
125       
126       LOG.debug("Received InMessage: " + receivedMessage);
127       
128       
129       // Tests if the message is a wsdl-11-wrapped
130       // Document inMessageDoc = getXMLDom(in.getContent());
131       XMLStreamReader xmlStreamReader = getXMLStreamReader(in.getContent());
132       
133       messageWrapped = WrapperUtil.isMessageWrapped(xmlStreamReader);
134       
135       LOG.debug("IsMessage Wrapped: " + messageWrapped);      
136       if (messageWrapped) {
137           LOG.debug("Message to be unwrapped");
138           // If its a wsdl-11-wrapped message, unwraps-it
139           msg.setXMLStreamReader(WrapperUtil.unWrapMessage(xmlStreamReader));
140       } else {
141           LOG.debug("Before setting stream reader");          
142           msg.setXMLStreamReader(getXMLStreamReader(new StringSource(receivedMessage)));
143       }     
144       
145       if (in.getAttachmentNames() != null && in.getAttachmentNames().size() > 0) {
146           JavaMailAttachments attachments = new JavaMailAttachments();
147           for (Iterator it = in.getAttachmentNames().iterator(); it.hasNext();) {
148               String name = (String) it.next();
149               DataHandler dh = in.getAttachment(name);
150               attachments.addPart(new SimpleAttachment(name, dh));
151           }
152           msg.setAttachments(attachments);
153       }
154       c.receive(ctx, msg);
155       c.close();
156       
157       // Set response or DONE status
158       if (isInAndOut(exchange)) {
159           if (ctx.getExchange().hasFaultMessage() && ctx.getExchange().getFaultMessage().getBody() != null) {              
160               
161               Fault fault = exchange.createFault();                           
162 
163               // The XFireFault is a SOAP Fault wrapper
164               XFireFault xFault = (XFireFault) ctx.getExchange().getFaultMessage().getBody();                    
165 
166               // If the XFireFault has details, the Fault is declared.              
167               if (xFault.hasDetails()) {
168                   // Serialize correctly the fault to a SOAP message
169                   Source faultSource = createJBIFaultSourceFromSOAPFault(ctx);                                                                             
170                   fault.setContent(faultSource);       
171                   
172                   exchange.setFault(fault);                  
173               } else {   
174                   // Sets the cause. Notice that (from the specs):
175                   // Used to specify the source of a failure status. Invoking this method automatically adjusts the status of the
176                   // ME to ExchangeStatus.ERROR.
177                   // So, the cause can be setted only if no Fault is setted.
178 
179                   if (xFault.getCause() instanceof Exception) {
180                       exchange.setError((Exception) xFault.getCause());
181                   } else {
182                       exchange.setError(new Exception(xFault.getCause()));
183                   }
184               }
185                                                                                                                                                                                                                                                   
186           } else {
187               String charSet = ctx.getOutMessage().getEncoding();
188               
189               NormalizedMessage outMsg = exchange.createMessage();
190               Attachments attachments = ctx.getCurrentMessage().getAttachments();
191               if (attachments != null) {
192                   for (Iterator it = attachments.getParts(); it.hasNext();) {
193                       Attachment att = (Attachment) it.next();
194                       outMsg.addAttachment(att.getId(), att.getDataHandler());
195                   }
196               }
197               
198               LOG.debug("Output message(before wrapping): " + out);
199               
200               OperationInfo op = service.getServiceInfo().getOperation(exchange.getOperation().getLocalPart());
201               QName messageQName = op.getOutputMessage().getName();
202               
203               // Ok for the operation Name.
204               // If the in-message is wrapped, also the response should be wrapped.
205               Source msgSource = null;
206               if (messageWrapped) {
207                   msgSource = WrapperUtil.jbiMessageWrapper(out.toString(charSet), messageQName, op.getName());
208               } else {
209                   msgSource = new StringSource(out.toString(charSet));
210               }                                                           
211               
212               outMsg.setContent(msgSource);
213               
214               LOG.debug("Sending outMessage: " + sourceTransformer.contentToString(outMsg));  
215               
216               exchange.setMessage(outMsg, "out");
217           }
218       } else {
219           exchange.setStatus(ExchangeStatus.DONE);
220       }
221       channel.send(exchange);
222   }
223 
224   public void start() throws Exception {
225       channel = endpoint.getServiceUnit().getComponent().getComponentContext().getDeliveryChannel();
226   }
227 
228   public void stop() throws Exception {
229   }
230 
231   protected XMLStreamReader getXMLStreamReader(Source source) throws TransformerException, XMLStreamException {
232       return transformer.toXMLStreamReader(source);
233   }
234   
235   protected boolean isInAndOut(MessageExchange exchange) {
236       return exchange instanceof InOut || exchange instanceof InOptionalOut;
237   }
238    
239   
240   /**
241    * Create a JBI Fault <code>Source</code> using the XFireFault details. 
242    * @return Source    The source
243    * @param  ctx    The message context
244    * @throws XMLStreamException    The XML Stream Exception
245    * @throws XFireFault    The XFire Foult Exception 
246    */
247   private Source createJBIFaultSourceFromSOAPFault(MessageContext ctx) throws XMLStreamException, XFireFault {
248 
249       StringWriter strWriter = new StringWriter();
250       XMLOutputFactory witerFactory = XMLOutputFactory.newInstance();                           
251       XMLStreamWriter writer = witerFactory.createXMLStreamWriter(strWriter);
252       XFireFault fault = (XFireFault) ctx.getExchange().getFaultMessage().getBody();
253       
254       if (fault.hasDetails())
255       {
256           Element detail = fault.getDetail();                   
257           StaxSerializer serializer = new StaxSerializer();
258           List details = detail.getContent();
259           for (int i = 0; i < details.size(); i++)
260           {
261               serializer.writeElement((Element) details.get(i), writer);
262           }
263 
264       }                       
265       writer.flush();                  
266       StringSource stringSource = new StringSource(strWriter.toString());
267        
268       LOG.debug("Fault message produced: " + stringSource);
269       
270       return stringSource;
271   }
272   
273 
274 }