KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectweb > celtix > bus > ws > rm > soap > RMSoapHandler


1 package org.objectweb.celtix.bus.ws.rm.soap;
2
3
4 import java.util.ArrayList JavaDoc;
5 import java.util.Collection JavaDoc;
6 import java.util.Iterator JavaDoc;
7 import java.util.Map JavaDoc;
8 import java.util.Set JavaDoc;
9 import java.util.logging.Level JavaDoc;
10 import java.util.logging.Logger JavaDoc;
11
12 import javax.xml.bind.JAXBContext;
13 import javax.xml.bind.JAXBElement;
14 import javax.xml.bind.JAXBException;
15 import javax.xml.bind.Marshaller;
16 import javax.xml.bind.Unmarshaller;
17 import javax.xml.namespace.QName JavaDoc;
18 import javax.xml.soap.Name JavaDoc;
19 import javax.xml.soap.SOAPEnvelope JavaDoc;
20 import javax.xml.soap.SOAPException JavaDoc;
21 import javax.xml.soap.SOAPHeader JavaDoc;
22 import javax.xml.soap.SOAPHeaderElement JavaDoc;
23 import javax.xml.soap.SOAPMessage JavaDoc;
24 import javax.xml.ws.handler.MessageContext;
25 import javax.xml.ws.handler.soap.SOAPHandler;
26 import javax.xml.ws.handler.soap.SOAPMessageContext;
27
28
29 import org.objectweb.celtix.bindings.BindingContextUtils;
30 import org.objectweb.celtix.bindings.DataBindingCallback;
31 import org.objectweb.celtix.bus.ws.addressing.ContextUtils;
32 import org.objectweb.celtix.bus.ws.rm.CreateSequenceRequest;
33 import org.objectweb.celtix.bus.ws.rm.CreateSequenceResponse;
34 import org.objectweb.celtix.bus.ws.rm.Names;
35 import org.objectweb.celtix.bus.ws.rm.RMContextUtils;
36 import org.objectweb.celtix.bus.ws.rm.RMPropertiesImpl;
37 import org.objectweb.celtix.bus.ws.rm.RMUtils;
38 import org.objectweb.celtix.bus.ws.rm.TerminateSequenceRequest;
39 import org.objectweb.celtix.common.logging.LogUtils;
40 import org.objectweb.celtix.context.ObjectMessageContext;
41 import org.objectweb.celtix.ws.addressing.AddressingProperties;
42 import org.objectweb.celtix.ws.addressing.AttributedURIType;
43 import org.objectweb.celtix.ws.rm.AckRequestedType;
44 import org.objectweb.celtix.ws.rm.RMProperties;
45 import org.objectweb.celtix.ws.rm.SequenceAcknowledgement;
46 import org.objectweb.celtix.ws.rm.SequenceType;
47
48
49 /**
50  * Protocol Handler responsible for {en|de}coding the RM
51  * Properties for {outgo|incom}ing messages.
52  */

53 public class RMSoapHandler implements SOAPHandler<SOAPMessageContext> {
54
55     private static final Logger JavaDoc LOG = LogUtils.getL7dLogger(RMSoapHandler.class);
56     private static final String JavaDoc WS_RM_PACKAGE =
57         SequenceType.class.getPackage().getName();
58     protected JAXBContext jaxbContext;
59
60     /**
61      * Constructor.
62      */

63     public RMSoapHandler() {
64     }
65
66     /**
67      * Initialize the handler.
68      */

69     public void init(Map JavaDoc<String JavaDoc, Object JavaDoc> map) {
70     }
71
72     /**
73      * @return the set of SOAP headers understood by this handler
74      */

75     public Set JavaDoc<QName JavaDoc> getHeaders() {
76         return Names.HEADERS;
77     }
78     
79     /**
80      * Invoked for normal processing of inbound and outbound messages.
81      *
82      * @param context the messsage context
83      */

84     public boolean handleMessage(SOAPMessageContext context) {
85         return mediate(context);
86     }
87
88     /**
89      * Invoked for fault processing.
90      *
91      * @param context the messsage context
92      */

93     public boolean handleFault(SOAPMessageContext context) {
94         return mediate(context);
95     }
96
97     /**
98      * Called at the conclusion of a message exchange pattern just prior to
99      * the JAX-WS runtime dispatching a message, fault or exception.
100      *
101      * @param context the message context
102      */

103     public void close(MessageContext context) {
104     }
105
106     /**
107      * Release handler resources.
108      */

109     public void destroy() {
110     }
111
112     /**
113      * Mediate message flow, peforming MAP {en|de}coding.
114      *
115      * @param context the messsage context
116      * @return true if processing should continue on dispatch path
117      */

118     private boolean mediate(SOAPMessageContext context) {
119         if (ContextUtils.isOutbound(context)) {
120             encode(context);
121         } else {
122             decode(context);
123             storeBindingInfo(context);
124         }
125         return true;
126     }
127     
128     /**
129      * Encode the current RM properties in protocol-specific headers.
130      *
131      * @param context the message context.
132      */

133     private void encode(SOAPMessageContext context) {
134         RMProperties rmps = RMContextUtils.retrieveRMProperties(context, true);
135         if (null == rmps) {
136             // nothing to encode
137
return;
138         }
139         SOAPMessage JavaDoc message = context.getMessage();
140         try {
141             SOAPEnvelope JavaDoc env = message.getSOAPPart().getEnvelope();
142             SOAPHeader JavaDoc header = env.getHeader() != null
143                                 ? env.getHeader()
144                                 : env.addHeader();
145                                 
146             discardRMHeaders(header);
147             header.addNamespaceDeclaration(Names.WSRM_NAMESPACE_PREFIX,
148                                            Names.WSRM_NAMESPACE_NAME);
149             Marshaller marshaller = getJAXBContext().createMarshaller();
150             marshaller.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE);
151            
152             SequenceType seq = rmps.getSequence();
153             if (null != seq) {
154                 encodeProperty(seq,
155                                Names.WSRM_SEQUENCE_QNAME,
156                                SequenceType.class,
157                                header,
158                                marshaller);
159             }
160             Collection JavaDoc<SequenceAcknowledgement> acks = rmps.getAcks();
161             if (null != acks) {
162                 for (SequenceAcknowledgement ack : acks) {
163                     encodeProperty(ack,
164                                    Names.WSRM_SEQUENCE_ACK_QNAME,
165                                    SequenceAcknowledgement.class,
166                                    header,
167                                    marshaller);
168                 }
169             }
170             Collection JavaDoc<AckRequestedType> requested = rmps.getAcksRequested();
171             if (null != requested) {
172                 for (AckRequestedType ar : requested) {
173                     encodeProperty(ar,
174                                    Names.WSRM_ACK_REQUESTED_QNAME,
175                                    AckRequestedType.class,
176                                    header,
177                                    marshaller);
178                 }
179             }
180         } catch (SOAPException JavaDoc se) {
181             LOG.log(Level.WARNING, "SOAP_HEADER_ENCODE_FAILURE_MSG", se);
182         } catch (JAXBException je) {
183             LOG.log(Level.WARNING, "SOAP_HEADER_ENCODE_FAILURE_MSG", je);
184         }
185     }
186     
187     /**
188      * Decode the RM properties from protocol-specific headers.
189      *
190      * @param context the messsage context
191      * @param the decoded MAPs
192      * @exception SOAPFaultException if decoded MAPs are invalid
193      */

194     private void decode(SOAPMessageContext context) {
195         SOAPMessage JavaDoc message = context.getMessage();
196         RMProperties rmps = unmarshalRMProperties(message);
197         RMContextUtils.storeRMProperties(context, rmps, false);
198     }
199     
200     /**
201      * Decode the RM properties from the SOAP message.
202      *
203      * @param message the SOAP message
204      * @return the RM properties
205      */

206     public RMProperties unmarshalRMProperties(SOAPMessage JavaDoc message) {
207         RMProperties rmps = new RMPropertiesImpl();
208         
209         try {
210             Collection JavaDoc<SequenceAcknowledgement> acks = new ArrayList JavaDoc<SequenceAcknowledgement>();
211             Collection JavaDoc<AckRequestedType> requested = new ArrayList JavaDoc<AckRequestedType>();
212             
213             SOAPEnvelope JavaDoc env = message.getSOAPPart().getEnvelope();
214             SOAPHeader JavaDoc header = env.getHeader();
215             
216             if (header != null) {
217                 Unmarshaller unmarshaller =
218                     getJAXBContext().createUnmarshaller();
219                 Iterator JavaDoc headerElements = header.examineAllHeaderElements();
220                 while (headerElements.hasNext()) {
221                     SOAPHeaderElement JavaDoc headerElement =
222                         (SOAPHeaderElement JavaDoc)headerElements.next();
223                     Name JavaDoc headerName = headerElement.getElementName();
224                     String JavaDoc localName = headerName.getLocalName();
225                     if (Names.WSRM_NAMESPACE_NAME.equals(headerName.getURI())) {
226                         LOG.log(Level.INFO, "decoding RM header {0}", localName);
227                         if (Names.WSRM_SEQUENCE_NAME.equals(localName)) {
228                             SequenceType s = decodeProperty(SequenceType.class,
229                                                             headerElement,
230                                                             unmarshaller);
231                             
232                             rmps.setSequence(s);
233                         } else if (Names.WSRM_SEQUENCE_ACK_NAME.equals(localName)) {
234                             SequenceAcknowledgement ack = decodeProperty(SequenceAcknowledgement.class,
235                                                             headerElement,
236                                                             unmarshaller);
237                             acks.add(ack);
238                         } else if (Names.WSRM_ACK_REQUESTED_NAME.equals(localName)) {
239                             AckRequestedType ar = decodeProperty(AckRequestedType.class,
240                                                             headerElement,
241                                                             unmarshaller);
242                             requested.add(ar);
243                         }
244                     }
245                 }
246                 if (acks.size() > 0) {
247                     rmps.setAcks(acks);
248                 }
249                 if (requested.size() > 0) {
250                     rmps.setAcksRequested(requested);
251                 }
252             }
253         } catch (SOAPException JavaDoc se) {
254             LOG.log(Level.WARNING, "SOAP_HEADER_DECODE_FAILURE_MSG", se);
255         } catch (JAXBException je) {
256             LOG.log(Level.WARNING, "SOAP_HEADER_DECODE_FAILURE_MSG", je);
257         }
258         return rmps;
259     }
260
261
262     /**
263      * @return a JAXBContext
264      */

265     private synchronized JAXBContext getJAXBContext() throws JAXBException {
266         if (jaxbContext == null) {
267             jaxbContext = JAXBContext.newInstance(WS_RM_PACKAGE);
268         }
269         return jaxbContext;
270     }
271     
272     /**
273      * Encodes an RM property as a SOAP header.
274      *
275      * @param value the value to encode
276      * @param qname the QName for the header
277      * @param clz the class
278      * @param header the SOAP header
279      * @param marshaller the JAXB marshaller to use
280      */

281     private <T> void encodeProperty(T value,
282                                     QName JavaDoc qname,
283                                     Class JavaDoc<T> clz,
284                                     SOAPHeader JavaDoc header,
285                                     Marshaller marshaller) throws JAXBException {
286         if (value != null) {
287             LOG.log(Level.INFO, "encoding " + value + " into RM header {0}", qname);
288             marshaller.marshal(new JAXBElement<T>(qname, clz, value), header);
289         }
290     }
291     
292     /**
293      * Decodes an RM property from a SOAP header.
294      *
295      * @param clz the class
296      * @param headerElement the SOAP header element
297      * @param marshaller the JAXB marshaller to use
298      * @return the decoded EndpointReference
299      */

300     private <T> T decodeProperty(Class JavaDoc<T> clz,
301                             SOAPHeaderElement JavaDoc headerElement,
302                             Unmarshaller unmarshaller) throws JAXBException {
303         JAXBElement<T> element =
304             unmarshaller.unmarshal(headerElement, clz);
305         return element.getValue();
306     }
307
308
309     /**
310      * Discard any pre-existing RM headers - this may occur if the runtime
311      * re-uses a SOAP message.
312      *
313      * @param header the SOAP header
314      */

315     private void discardRMHeaders(SOAPHeader JavaDoc header) throws SOAPException JavaDoc {
316         Iterator JavaDoc headerElements = header.examineAllHeaderElements();
317         while (headerElements.hasNext()) {
318             SOAPHeaderElement JavaDoc headerElement =
319                 (SOAPHeaderElement JavaDoc)headerElements.next();
320             Name JavaDoc headerName = headerElement.getElementName();
321             if (Names.WSRM_NAMESPACE_NAME.equals(headerName.getURI())) {
322                 headerElement.detachNode();
323             }
324             
325             if (org.objectweb.celtix.bus.ws.addressing.Names.WSA_NAMESPACE_NAME
326                 .equals(headerName.getURI())
327                 && org.objectweb.celtix.bus.ws.addressing.Names.WSA_ACTION_NAME
328                 .equals(headerName.getLocalName())) {
329                 headerElement.detachNode();
330             }
331         }
332     }
333     
334     /**
335      * When invoked inbound, check if the action indicates that this is one of the
336      * RM protocol messages (CreateSequence, CreateSequenceResponse, TerminateSequence)
337      * and if so, store method, operation name and data binding callback in the context.
338      * The action has already been extracted from its associated soap header into the
339      * addressing properties as the addressing protocol handler is executed.
340      *
341      * @param context
342      */

343     private void storeBindingInfo(MessageContext context) {
344         assert !ContextUtils.isOutbound(context);
345         AddressingProperties maps = ContextUtils.retrieveMAPs(context, false, false);
346         AttributedURIType actionURI = null == maps ? null : maps.getAction();
347         String JavaDoc action = null == actionURI ? null : actionURI.getValue();
348         DataBindingCallback callback = null;
349         String JavaDoc operationName = null;
350         boolean rmProtocolMessage = true;
351
352         if (RMUtils.getRMConstants().getCreateSequenceAction().equals(action)) {
353             callback = CreateSequenceRequest.createDataBindingCallback();
354             operationName = CreateSequenceRequest.getOperationName();
355         } else if (RMUtils.getRMConstants().getCreateSequenceResponseAction().equals(action)) {
356             callback = CreateSequenceResponse.createDataBindingCallback();
357             operationName = CreateSequenceResponse.getOperationName();
358         } else if (RMUtils.getRMConstants().getTerminateSequenceAction().equals(action)) {
359             callback = TerminateSequenceRequest.createDataBindingCallback();
360             operationName = TerminateSequenceRequest.getOperationName();
361         } else if (RMUtils.getRMConstants().getLastMessageAction().equals(action)
362             || RMUtils.getRMConstants().getSequenceAcknowledgmentAction().equals(action)) {
363             // It does not really matter what callback we are using here as the body
364
// in messages with these actions is always empty
365
callback = TerminateSequenceRequest.createDataBindingCallback();
366             operationName = TerminateSequenceRequest.getOperationName();
367         } else {
368             rmProtocolMessage = false;
369         }
370         
371         if (rmProtocolMessage) {
372             BindingContextUtils.storeDispatch(context, false);
373             BindingContextUtils.storeDataBindingCallback(context, callback);
374             context.put(MessageContext.WSDL_OPERATION, new QName JavaDoc("", operationName));
375             context.put(ObjectMessageContext.MESSAGE_INPUT, Boolean.FALSE);
376         }
377     }
378
379 }
380
381
382
383
384
385
386
Popular Tags