KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectweb > petals > binding > axis2 > listener > soap > PetalsReceiver


1 /**
2  * PETALS - PETALS Services Platform.
3  * Copyright (c) 2006 EBM Websourcing, http://www.ebmwebsourcing.com/
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  *
18  * -------------------------------------------------------------------------
19  * $Id: Axis2BCListener.java 154 19 avr. 2006 wjoseph $
20  * -------------------------------------------------------------------------
21  */

22 package org.objectweb.petals.binding.axis2.listener.soap;
23
24 import java.io.ByteArrayInputStream JavaDoc;
25 import java.util.Map JavaDoc;
26 import java.util.logging.Level JavaDoc;
27 import java.util.logging.Logger JavaDoc;
28
29 import javax.jbi.component.ComponentContext;
30 import javax.jbi.messaging.DeliveryChannel;
31 import javax.jbi.messaging.ExchangeStatus;
32 import javax.jbi.messaging.InOptionalOut;
33 import javax.jbi.messaging.InOut;
34 import javax.jbi.messaging.MessageExchange;
35 import javax.jbi.messaging.MessageExchangeFactory;
36 import javax.jbi.messaging.MessagingException;
37 import javax.jbi.messaging.NormalizedMessage;
38 import javax.jbi.servicedesc.ServiceEndpoint;
39 import javax.xml.namespace.QName JavaDoc;
40 import javax.xml.stream.XMLInputFactory;
41 import javax.xml.stream.XMLStreamReader;
42 import javax.xml.transform.Source JavaDoc;
43 import javax.xml.transform.TransformerException JavaDoc;
44
45 import org.apache.axiom.om.OMElement;
46 import org.apache.axiom.om.impl.builder.StAXOMBuilder;
47 import org.apache.axiom.soap.SOAPBody;
48 import org.apache.axiom.soap.SOAPEnvelope;
49 import org.apache.axiom.soap.SOAPFactory;
50 import org.apache.axis2.AxisFault;
51 import org.apache.axis2.client.Options;
52 import org.apache.axis2.context.MessageContext;
53 import org.apache.axis2.description.AxisService;
54 import org.apache.axis2.engine.AxisEngine;
55 import org.apache.axis2.receivers.AbstractMessageReceiver;
56 import org.apache.axis2.util.Utils;
57 import org.objectweb.petals.binding.axis2.SOAPHelper;
58 import org.objectweb.petals.component.common.su.SimpleServiceUnitManager;
59 import org.objectweb.petals.tools.jbicommon.util.StringHelper;
60 import org.objectweb.petals.tools.jbicommon.util.XMLUtil;
61 import org.w3c.dom.Document JavaDoc;
62
63 /**
64  * The message receiver used by the binding component. The SOAP message is
65  * forwarded to the JBI endpoint.
66  *
67  * @version $Rev: 250 $ $Date: 2006-04-21 14:20:57 +0200 (ven, 21 avr 2006) $
68  * @since Petals 1.0
69  * @author alouis,wjoseph,chamerling - EBM Websourcing
70  *
71  */

72 public class PetalsReceiver extends AbstractMessageReceiver {
73
74     protected static final String JavaDoc ERROR_SERVICE_NOT_FOUND = "Requested service and/or operation not found/available";
75
76     protected static final String JavaDoc ERROR_GET_WSDL = "Error while retrieving the service WSDL";
77
78     protected static final String JavaDoc ERROR_WRONG_MESSAGE_STATUS = "JBI message has wrong status";
79
80     protected static final String JavaDoc ERROR_SERVICE_INVOKATION = "An error occured in service invokation";
81
82     protected static final String JavaDoc ERROR_CREATE_RESPONSE_FROM_DOM = "Error creating a string from a DOM service description";
83
84     protected static final String JavaDoc ERROR_CREATE_STRING_FROM_NM = "Error creating a string from normalized message";
85
86     protected Axis2ReceiverUtil axis2ReceiverUtil;
87
88     protected Logger JavaDoc log;
89
90     protected ComponentContext context;
91
92     protected DeliveryChannel channel;
93
94     protected MessageExchangeFactory exchangeFactory;
95
96     protected SimpleServiceUnitManager bindingSUM;
97
98     /**
99      * Creates a new instance of PetalsReceiver
100      *
101      * @param context
102      * @param channel
103      * @param bindingSUM
104      * @param log
105      */

106     public PetalsReceiver(ComponentContext context, DeliveryChannel channel,
107         SimpleServiceUnitManager bindingSUM, Logger JavaDoc log) {
108         super();
109         this.axis2ReceiverUtil = new Axis2ReceiverUtil();
110         this.channel = channel;
111         this.context = context;
112         this.log = log;
113         this.bindingSUM = bindingSUM;
114         this.exchangeFactory = channel.createExchangeFactory();
115     }
116
117     /*
118      * (non-Javadoc)
119      *
120      * @see org.apache.axis2.engine.MessageReceiver#receive(org.apache.axis2.context.MessageContext)
121      */

122     public final void receive(final MessageContext msgContext) throws AxisFault {
123         log.log(Level.FINE, "Receive SOAP message");
124
125         MessageContext outMsgContext = Utils
126             .createOutMessageContext(msgContext);
127         outMsgContext.getOperationContext().addMessageContext(outMsgContext);
128
129         ServiceEndpoint jbiEndpoint = findEndpoint(msgContext);
130         process(jbiEndpoint, msgContext, outMsgContext);
131
132         // send the response if required
133
if (outMsgContext.getEnvelope() != null) {
134             AxisEngine engine = new AxisEngine(msgContext.getOperationContext()
135                 .getServiceContext().getConfigurationContext());
136
137             engine.send(outMsgContext);
138         }
139     }
140
141     /**
142      * Return a new SOAP envelop from the SOAPFactory of the given
143      * MessageContext
144      *
145      * @param msgContext -
146      * not null
147      * @return a new SOAPEnvelope
148      * @throws AxisFault
149      */

150     protected SOAPEnvelope createResponseEnvelope(MessageContext msgContext)
151         throws AxisFault {
152         SOAPFactory factory = getSOAPFactory(msgContext);
153         return factory.createSOAPEnvelope();
154     }
155
156     /**
157      * Return the JBI ServiceEndpoint according to : <br>{
158      * axisService.getTargetNamespace() } axisService.getName() <br>
159      * axisService.getEndpoint()
160      *
161      * @param msgContext
162      * @return the corresponding endpoint, null if no one corresponding
163      */

164     protected ServiceEndpoint findEndpoint(MessageContext msgContext) {
165         AxisService axisService = msgContext.getAxisService();
166         String JavaDoc endpointName = axisService.getEndpoint();
167         QName JavaDoc serviceName = new QName JavaDoc(axisService.getTargetNamespace(),
168             endpointName);
169
170         return context.getEndpoint(serviceName, endpointName);
171     }
172
173     /**
174      * Create a String result from a DOM document
175      *
176      * @param document
177      * the DOM Document
178      * @return a String representation of the DOM Document
179      * @throws TransformerException
180      */

181     public String JavaDoc createStringFromDOMDocument(Document JavaDoc document)
182         throws TransformerException JavaDoc {
183         return XMLUtil.createStringFromDOMNode(document);
184     }
185
186     /**
187      * Sends the SOAPEnvelope of the resquest message directly to a JBI service
188      * and operation on the JBI container. The response message from the JBI
189      * service invocation is transmitted as an outgoing message.
190      *
191      * @param inMessage
192      * MessageContext for incoming message
193      * @param outMessage
194      * MessageContect fot outgoing message
195      * @throws AxisFault
196      * error while processing request, send the JBI Exchange,
197      * processing the JBI response, or if the JBI response is a
198      * Fault
199      */

200     public void process(ServiceEndpoint endpoint, MessageContext inContext,
201         MessageContext outContext) throws AxisFault {
202         log.log(Level.FINE, "Process SOAP request");
203
204         // Retrieve message operation and service
205
QName JavaDoc operationName = findSOAPOperation(inContext);
206         if (operationName == null) {
207             throw new AxisFault("Operation not found in message context");
208         }
209
210         MessageExchange exchange = null;
211         try {
212             exchange = createMessageExchange(inContext, endpoint, operationName);
213
214         } catch (AxisFault e) {
215             String JavaDoc errorMsg = "Error while transforming SOAP request to JBI MessageExchange";
216             log.log(Level.SEVERE, errorMsg, e);
217             throw new AxisFault(errorMsg, e);
218         }
219
220         // send the message exchange through JBI
221
// As the SOAP/HTTP request wait for a response,
222
// use the sendSynchrone MEP
223
try {
224             channel.sendSync(exchange);
225         } catch (MessagingException e) {
226             String JavaDoc errorMsg = "Error while sending message through JBI NMR.";
227             log.log(Level.SEVERE, errorMsg, e);
228             throw new AxisFault(errorMsg, e);
229         }
230
231         // process the response received from JBI NMR. The outcontext is updated
232
processJbiNmrResponse(exchange, outContext, getSOAPFactory(inContext));
233     }
234
235     /**
236      * Return the operation according to the WSAAction SOAP attribute
237      *
238      * @param inContext
239      * SOAPrequest context
240      * @return operation as QName, null if no WSAAction is specified
241      */

242     protected QName JavaDoc findSOAPOperation(MessageContext inContext) {
243         String JavaDoc operation = inContext.getWSAAction();
244         QName JavaDoc operationName = null;
245         if (!StringHelper.isNullOrEmpty(operation)) {
246             operationName = QName.valueOf(operation);
247         }
248         return operationName;
249     }
250
251     /**
252      * Process the JBI response. <br>
253      * According to the response status :
254      * <li>
255      * <ul>
256      * do nothin for DONE,
257      * </ul>
258      * <ul>
259      * throws an AxisFault for ERROR,
260      * </ul>
261      * <ul>
262      * set outContext body to a FAULT,
263      * </ul>
264      * <ul>
265      * set outContext body to the response.
266      * </ul>
267      * </li>
268      *
269      * @param exchange
270      * JBI response
271      * @param outMessage
272      * set to FAULT or OUT JBI response
273      * @param factory
274      * soap factory used to create body response
275      * @throws AxisFault
276      * with ERROR JBI status, or problem while creating response
277      */

278     protected void processJbiNmrResponse(MessageExchange exchange,
279         MessageContext outMessage, SOAPFactory factory) throws AxisFault {
280         if (exchange.getStatus().equals(ExchangeStatus.DONE)) {
281             // exchange DONE, nothing to do, no soap response
282

283         } else if (exchange.getStatus().equals(ExchangeStatus.ERROR)) {
284             // exchange ERROR: throws an axis fault
285
throw new AxisFault(exchange.getError());
286
287         } else if (exchange.getStatus().equals(ExchangeStatus.ACTIVE)) {
288             if (exchange.getFault() != null) {
289                 // exchange FAULT : return a fault message
290
try {
291                     outMessage.setEnvelope(createResponseFromNormalizedMessage(
292                         factory, exchange.getFault()));
293                 } catch (AxisFault e) {
294                     String JavaDoc errorMsg = "Error while creating SOAP Fault response.";
295                     log.log(Level.SEVERE, errorMsg, e);
296                     throw new AxisFault(errorMsg, e);
297                 }
298
299             } else {
300                 // Get the ouput message if the message is an instance of out
301
try {
302                     NormalizedMessage nm = null;
303                     if (exchange instanceof InOptionalOut) {
304                         InOptionalOut mex = (InOptionalOut) exchange;
305                         nm = mex.getOutMessage();
306                     } else if (exchange instanceof InOut) {
307                         InOut mex = (InOut) exchange;
308                         nm = mex.getOutMessage();
309                     }
310
311                     outMessage.setEnvelope(createResponseFromNormalizedMessage(
312                         factory, nm));
313
314                     SOAPHelper.copyAttachmentsFromJBIToSOAP(nm, outMessage);
315                 } catch (AxisFault e) {
316                     String JavaDoc errorMsg = "Error while creating SOAP Fault response.";
317                     log.log(Level.SEVERE, errorMsg, e);
318                     throw new AxisFault(errorMsg, e);
319                 }
320             }
321             // close the messageExchange with the JBI NMR
322
try {
323                 exchange.setStatus(ExchangeStatus.DONE);
324                 channel.send(exchange);
325             } catch (MessagingException e) {
326                 String JavaDoc errorMsg = "Error while closing JBI MessageExchange.";
327                 log.log(Level.SEVERE, errorMsg, e);
328                 throw new AxisFault(errorMsg, e);
329             }
330
331         } else {
332             throw new AxisFault(ERROR_WRONG_MESSAGE_STATUS);
333         }
334
335     }
336
337     /**
338      * Creates a SOAP response from a NormalizedMessage
339      *
340      * @param factory
341      * soap factory
342      * @param nm2
343      * NormalizedMessage containing the response
344      * @return a SOAPEnveloppe created from the nm NomalizedMessage content
345      * @throws AxisFault
346      */

347     protected SOAPEnvelope createResponseFromNormalizedMessage(
348         SOAPFactory factory, NormalizedMessage nm) throws AxisFault {
349
350         SOAPEnvelope responseEnv = createSoapEnvelope(factory);
351
352         /*
353          * Create and fill the Soap body with the content of the Normalized
354          * message
355          */

356         String JavaDoc response = null;
357         if (nm != null) {
358             try {
359                 response = axis2ReceiverUtil.createStringContent(nm);
360             } catch (Exception JavaDoc e) {
361                 log.log(Level.SEVERE, ERROR_CREATE_STRING_FROM_NM);
362                 throw new AxisFault(ERROR_CREATE_STRING_FROM_NM, e);
363             }
364         } else {
365             response = "<Response>Done</Response>";
366         }
367         createSoapBody(factory, responseEnv, response);
368         return responseEnv;
369     }
370
371     /**
372      * Create a new Axis 2 SOAP body with the right name spaces and service name
373      *
374      * @param factory
375      * the soap factory
376      * @param envelope
377      * a soap envelope
378      * @param response
379      * the response
380      * @return a new soap body
381      */

382     protected OMElement createSoapBody(SOAPFactory factory,
383         SOAPEnvelope envelope, String JavaDoc response) throws AxisFault {
384         OMElement bodyContent = null;
385         ByteArrayInputStream JavaDoc inputStream = new ByteArrayInputStream JavaDoc(response
386             .getBytes());
387         try {
388             XMLStreamReader parser = XMLInputFactory.newInstance()
389                 .createXMLStreamReader(inputStream);
390             StAXOMBuilder builder = new StAXOMBuilder(factory, parser);
391             bodyContent = (OMElement) builder.getDocumentElement();
392         } catch (Exception JavaDoc e) {
393             throw new AxisFault(
394                 "Error parsing the response from JBI service to a SOAPBody", e);
395         }
396         SOAPBody respBody = factory.createSOAPBody(envelope);
397         respBody.addChild(bodyContent);
398         return respBody;
399     }
400
401     /**
402      * Create a new Axis 2 SOAP envelope with the right name spaces
403      *
404      * @param factory
405      * the soap factory; there are ex
406      * @param namespaces
407      * name spaces for the soap envelope
408      * @return a new SOAP envelope
409      */

410     protected SOAPEnvelope createSoapEnvelope(SOAPFactory factory) {
411         return factory.createSOAPEnvelope();
412     }
413
414     /**
415      * Create the message to be send through JBI.
416      *
417      * @param inContext
418      * @param endpoint
419      * @param operationName
420      * @return
421      * @throws AxisFault
422      */

423     protected MessageExchange createMessageExchange(MessageContext inContext,
424         ServiceEndpoint endpoint, QName JavaDoc operationName) throws AxisFault {
425         InOptionalOut exchange = null;
426         NormalizedMessage nm = null;
427
428         try {
429             
430             // create an inoptional out message
431
// TODO : get good MEP (feature request 306593)
432
Source JavaDoc source = axis2ReceiverUtil.createSourceContent(inContext);
433             exchange = exchangeFactory.createInOptionalOutExchange();
434             nm = exchange.createMessage();
435             exchange.setInMessage(nm);
436             nm.setContent(source);
437             exchange.setEndpoint(endpoint);
438             exchange.setOperation(operationName);
439
440             // add SOAP attachements to normalized message
441
SOAPHelper.copyAttachmentsFromSOAPToJBI(inContext, nm);
442
443             // Get the options from the SOAP message and put them into the JBI
444
// message
445
addOptions(inContext, exchange);
446
447         } catch (Exception JavaDoc e) {
448             throw AxisFault.makeFault(e);
449         }
450
451         return exchange;
452     }
453
454     /**
455      * Add the options properties from the Axis message context to the
456      * properties of the normalized message.
457      *
458      * @param context
459      * @param message
460      */

461     protected void addOptions(MessageContext context, MessageExchange exchange) {
462         Options options = context.getOptions();
463         Map JavaDoc properties = options.getProperties();
464         for (Object JavaDoc key : properties.keySet()) {
465             exchange.setProperty(key.toString(), properties.get(key));
466         }
467     }
468 }
469
Popular Tags