KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectweb > celtix > bus > ws > addressing > soap > MAPCodec


1 package org.objectweb.celtix.bus.ws.addressing.soap;
2
3
4 import java.util.Iterator JavaDoc;
5 import java.util.Map JavaDoc;
6 import java.util.Set JavaDoc;
7 import java.util.logging.Level JavaDoc;
8 import java.util.logging.Logger JavaDoc;
9
10 import javax.xml.bind.JAXBContext;
11 import javax.xml.bind.JAXBElement;
12 import javax.xml.bind.JAXBException;
13 import javax.xml.bind.Marshaller;
14 import javax.xml.bind.Unmarshaller;
15 import javax.xml.namespace.QName JavaDoc;
16 import javax.xml.soap.MimeHeaders JavaDoc;
17 import javax.xml.soap.Name JavaDoc;
18 import javax.xml.soap.SOAPEnvelope JavaDoc;
19 import javax.xml.soap.SOAPException JavaDoc;
20 import javax.xml.soap.SOAPFactory JavaDoc;
21 import javax.xml.soap.SOAPFault JavaDoc;
22 import javax.xml.soap.SOAPHeader JavaDoc;
23 import javax.xml.soap.SOAPHeaderElement JavaDoc;
24 import javax.xml.soap.SOAPMessage JavaDoc;
25 import javax.xml.ws.handler.MessageContext;
26 import javax.xml.ws.handler.soap.SOAPHandler;
27 import javax.xml.ws.handler.soap.SOAPMessageContext;
28 import javax.xml.ws.soap.SOAPFaultException;
29
30 import org.objectweb.celtix.bus.ws.addressing.AddressingPropertiesImpl;
31 import org.objectweb.celtix.bus.ws.addressing.ContextUtils;
32 import org.objectweb.celtix.bus.ws.addressing.Names;
33 import org.objectweb.celtix.common.logging.LogUtils;
34 import org.objectweb.celtix.ws.addressing.AddressingProperties;
35 import org.objectweb.celtix.ws.addressing.AttributedURIType;
36 import org.objectweb.celtix.ws.addressing.EndpointReferenceType;
37 import org.objectweb.celtix.ws.addressing.RelatesToType;
38
39
40 /**
41  * Protocol Handler responsible for {en|de}coding the Message Addressing
42  * Properties for {outgo|incom}ing messages.
43  */

44 public class MAPCodec
45     implements SOAPHandler<SOAPMessageContext> {
46
47     private static final Logger JavaDoc LOG = LogUtils.getL7dLogger(MAPCodec.class);
48     private static SOAPFactory JavaDoc soapFactory;
49     
50     private VersionTransformer transformer;
51
52     /**
53      * Constructor.
54      */

55     public MAPCodec() {
56         transformer = new VersionTransformer(this);
57     }
58
59     /**
60      * Initialize the handler.
61      */

62     public void init(Map JavaDoc<String JavaDoc, Object JavaDoc> map) {
63     }
64
65     /**
66      * @return the set of SOAP headers understood by this handler
67      */

68     public Set JavaDoc<QName JavaDoc> getHeaders() {
69         return VersionTransformer.HEADERS;
70     }
71     
72     /**
73      * Invoked for normal processing of inbound and outbound messages.
74      *
75      * @param context the messsage context
76      */

77     public boolean handleMessage(SOAPMessageContext context) {
78         return mediate(context);
79     }
80
81     /**
82      * Invoked for fault processing.
83      *
84      * @param context the messsage context
85      */

86     public boolean handleFault(SOAPMessageContext context) {
87         return mediate(context);
88     }
89
90     /**
91      * Called at the conclusion of a message exchange pattern just prior to
92      * the JAX-WS runtime dispatching a message, fault or exception.
93      *
94      * @param context the message context
95      */

96     public void close(MessageContext context) {
97     }
98
99     /**
100      * Release handler resources.
101      */

102     public void destroy() {
103     }
104
105     /**
106      * Mediate message flow, peforming MAP {en|de}coding.
107      *
108      * @param context the messsage context
109      * @return true if processing should continue on dispatch path
110      */

111     private boolean mediate(SOAPMessageContext context) {
112         if (ContextUtils.isOutbound(context)) {
113             encode(context, ContextUtils.retrieveMAPs(context, false, true));
114         } else {
115             ContextUtils.storeMAPs(decode(context), context, false);
116         }
117         return true;
118     }
119
120     /**
121      * Encode the current MAPs in protocol-specific headers.
122      *
123      * @param context the messsage context
124      * @param maps the MAPs to encode
125      */

126     private void encode(SOAPMessageContext context,
127                         AddressingProperties maps) {
128         if (maps != null) {
129             SOAPMessage JavaDoc message = context.getMessage();
130             LOG.log(Level.INFO, "encoding MAPs in SOAP headers");
131             try {
132                 SOAPEnvelope JavaDoc env = message.getSOAPPart().getEnvelope();
133                 SOAPHeader JavaDoc header = env.getHeader() != null
134                                     ? env.getHeader()
135                                     : env.addHeader();
136                 discardMAPs(header);
137                 header.addNamespaceDeclaration(Names.WSA_NAMESPACE_PREFIX,
138                                                maps.getNamespaceURI());
139                 JAXBContext jaxbContext =
140                     VersionTransformer.getExposedJAXBContext(
141                                                      maps.getNamespaceURI());
142                 Marshaller marshaller = jaxbContext.createMarshaller();
143                 marshaller.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE);
144                 transformer.encodeAsExposed(maps.getNamespaceURI(),
145                                             maps.getMessageID(),
146                                             Names.WSA_MESSAGEID_NAME,
147                                             AttributedURIType.class,
148                                             header,
149                                             marshaller);
150                 transformer.encodeAsExposed(maps.getNamespaceURI(),
151                                             maps.getTo(),
152                                             Names.WSA_TO_NAME,
153                                             AttributedURIType.class,
154                                             header,
155                                             marshaller);
156                 transformer.encodeAsExposed(maps.getNamespaceURI(),
157                                             maps.getReplyTo(),
158                                             Names.WSA_REPLYTO_NAME,
159                                             EndpointReferenceType.class,
160                                             header,
161                                             marshaller);
162                 transformer.encodeAsExposed(maps.getNamespaceURI(),
163                                             maps.getFaultTo(),
164                                             Names.WSA_FAULTTO_NAME,
165                                             EndpointReferenceType.class,
166                                             header,
167                                             marshaller);
168                 transformer.encodeAsExposed(maps.getNamespaceURI(),
169                                             maps.getRelatesTo(),
170                                             Names.WSA_RELATESTO_NAME,
171                                             RelatesToType.class,
172                                             header,
173                                             marshaller);
174                 transformer.encodeAsExposed(maps.getNamespaceURI(),
175                                             maps.getAction(),
176                                             Names.WSA_ACTION_NAME,
177                                             AttributedURIType.class,
178                                             header,
179                                             marshaller);
180                 propogateAction(maps.getAction(), message);
181                 applyMAPValidation(context);
182             } catch (SOAPException JavaDoc se) {
183                 LOG.log(Level.WARNING, "SOAP_HEADER_ENCODE_FAILURE_MSG", se);
184             } catch (JAXBException je) {
185                 LOG.log(Level.WARNING, "SOAP_HEADER_ENCODE_FAILURE_MSG", je);
186             }
187         }
188     }
189
190     /**
191      * Decode the MAPs from protocol-specific headers.
192      *
193      * @param message the SOAP message
194      * @param the decoded MAPs
195      * @exception SOAPFaultException if decoded MAPs are invalid
196      */

197     public AddressingProperties unmarshalMAPs(SOAPMessage JavaDoc message) {
198         // REVISIT generate MessageAddressingHeaderRequired fault if an
199
// expected header is missing
200
AddressingPropertiesImpl maps = null;
201         try {
202             SOAPEnvelope JavaDoc env = message.getSOAPPart().getEnvelope();
203             SOAPHeader JavaDoc header = env.getHeader();
204             if (header != null) {
205                 Unmarshaller unmarshaller = null;
206                 Iterator JavaDoc headerElements = header.examineAllHeaderElements();
207                 while (headerElements.hasNext()) {
208                     SOAPHeaderElement JavaDoc headerElement =
209                         (SOAPHeaderElement JavaDoc)headerElements.next();
210                     Name JavaDoc headerName = headerElement.getElementName();
211                     String JavaDoc headerURI = headerName.getURI();
212                     if (unmarshaller == null) {
213                         JAXBContext jaxbContext =
214                             VersionTransformer.getExposedJAXBContext(headerURI);
215                         unmarshaller =
216                             jaxbContext.createUnmarshaller();
217                     }
218                     if (transformer.isSupported(headerURI)) {
219                         if (maps == null) {
220                             maps = new AddressingPropertiesImpl();
221                             maps.exposeAs(headerURI);
222                         }
223                         String JavaDoc localName = headerName.getLocalName();
224                         LOG.log(Level.INFO, "decoding WSA header {0}", localName);
225                         if (Names.WSA_MESSAGEID_NAME.equals(localName)) {
226                             maps.setMessageID(transformer.decodeAsNative(
227                                                       headerURI,
228                                                       AttributedURIType.class,
229                                                       headerElement,
230                                                       unmarshaller));
231                         } else if (Names.WSA_TO_NAME.equals(localName)) {
232                             maps.setTo(transformer.decodeAsNative(
233                                                       headerURI,
234                                                       AttributedURIType.class,
235                                                       headerElement,
236                                                       unmarshaller));
237                         } else if (Names.WSA_REPLYTO_NAME.equals(localName)) {
238                             maps.setReplyTo(transformer.decodeAsNative(
239                                                        headerURI,
240                                                        EndpointReferenceType.class,
241                                                        headerElement,
242                                                        unmarshaller));
243                         } else if (Names.WSA_FAULTTO_NAME.equals(localName)) {
244                             maps.setFaultTo(transformer.decodeAsNative(
245                                                                        headerURI,
246                                                                        EndpointReferenceType.class,
247                                                                        headerElement,
248                                                                        unmarshaller));
249                         } else if (Names.WSA_RELATESTO_NAME.equals(localName)) {
250                             maps.setRelatesTo(transformer.decodeAsNative(
251                                                        headerURI,
252                                                        RelatesToType.class,
253                                                        headerElement,
254                                                        unmarshaller));
255                         } else if (Names.WSA_ACTION_NAME.equals(localName)) {
256                             maps.setAction(transformer.decodeAsNative(
257                                                       headerURI,
258                                                       AttributedURIType.class,
259                                                       headerElement,
260                                                       unmarshaller));
261                         }
262                     } else if (headerURI.contains(Names.WSA_NAMESPACE_PATTERN)) {
263                         LOG.log(Level.WARNING,
264                                 "UNSUPPORTED_VERSION_MSG",
265                                 headerURI);
266                     }
267                 }
268             }
269         } catch (SOAPException JavaDoc se) {
270             LOG.log(Level.WARNING, "SOAP_HEADER_DECODE_FAILURE_MSG", se);
271         } catch (JAXBException je) {
272             LOG.log(Level.WARNING, "SOAP_HEADER_DECODE_FAILURE_MSG", je);
273         }
274         return maps;
275     }
276     
277     /**
278      * Decode the MAPs from protocol-specific headers.
279      *
280      * @param context the messsage context
281      * @param the decoded MAPs
282      * @exception SOAPFaultException if decoded MAPs are invalid
283      */

284     private AddressingProperties decode(SOAPMessageContext context) {
285         // REVISIT generate MessageAddressingHeaderRequired fault if an
286
// expected header is missing
287
AddressingProperties maps = null;
288         boolean isRequestor = ContextUtils.isRequestor(context);
289         SOAPMessage JavaDoc message = context.getMessage();
290         maps = unmarshalMAPs(message);
291         if (isRequestor && null != maps.getRelatesTo()) {
292             ContextUtils.storeCorrelationID(maps.getRelatesTo(),
293                                             false,
294                                             context);
295         }
296         return maps;
297     }
298
299     /**
300      * Encodes an MAP as a SOAP header.
301      *
302      * @param value the value to encode
303      * @param qname the QName for the header
304      * @param clz the class
305      * @param header the SOAP header
306      * @param marshaller the JAXB marshaller to use
307      */

308     protected <T> void encodeMAP(T value,
309                                  QName JavaDoc qname,
310                                  Class JavaDoc<T> clz,
311                                  SOAPHeader JavaDoc header,
312                                  Marshaller marshaller) throws JAXBException {
313         LOG.log(Level.INFO, "encoding WSA header {0}", qname);
314         if (value != null) {
315             marshaller.marshal(new JAXBElement<T>(qname, clz, value), header);
316         }
317     }
318
319     /**
320      * Decodes a MAP from a SOAP header.
321      *
322      * @param clz the class
323      * @param headerElement the SOAP header element
324      * @param marshaller the JAXB marshaller to use
325      * @return the decoded value
326      */

327     protected <T> T decodeMAP(Class JavaDoc<T> clz,
328                               SOAPHeaderElement JavaDoc headerElement,
329                               Unmarshaller unmarshaller) throws JAXBException {
330         JAXBElement<T> element =
331             unmarshaller.unmarshal(headerElement, clz);
332         return element.getValue();
333     }
334
335     /**
336      * Discard any pre-existing MAP headers - this may occur if the runtime
337      * re-uses a SOAP message.
338      *
339      * @param header the SOAP header
340      */

341     private void discardMAPs(SOAPHeader JavaDoc header) throws SOAPException JavaDoc {
342         Iterator JavaDoc headerElements = header.examineAllHeaderElements();
343         while (headerElements.hasNext()) {
344             SOAPHeaderElement JavaDoc headerElement =
345                 (SOAPHeaderElement JavaDoc)headerElements.next();
346             Name JavaDoc headerName = headerElement.getElementName();
347             if (Names.WSA_NAMESPACE_NAME.equals(headerName.getURI())) {
348                 headerElement.detachNode();
349             }
350         }
351     }
352
353     /**
354      * Propogate action to SOAPAction header
355      *
356      * @param action the Action property
357      * @param message the SOAP message
358      */

359     private void propogateAction(AttributedURIType action,
360                                  SOAPMessage JavaDoc message) {
361         if (!(action == null || "".equals(action.getValue()))) {
362             MimeHeaders JavaDoc mimeHeaders = message.getMimeHeaders();
363             String JavaDoc[] soapActionHeaders =
364                 mimeHeaders.getHeader(Names.SOAP_ACTION_HEADER);
365             // only propogate to SOAPAction header if currently non-empty
366
if (!(soapActionHeaders == null
367                   || soapActionHeaders.length == 0
368                   || "".equals(soapActionHeaders[0]))) {
369                 LOG.log(Level.INFO,
370                         "encoding wsa:Action in SOAPAction header {0}",
371                         action.getValue());
372                 String JavaDoc soapAction = "\"" + action.getValue() + "\"";
373                 mimeHeaders.setHeader(Names.SOAP_ACTION_HEADER, soapAction);
374             }
375         }
376     }
377
378     /**
379      * Apply results of validation of incoming MAPs.
380      *
381      * @param context the message context
382      * @exception SOAPFaultException if the MAPs are invalid
383      * @exception SOAPException if SOAPFault cannot be constructed
384      */

385     private void applyMAPValidation(SOAPMessageContext context)
386         throws SOAPException JavaDoc {
387         String JavaDoc faultName = ContextUtils.retrieveMAPFaultName(context);
388         if (faultName != null) {
389             String JavaDoc reason = ContextUtils.retrieveMAPFaultReason(context);
390             throw createSOAPFaultException(faultName,
391                                            Names.WSA_NAMESPACE_PREFIX,
392                                            Names.WSA_NAMESPACE_NAME,
393                                            reason);
394         }
395     }
396
397     /**
398      * @return SOAPFactory
399      */

400     private static synchronized SOAPFactory JavaDoc getSOAPFactory() throws SOAPException JavaDoc {
401         if (soapFactory == null) {
402             soapFactory = SOAPFactory.newInstance();
403         }
404         return soapFactory;
405     }
406
407     /**
408      * Create a SOAPFaultException.
409      *
410      * @param localName the fault local name
411      * @param prefix the fault prefix
412      * @param namespace the fault namespace
413      * @param reason the fault reason
414      * @return a new SOAPFaultException
415      */

416     private SOAPFaultException createSOAPFaultException(String JavaDoc localName,
417                                                         String JavaDoc prefix,
418                                                         String JavaDoc namespace,
419                                                         String JavaDoc reason)
420         throws SOAPException JavaDoc {
421         SOAPFactory JavaDoc factory = getSOAPFactory();
422         SOAPFault JavaDoc fault = factory.createFault();
423         Name JavaDoc qname = factory.createName(localName, prefix, namespace);
424         fault.setFaultCode(qname);
425         fault.setFaultString(reason);
426         return new SOAPFaultException(fault);
427     }
428 }
429
430
431
432
433
434
435
Popular Tags