001: /**
002: * Licensed to the Apache Software Foundation (ASF) under one
003: * or more contributor license agreements. See the NOTICE file
004: * distributed with this work for additional information
005: * regarding copyright ownership. The ASF licenses this file
006: * to you under the Apache License, Version 2.0 (the
007: * "License"); you may not use this file except in compliance
008: * with the License. You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing,
013: * software distributed under the License is distributed on an
014: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015: * KIND, either express or implied. See the License for the
016: * specific language governing permissions and limitations
017: * under the License.
018: */package org.apache.cxf.ws.addressing.soap;
019:
020: import java.util.Collections;
021: import java.util.HashMap;
022: import java.util.HashSet;
023: import java.util.Iterator;
024: import java.util.List;
025: import java.util.Map;
026: import java.util.Set;
027: import java.util.logging.Level;
028: import java.util.logging.Logger;
029:
030: import javax.xml.bind.JAXBContext;
031: import javax.xml.bind.JAXBElement;
032: import javax.xml.bind.JAXBException;
033: import javax.xml.bind.Marshaller;
034: import javax.xml.bind.Unmarshaller;
035: import javax.xml.namespace.QName;
036:
037: import org.w3c.dom.Attr;
038: import org.w3c.dom.Document;
039: import org.w3c.dom.Element;
040: import org.w3c.dom.Node;
041: import org.w3c.dom.NodeList;
042:
043: import org.apache.cxf.binding.soap.SoapFault;
044: import org.apache.cxf.binding.soap.SoapMessage;
045: import org.apache.cxf.binding.soap.SoapVersion;
046: import org.apache.cxf.binding.soap.interceptor.AbstractSoapInterceptor;
047: import org.apache.cxf.common.logging.LogUtils;
048: import org.apache.cxf.common.util.StringUtils;
049: import org.apache.cxf.endpoint.Endpoint;
050: import org.apache.cxf.headers.Header;
051: import org.apache.cxf.helpers.CastUtils;
052: import org.apache.cxf.helpers.DOMUtils;
053: import org.apache.cxf.message.Exchange;
054: import org.apache.cxf.message.Message;
055: import org.apache.cxf.phase.Phase;
056: import org.apache.cxf.ws.addressing.AddressingProperties;
057: import org.apache.cxf.ws.addressing.AddressingPropertiesImpl;
058: import org.apache.cxf.ws.addressing.AttributedURIType;
059: import org.apache.cxf.ws.addressing.ContextUtils;
060: import org.apache.cxf.ws.addressing.EndpointReferenceType;
061: import org.apache.cxf.ws.addressing.Names;
062: import org.apache.cxf.ws.addressing.ReferenceParametersType;
063: import org.apache.cxf.ws.addressing.RelatesToType;
064: import org.apache.cxf.wsdl.EndpointReferenceUtils;
065:
066: /**
067: * SOAP interceptor responsible for {en|de}coding the Message Addressing
068: * Properties for {outgo|incom}ing messages.
069: */
070: public class MAPCodec extends AbstractSoapInterceptor {
071:
072: private static final Logger LOG = LogUtils
073: .getL7dLogger(MAPCodec.class);
074: private static final String IS_REFERENCE_PARAM_ATTR_NAME = "isReferenceParameter";
075:
076: /**
077: * REVISIT: map usage that the *same* interceptor instance
078: * is used in all chains.
079: */
080: protected final Map<String, Exchange> uncorrelatedExchanges = Collections
081: .synchronizedMap(new HashMap<String, Exchange>());
082:
083: private VersionTransformer transformer;
084: private HeaderFactory headerFactory;
085:
086: /**
087: * Constructor.
088: */
089: public MAPCodec() {
090: super (Phase.PRE_PROTOCOL);
091: addBefore("org.apache.cxf.jaxws.handler.soap.SOAPHandlerInterceptor");
092: transformer = new VersionTransformer(this );
093: }
094:
095: /**
096: * @return the set of SOAP headers understood by this handler
097: */
098: public Set<QName> getUnderstoodHeaders() {
099: return VersionTransformer.HEADERS;
100: }
101:
102: /**
103: * Invoked for normal processing of inbound and outbound messages.
104: *
105: * @param message the messsage
106: */
107: public void handleMessage(SoapMessage message) {
108: mediate(message);
109: }
110:
111: /**
112: * Invoked when unwinding normal interceptor chain when a fault occurred.
113: *
114: * @param message the messsage message
115: */
116: public void handleFault(SoapMessage message) {
117: }
118:
119: /**
120: * Mediate message flow, peforming MAP {en|de}coding.
121: *
122: * @param message the messsage message
123: */
124: private void mediate(SoapMessage message) {
125: if (ContextUtils.isOutbound(message)) {
126: encode(message, ContextUtils.retrieveMAPs(message, false,
127: true));
128: } else if (null == ContextUtils.retrieveMAPs(message, false,
129: false, false)) {
130: AddressingProperties maps = decode(message);
131: ContextUtils.storeMAPs(maps, message, false);
132: markPartialResponse(message, maps);
133: restoreExchange(message, maps);
134: }
135: }
136:
137: /**
138: * Encode the current MAPs in protocol-specific headers.
139: *
140: * @param message the messsage message
141: * @param maps the MAPs to encode
142: */
143: private void encode(SoapMessage message,
144: AddressingPropertiesImpl maps) {
145: if (maps != null) {
146: cacheExchange(message, maps);
147: LOG.log(Level.INFO, "Outbound WS-Addressing headers");
148: try {
149: List<Header> header = message.getHeaders();
150: discardMAPs(header, maps);
151:
152: Element hdr = getHeaderFactory().getHeader(
153: message.getVersion());
154: JAXBContext jaxbContext = VersionTransformer
155: .getExposedJAXBContext(maps.getNamespaceURI());
156: Marshaller marshaller = jaxbContext.createMarshaller();
157: QName duplicate = maps.getDuplicate();
158: marshaller.setProperty(Marshaller.JAXB_FRAGMENT,
159: Boolean.TRUE);
160: encodeAsExposed(maps, message, maps.getMessageID(),
161: Names.WSA_MESSAGEID_QNAME,
162: AttributedURIType.class, hdr, marshaller);
163: if (Names.WSA_MESSAGEID_QNAME.equals(duplicate)) {
164: encodeAsExposed(maps, message, maps.getMessageID(),
165: Names.WSA_MESSAGEID_QNAME,
166: AttributedURIType.class, hdr, marshaller);
167: }
168: encodeAsExposed(maps, message, maps.getTo(),
169: Names.WSA_TO_QNAME, AttributedURIType.class,
170: hdr, marshaller);
171: if (Names.WSA_TO_QNAME.equals(duplicate)) {
172: encodeAsExposed(maps, message, maps.getTo(),
173: Names.WSA_TO_QNAME,
174: AttributedURIType.class, hdr, marshaller);
175: }
176: encodeAsExposed(maps, message, maps.getFrom(),
177: Names.WSA_FROM_QNAME,
178: EndpointReferenceType.class, hdr, marshaller);
179: if (Names.WSA_FROM_QNAME.equals(duplicate)) {
180: encodeAsExposed(maps, message, maps.getFrom(),
181: Names.WSA_FROM_QNAME,
182: EndpointReferenceType.class, hdr,
183: marshaller);
184: }
185: encodeAsExposed(maps, message, maps.getReplyTo(),
186: Names.WSA_REPLYTO_QNAME,
187: EndpointReferenceType.class, hdr, marshaller);
188: if (Names.WSA_REPLYTO_QNAME.equals(duplicate)) {
189: encodeAsExposed(maps, message, maps.getReplyTo(),
190: Names.WSA_REPLYTO_QNAME,
191: EndpointReferenceType.class, hdr,
192: marshaller);
193: }
194: encodeAsExposed(maps, message, maps.getFaultTo(),
195: Names.WSA_FAULTTO_QNAME,
196: EndpointReferenceType.class, hdr, marshaller);
197: if (Names.WSA_FAULTTO_QNAME.equals(duplicate)) {
198: encodeAsExposed(maps, message, maps.getFaultTo(),
199: Names.WSA_FAULTTO_QNAME,
200: EndpointReferenceType.class, hdr,
201: marshaller);
202: }
203: encodeAsExposed(maps, message, maps.getRelatesTo(),
204: Names.WSA_RELATESTO_QNAME, RelatesToType.class,
205: hdr, marshaller);
206: if (Names.WSA_RELATESTO_QNAME.equals(duplicate)) {
207: encodeAsExposed(maps, message, maps.getRelatesTo(),
208: Names.WSA_RELATESTO_QNAME,
209: RelatesToType.class, hdr, marshaller);
210: }
211: encodeAsExposed(maps, message, maps.getAction(),
212: Names.WSA_ACTION_QNAME,
213: AttributedURIType.class, hdr, marshaller);
214: if (Names.WSA_ACTION_QNAME.equals(duplicate)) {
215: encodeAsExposed(maps, message, maps.getAction(),
216: Names.WSA_ACTION_QNAME,
217: AttributedURIType.class, hdr, marshaller);
218: }
219: encodeReferenceParameters(maps, hdr, marshaller);
220:
221: NodeList children = hdr.getChildNodes();
222: int len = children.getLength();
223: for (int i = 0; i < len; i++) {
224: Node node = children.item(i);
225:
226: Header holder = new Header(new QName(node
227: .getNamespaceURI(), node.getLocalName()),
228: node);
229: header.add(holder);
230: }
231: ((AddressingPropertiesImpl) maps).setDuplicate(null);
232:
233: propogateAction(maps.getAction(), message);
234: applyMAPValidation(message);
235: } catch (JAXBException je) {
236: LOG.log(Level.WARNING,
237: "SOAP_HEADER_ENCODE_FAILURE_MSG", je);
238: }
239: }
240: }
241:
242: private void encodeReferenceParameters(AddressingProperties maps,
243: Element header, Marshaller marshaller) throws JAXBException {
244: EndpointReferenceType toEpr = maps.getToEndpointReference();
245: if (null != toEpr) {
246: ReferenceParametersType params = toEpr
247: .getReferenceParameters();
248: if (null != params) {
249: for (Object o : params.getAny()) {
250: if (o instanceof Element
251: || o instanceof JAXBElement) {
252: JAXBElement jaxbEl = null;
253: if (o instanceof Element) {
254: Element e = (Element) o;
255: QName elQn = new QName(e.getNamespaceURI(),
256: e.getLocalName());
257: jaxbEl = new JAXBElement<String>(elQn,
258: String.class, e.getTextContent());
259: } else {
260: jaxbEl = (JAXBElement) o;
261: }
262: marshaller.marshal(jaxbEl, header);
263:
264: Element lastAdded = (Element) header
265: .getLastChild();
266: addIsReferenceParameterMarkerAttribute(
267: lastAdded, maps.getNamespaceURI());
268: } else {
269: LOG.log(Level.WARNING,
270: "IGNORE_NON_ELEMENT_REF_PARAM_MSG", o);
271: }
272: }
273: }
274: }
275: }
276:
277: private void addIsReferenceParameterMarkerAttribute(
278: Element lastAdded, String namespaceURI) {
279: String pfx = lastAdded.lookupPrefix(namespaceURI);
280: if (StringUtils.isEmpty(pfx)) {
281: //attributes cannot be in empty namespace...
282: if (lastAdded.lookupNamespaceURI("wsa") == null) {
283: pfx = "wsa";
284: lastAdded.setAttributeNS(
285: "http://www.w3.org/2000/xmlns/", "xmlns:wsa",
286: namespaceURI);
287: } else if (lastAdded.lookupNamespaceURI("wsa").equals(
288: namespaceURI)) {
289: pfx = "wsa";
290: } else {
291: int cnt = 1;
292: while (lastAdded.lookupNamespaceURI("wsa" + cnt) != null) {
293: cnt++;
294: }
295: pfx = "wsa" + cnt;
296: lastAdded.setAttributeNS(
297: "http://www.w3.org/2000/xmlns/", "xmlns:wsa"
298: + cnt, namespaceURI);
299: }
300: }
301: Attr isRefParamAttr = lastAdded.getOwnerDocument()
302: .createAttributeNS(namespaceURI,
303: pfx + ":" + IS_REFERENCE_PARAM_ATTR_NAME);
304: isRefParamAttr.setTextContent("1");
305: lastAdded.setAttributeNodeNS(isRefParamAttr);
306: }
307:
308: private void addMustUnderstandAttribute(Element header, QName name,
309: SoapVersion version, AddressingPropertiesImpl maps) {
310: if (maps.getMustUnderstand().contains(name)) {
311: Element lastAdded = (Element) header.getLastChild();
312: Attr mustUnderstandAttr = lastAdded.getOwnerDocument()
313: .createAttributeNS(version.getNamespace(),
314: version.getPrefix() + ":mustUnderstand");
315: mustUnderstandAttr.setTextContent("1");
316: lastAdded.setAttributeNodeNS(mustUnderstandAttr);
317: }
318: }
319:
320: /**
321: * Encode message in exposed version.
322: *
323: * @param maps the MAPs, where getNamespceURI() specifies the WS-Addressing
324: * version to expose
325: * @param value the value to encode
326: * @param name the QName for the header
327: * @param clz the class
328: * @param header the SOAP header element
329: * @param marshaller the JAXB marshaller to use
330: */
331: private <T> void encodeAsExposed(AddressingPropertiesImpl maps,
332: SoapMessage message, T value, QName name, Class<T> clz,
333: Element header, Marshaller marshaller) throws JAXBException {
334: if (value != null) {
335: LOG.log(Level.INFO, "{0} : {1}", new Object[] {
336: name.getLocalPart(), getLogText(value) });
337: transformer.encodeAsExposed(maps.getNamespaceURI(), value,
338: name.getLocalPart(), clz, header, marshaller);
339: }
340: addMustUnderstandAttribute(header, name, message.getVersion(),
341: maps);
342: }
343:
344: /**
345: * Decode the MAPs from protocol-specific headers.
346: *
347: * @param message the SOAP message
348: * @param the decoded MAPs
349: * @exception SOAPFaultException if decoded MAPs are invalid
350: */
351: public AddressingProperties unmarshalMAPs(SoapMessage message) {
352: // REVISIT generate MessageAddressingHeaderRequired fault if an
353: // expected header is missing
354: AddressingPropertiesImpl maps = null;
355: try {
356: List<Header> header = message.getHeaders();
357: if (header != null) {
358: LOG.log(Level.INFO, "Inbound WS-Addressing headers");
359: Unmarshaller unmarshaller = null;
360: Set<Element> referenceParameterHeaders = null;
361:
362: Iterator<Header> iter = header.iterator();
363: while (iter.hasNext()) {
364: Header hdr = iter.next();
365: if (hdr.getObject() instanceof Element) {
366: Element headerElement = (Element) hdr
367: .getObject();
368: String headerURI = headerElement
369: .getNamespaceURI();
370: // Need to check the uri before getting unmarshaller else
371: // would get wrong unmarshaller and fail to process required
372: // headers.
373: if (transformer.isSupported(headerURI)) {
374: if (unmarshaller == null) {
375: JAXBContext jaxbContext = VersionTransformer
376: .getExposedJAXBContext(headerURI);
377: unmarshaller = jaxbContext
378: .createUnmarshaller();
379: }
380: if (maps == null) {
381: maps = new AddressingPropertiesImpl();
382: maps.exposeAs(headerURI);
383: }
384: String localName = headerElement
385: .getLocalName();
386: if (Names.WSA_MESSAGEID_NAME
387: .equals(localName)) {
388: maps.setMessageID(decodeAsNative(
389: headerURI,
390: AttributedURIType.class,
391: headerElement, unmarshaller));
392: } else if (Names.WSA_TO_NAME
393: .equals(localName)) {
394: AttributedURIType addr = decodeAsNative(
395: headerURI,
396: AttributedURIType.class,
397: headerElement, unmarshaller);
398: maps.setTo(EndpointReferenceUtils
399: .getEndpointReference(addr));
400: } else if (Names.WSA_REPLYTO_NAME
401: .equals(localName)) {
402: maps.setReplyTo(decodeAsNative(
403: headerURI,
404: EndpointReferenceType.class,
405: headerElement, unmarshaller));
406: } else if (Names.WSA_FAULTTO_NAME
407: .equals(localName)) {
408: maps.setFaultTo(decodeAsNative(
409: headerURI,
410: EndpointReferenceType.class,
411: headerElement, unmarshaller));
412: } else if (Names.WSA_RELATESTO_NAME
413: .equals(localName)) {
414: maps.setRelatesTo(decodeAsNative(
415: headerURI, RelatesToType.class,
416: headerElement, unmarshaller));
417: } else if (Names.WSA_ACTION_NAME
418: .equals(localName)) {
419: maps.setAction(decodeAsNative(
420: headerURI,
421: AttributedURIType.class,
422: headerElement, unmarshaller));
423: }
424: } else if (null != headerElement
425: .getAttribute(IS_REFERENCE_PARAM_ATTR_NAME)) {
426: if (null == referenceParameterHeaders) {
427: referenceParameterHeaders = new HashSet<Element>();
428: }
429: referenceParameterHeaders
430: .add(headerElement);
431: } else if (headerURI
432: .contains(Names.WSA_NAMESPACE_PATTERN)) {
433: LOG.log(Level.WARNING,
434: "UNSUPPORTED_VERSION_MSG",
435: headerURI);
436: }
437: }
438: }
439: if (null != referenceParameterHeaders && null != maps) {
440: decodeReferenceParameters(
441: referenceParameterHeaders, maps,
442: unmarshaller);
443: }
444: }
445: } catch (JAXBException je) {
446: LOG
447: .log(Level.WARNING,
448: "SOAP_HEADER_DECODE_FAILURE_MSG", je);
449: }
450: return maps;
451: }
452:
453: private void decodeReferenceParameters(
454: Set<Element> referenceParameterHeaders,
455: AddressingPropertiesImpl maps, Unmarshaller unmarshaller)
456: throws JAXBException {
457: EndpointReferenceType toEpr = maps.getToEndpointReference();
458: if (null != toEpr) {
459: for (Element e : referenceParameterHeaders) {
460: JAXBElement<String> el = unmarshaller.unmarshal(e,
461: String.class);
462: ContextUtils.applyReferenceParam(toEpr, el);
463: }
464: }
465: }
466:
467: /**
468: * Decodes a MAP from a exposed version.
469: *
470: * @param encodedAs specifies the encoded version
471: * @param clz the class
472: * @param headerElement the SOAP header element
473: * @param marshaller the JAXB marshaller to use
474: * @return the decoded value
475: */
476: public <T> T decodeAsNative(String encodedAs, Class<T> clz,
477: Element headerElement, Unmarshaller unmarshaller)
478: throws JAXBException {
479: T value = clz.cast(transformer.decodeAsNative(encodedAs, clz,
480: headerElement, unmarshaller));
481: LOG.log(Level.INFO, "{0} : {1}", new Object[] {
482: headerElement.getLocalName(), getLogText(value) });
483: return value;
484: }
485:
486: /**
487: * Return a text representation of a header value for logging.
488: *
489: * @param <T> header type
490: * @param value header value
491: * @return
492: */
493: private <T> String getLogText(T value) {
494: String text = "unknown";
495: if (value == null) {
496: text = "null";
497: } else if (value instanceof AttributedURIType) {
498: text = ((AttributedURIType) value).getValue();
499: } else if (value instanceof EndpointReferenceType) {
500: text = ((EndpointReferenceType) value).getAddress() != null ? ((EndpointReferenceType) value)
501: .getAddress().getValue()
502: : "null";
503: } else if (value instanceof RelatesToType) {
504: text = ((RelatesToType) value).getValue();
505: }
506: return text;
507: }
508:
509: /**
510: * Decode the MAPs from protocol-specific headers.
511: *
512: * @param message the messsage
513: * @param the decoded MAPs
514: * @exception SOAPFaultException if decoded MAPs are invalid
515: */
516: private AddressingProperties decode(SoapMessage message) {
517: // REVISIT generate MessageAddressingHeaderRequired fault if an
518: // expected header is missing
519: return unmarshalMAPs(message);
520: }
521:
522: /**
523: * Encodes an MAP as a SOAP header.
524: *
525: * @param value the value to encode
526: * @param qname the QName for the header
527: * @param clz the class
528: * @param header the SOAP header element
529: * @param marshaller the JAXB marshaller to use
530: */
531: protected <T> void encodeMAP(T value, QName qname, Class<T> clz,
532: Element header, Marshaller marshaller) throws JAXBException {
533: if (value != null) {
534: marshaller.marshal(new JAXBElement<T>(qname, clz, value),
535: header);
536: }
537: }
538:
539: /**
540: * Decodes a MAP from a SOAP header.
541: *
542: * @param clz the class
543: * @param headerElement the SOAP header element
544: * @param marshaller the JAXB marshaller to use
545: * @return the decoded value
546: */
547: protected <T> T decodeMAP(Class<T> clz, Element headerElement,
548: Unmarshaller unmarshaller) throws JAXBException {
549: JAXBElement<T> element = unmarshaller.unmarshal(headerElement,
550: clz);
551: return element.getValue();
552: }
553:
554: /**
555: * Discard any pre-existing MAP headers - this may occur if the runtime
556: * re-uses a SOAP message.
557: *
558: * @param header the SOAP header
559: * @param maps the current MAPs
560: */
561: private void discardMAPs(List<Header> header,
562: AddressingProperties maps) {
563: Iterator<Header> iter = header.iterator();
564: while (iter.hasNext()) {
565: Header hdr = iter.next();
566: if (Names.WSA_NAMESPACE_NAME.equals(hdr.getName()
567: .getNamespaceURI())) {
568: iter.remove();
569: }
570: }
571: /*
572: NodeList headerElements =
573: header.getElementsByTagNameNS(maps.getNamespaceURI(), "*");
574: for (int i = 0; i < headerElements.getLength(); i++) {
575: Node headerElement = headerElements.item(i);
576: if (Names.WSA_NAMESPACE_NAME.equals(headerElement.getNamespaceURI())) {
577: header.removeChild(headerElement);
578: }
579: } */
580: }
581:
582: /**
583: * Propogate action to SOAPAction header
584: *
585: * @param action the Action property
586: * @param message the SOAP message
587: */
588: private void propogateAction(AttributedURIType action,
589: SoapMessage message) {
590: if (!(action == null || "".equals(action.getValue()))) {
591: Map<String, List<String>> mimeHeaders = CastUtils
592: .cast((Map<?, ?>) message.get(Message.MIME_HEADERS));
593: if (mimeHeaders != null) {
594: List<String> soapActionHeaders = mimeHeaders
595: .get(Names.SOAP_ACTION_HEADER);
596: // only propogate to SOAPAction header if currently non-empty
597: if (!(soapActionHeaders == null
598: || soapActionHeaders.size() == 0 || ""
599: .equals(soapActionHeaders.get(0)))) {
600: LOG
601: .log(
602: Level.INFO,
603: "encoding wsa:Action in SOAPAction header {0}",
604: action.getValue());
605: soapActionHeaders.clear();
606: soapActionHeaders.add("\"" + action.getValue()
607: + "\"");
608: }
609: }
610: }
611: }
612:
613: /**
614: * Apply results of validation of incoming MAPs.
615: *
616: * @param message the message
617: * @exception SOAPFaultException if the MAPs are invalid
618: * @exception SOAPException if SOAPFault cannot be constructed
619: */
620: private void applyMAPValidation(SoapMessage message) {
621: String faultName = ContextUtils.retrieveMAPFaultName(message);
622: if (faultName != null) {
623: String reason = ContextUtils
624: .retrieveMAPFaultReason(message);
625: throw createSOAPFaut(faultName, Names.WSA_NAMESPACE_NAME,
626: reason);
627: }
628: }
629:
630: /**
631: * Create a SoapFault.
632: *
633: * @param localName the fault local name
634: * @param prefix the fault prefix
635: * @param namespace the fault namespace
636: * @param reason the fault reason
637: * @return a new SoapFault
638: */
639: private SoapFault createSOAPFaut(String localName,
640: String namespace, String reason) {
641: return new SoapFault(reason, new QName(namespace, localName));
642: }
643:
644: /**
645: * Cache exchange for correlated response
646: *
647: * @param message the current message
648: * @param maps the addressing properties
649: */
650: private void cacheExchange(SoapMessage message,
651: AddressingProperties maps) {
652: if (maps.getRelatesTo() == null) {
653: uncorrelatedExchanges.put(maps.getMessageID().getValue(),
654: message.getExchange());
655: }
656: }
657:
658: /**
659: * Restore exchange for correlated response
660: *
661: * @param message the current message
662: * @param maps the addressing properties
663: */
664: private void restoreExchange(SoapMessage message,
665: AddressingProperties maps) {
666: if (maps != null && maps.getRelatesTo() != null) {
667: Exchange correlatedExchange = uncorrelatedExchanges
668: .remove(maps.getRelatesTo().getValue());
669: if (correlatedExchange != null) {
670: synchronized (correlatedExchange) {
671: Exchange tmpExchange = message.getExchange();
672: message.setExchange(correlatedExchange);
673: Endpoint endpoint = correlatedExchange
674: .get(Endpoint.class);
675: if (Boolean.TRUE
676: .equals(tmpExchange
677: .get("deferred.fault.observer.notification"))
678: && endpoint != null) {
679: message.getInterceptorChain().abort();
680: if (endpoint.getInFaultObserver() != null) {
681: endpoint.getInFaultObserver().onMessage(
682: message);
683: }
684: }
685: }
686: } else {
687: LOG.log(Level.WARNING, "CORRELATION_FAILURE_MSG");
688: message.getInterceptorChain().abort();
689: }
690: }
691: }
692:
693: /**
694: * Marks a message as partial response
695: *
696: * @param message the current message
697: */
698: private void markPartialResponse(SoapMessage message,
699: AddressingProperties maps) {
700: if (ContextUtils.isRequestor(message) && null != maps
701: && null == maps.getRelatesTo()) {
702: message.put(Message.PARTIAL_RESPONSE_MESSAGE, Boolean.TRUE);
703: }
704: }
705:
706: protected HeaderFactory getHeaderFactory() {
707: if (headerFactory == null) {
708: headerFactory = new HeaderFactory() {
709: public Element getHeader(SoapVersion soapversion) {
710: Document doc = DOMUtils.createDocument();
711: return doc.createElementNS(soapversion.getHeader()
712: .getNamespaceURI(), soapversion.getHeader()
713: .getLocalPart());
714: }
715: };
716: }
717: return headerFactory;
718: }
719:
720: protected void setHeaderFactory(HeaderFactory factory) {
721: headerFactory = factory;
722: }
723:
724: public interface HeaderFactory {
725: Element getHeader(SoapVersion soapversion);
726: }
727: }
|