001: /*
002: * Portions Copyright 2006 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004: *
005: * This code is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU General Public License version 2 only, as
007: * published by the Free Software Foundation. Sun designates this
008: * particular file as subject to the "Classpath" exception as provided
009: * by Sun in the LICENSE file that accompanied this code.
010: *
011: * This code is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * version 2 for more details (a copy is included in the LICENSE file that
015: * accompanied this code).
016: *
017: * You should have received a copy of the GNU General Public License version
018: * 2 along with this work; if not, write to the Free Software Foundation,
019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022: * CA 95054 USA or visit www.sun.com if you need additional information or
023: * have any questions.
024: */
025:
026: package com.sun.xml.internal.ws.encoding.soap;
027:
028: import com.sun.xml.internal.ws.pept.encoding.Decoder;
029: import com.sun.xml.internal.ws.pept.ept.MessageInfo;
030: import com.sun.xml.internal.ws.pept.presentation.MessageStruct;
031: import com.sun.xml.internal.bind.api.BridgeContext;
032: import com.sun.xml.internal.messaging.saaj.packaging.mime.internet.ContentType;
033: import com.sun.xml.internal.messaging.saaj.packaging.mime.internet.ParseException;
034: import com.sun.xml.internal.messaging.saaj.util.ByteInputStream;
035: import com.sun.xml.internal.ws.encoding.JAXWSAttachmentUnmarshaller;
036: import com.sun.xml.internal.ws.encoding.jaxb.JAXBBridgeInfo;
037: import com.sun.xml.internal.ws.encoding.jaxb.RpcLitPayload;
038: import com.sun.xml.internal.ws.encoding.jaxb.RpcLitPayloadSerializer;
039: import com.sun.xml.internal.ws.encoding.soap.internal.AttachmentBlock;
040: import com.sun.xml.internal.ws.encoding.soap.internal.BodyBlock;
041: import com.sun.xml.internal.ws.encoding.soap.internal.HeaderBlock;
042: import com.sun.xml.internal.ws.encoding.soap.internal.InternalMessage;
043: import com.sun.xml.internal.ws.encoding.soap.message.SOAPFaultInfo;
044: import com.sun.xml.internal.ws.encoding.soap.streaming.SOAPNamespaceConstants;
045: import com.sun.xml.internal.ws.handler.HandlerChainCaller;
046: import com.sun.xml.internal.ws.handler.HandlerContext;
047: import com.sun.xml.internal.ws.model.soap.SOAPRuntimeModel;
048: import com.sun.xml.internal.ws.server.RuntimeContext;
049: import com.sun.xml.internal.ws.streaming.SourceReaderFactory;
050: import com.sun.xml.internal.ws.streaming.XMLReaderException;
051: import com.sun.xml.internal.ws.streaming.XMLStreamReaderException;
052: import com.sun.xml.internal.ws.streaming.XMLStreamReaderUtil;
053: import com.sun.xml.internal.ws.util.MessageInfoUtil;
054: import com.sun.xml.internal.ws.util.SOAPUtil;
055: import com.sun.xml.internal.ws.client.dispatch.DispatchContext;
056: import com.sun.xml.internal.ws.client.dispatch.impl.encoding.DispatchUtil;
057: import com.sun.xml.internal.ws.client.BindingProviderProperties;
058: import com.sun.xml.internal.ws.util.FastInfosetReflection;
059:
060: import javax.xml.namespace.QName;
061: import javax.xml.soap.AttachmentPart;
062: import javax.xml.soap.SOAPException;
063: import javax.xml.soap.SOAPFault;
064: import javax.xml.soap.SOAPMessage;
065: import javax.xml.soap.SOAPPart;
066: import javax.xml.stream.XMLStreamReader;
067: import javax.xml.transform.Source;
068: import javax.xml.transform.stream.StreamSource;
069: import javax.xml.ws.soap.SOAPBinding;
070: import javax.xml.ws.soap.SOAPFaultException;
071: import javax.xml.ws.Service;
072: import javax.xml.ws.WebServiceException;
073: import java.io.IOException;
074: import java.io.InputStream;
075: import java.util.HashSet;
076: import java.util.Iterator;
077: import java.util.Set;
078: import java.util.logging.Level;
079: import java.util.logging.Logger;
080:
081: import static javax.xml.stream.XMLStreamReader.*;
082: import javax.xml.bind.Unmarshaller;
083:
084: /**
085: * @author WS Development Team
086: */
087: public abstract class SOAPDecoder implements Decoder {
088:
089: public final static String NOT_UNDERSTOOD_HEADERS = "not-understood soap headers";
090:
091: protected static final Logger logger = Logger
092: .getLogger(com.sun.xml.internal.ws.util.Constants.LoggingDomain
093: + ".soap.decoder");
094:
095: protected final static String MUST_UNDERSTAND_FAULT_MESSAGE_STRING = "SOAP must understand error";
096:
097: /* (non-Javadoc)
098: * @see com.sun.pept.encoding.Decoder#decode(com.sun.pept.ept.MessageInfo)
099: */
100: public void decode(MessageInfo arg0) {
101: throw new UnsupportedOperationException();
102: }
103:
104: /* (non-Javadoc)
105: * @see com.sun.pept.encoding.Decoder#receieveAndDecode(com.sun.pept.ept.MessageInfo)
106: */
107: public void receiveAndDecode(MessageInfo arg0) {
108: throw new UnsupportedOperationException();
109: }
110:
111: /**
112: * parses and binds headers, body from SOAPMessage.
113: *
114: * @param soapMessage
115: * @return the <code>InternalMessage</code> for the <code>soapMessage</code>
116: */
117: public InternalMessage toInternalMessage(SOAPMessage soapMessage,
118: MessageInfo messageInfo) {
119: return null;
120: }
121:
122: /**
123: * Returns the roles required for the type of binding. Returns
124: * an empty set if there are none.
125: */
126: public Set<String> getRequiredRoles() {
127: return new HashSet<String>();
128: }
129:
130: /**
131: * Parses and binds headers from SOAPMessage.
132: *
133: * @param soapMessage
134: * @param internalMessage
135: * @param messageInfo
136: * @return the InternalMessage representation of the SOAPMessage
137: */
138: public InternalMessage toInternalMessage(SOAPMessage soapMessage,
139: InternalMessage internalMessage, MessageInfo messageInfo) {
140: return null;
141: }
142:
143: public SOAPMessage toSOAPMessage(MessageInfo messageInfo) {
144: return null;
145: }
146:
147: public void toMessageInfo(InternalMessage internalMessage,
148: MessageInfo messageInfo) {
149: }
150:
151: protected QName getEnvelopeTag() {
152: return SOAPConstants.QNAME_SOAP_ENVELOPE;
153: }
154:
155: protected QName getBodyTag() {
156: return SOAPConstants.QNAME_SOAP_BODY;
157: }
158:
159: protected QName getHeaderTag() {
160: return SOAPConstants.QNAME_SOAP_HEADER;
161: }
162:
163: protected QName getMUAttrQName() {
164: return SOAPConstants.QNAME_MUSTUNDERSTAND;
165: }
166:
167: protected QName getRoleAttrQName() {
168: return SOAPConstants.QNAME_ROLE;
169: }
170:
171: protected QName getFaultTag() {
172: return SOAPConstants.QNAME_SOAP_FAULT;
173: }
174:
175: protected QName getFaultDetailTag() {
176: return SOAPConstants.QNAME_SOAP_FAULT_DETAIL;
177: }
178:
179: protected void skipBody(XMLStreamReader reader) {
180: XMLStreamReaderUtil.verifyReaderState(reader, START_ELEMENT);
181: XMLStreamReaderUtil.verifyTag(reader, getBodyTag());
182: XMLStreamReaderUtil.skipElement(reader); // Moves to </Body>
183: XMLStreamReaderUtil.nextElementContent(reader);
184: }
185:
186: protected void skipHeader(XMLStreamReader reader,
187: MessageInfo messageInfo) {
188: XMLStreamReaderUtil.verifyReaderState(reader, START_ELEMENT);
189: if (!isDispatch(messageInfo))
190: return;
191:
192: if (!SOAPNamespaceConstants.TAG_HEADER.equals(reader
193: .getLocalName())) {
194: return;
195: }
196:
197: //XMLStreamReaderUtil.verifyTag(reader, getHeaderTag());
198:
199: dispatchUtil.collectPrefixes(reader);
200:
201: XMLStreamReaderUtil.skipElement(reader); // Moves to </Header>
202:
203: try {
204: reader.next();
205: } catch (Exception ex) {
206: ex.printStackTrace();
207: }
208: }
209:
210: protected boolean skipHeader(MessageInfo messageInfo) {
211: if (messageInfo
212: .getMetaData(DispatchContext.DISPATCH_MESSAGE_MODE) == Service.Mode.PAYLOAD) {
213: return true;
214: }
215: return false;
216: }
217:
218: /*
219: * skipBody is true, the body is skipped during parsing.
220: */
221: protected void decodeEnvelope(XMLStreamReader reader,
222: InternalMessage request, boolean skipBody,
223: MessageInfo messageInfo) {
224: XMLStreamReaderUtil.verifyReaderState(reader, START_ELEMENT);
225: XMLStreamReaderUtil.verifyTag(reader, getEnvelopeTag());
226: XMLStreamReaderUtil.nextElementContent(reader);
227: if (skipHeader(messageInfo))
228: skipHeader(reader, messageInfo);
229: else
230: decodeHeader(reader, messageInfo, request);
231:
232: if (skipBody) {
233: skipBody(reader);
234: } else {
235: decodeBody(reader, request, messageInfo);
236: }
237:
238: XMLStreamReaderUtil.verifyReaderState(reader, END_ELEMENT);
239: XMLStreamReaderUtil.verifyTag(reader, getEnvelopeTag());
240: XMLStreamReaderUtil.nextElementContent(reader);
241: XMLStreamReaderUtil.verifyReaderState(reader, END_DOCUMENT);
242: }
243:
244: protected void decodeHeader(XMLStreamReader reader,
245: MessageInfo messageInfo, InternalMessage request) {
246: XMLStreamReaderUtil.verifyReaderState(reader, START_ELEMENT);
247:
248: if (!SOAPNamespaceConstants.TAG_HEADER.equals(reader
249: .getLocalName())) {
250: return;
251: }
252: XMLStreamReaderUtil.verifyTag(reader, getHeaderTag());
253: if (isDispatch(messageInfo))
254: dispatchUtil.collectPrefixes(reader);
255: XMLStreamReaderUtil.nextElementContent(reader);
256: while (true) {
257: if (reader.getEventType() == START_ELEMENT) {
258: decodeHeaderElement(reader, messageInfo, request);
259: } else {
260: break;
261: }
262: }
263: XMLStreamReaderUtil.verifyReaderState(reader, END_ELEMENT);
264: XMLStreamReaderUtil.verifyTag(reader, getHeaderTag());
265: XMLStreamReaderUtil.nextElementContent(reader);
266: }
267:
268: /*
269: * If JAXB can deserialize a header, deserialize it.
270: * Otherwise, just ignore the header
271: */
272:
273: protected void decodeHeaderElement(XMLStreamReader reader,
274: MessageInfo messageInfo, InternalMessage msg) {
275: RuntimeContext rtCtxt = MessageInfoUtil
276: .getRuntimeContext(messageInfo);
277: if (rtCtxt == null) {
278:
279: XMLStreamReaderUtil.skipElement(reader); // Moves to END state
280: XMLStreamReaderUtil.nextElementContent(reader);
281: return;
282: }
283: BridgeContext bridgeContext = rtCtxt.getBridgeContext();
284: Set<QName> knownHeaders = ((SOAPRuntimeModel) rtCtxt.getModel())
285: .getKnownHeaders();
286: QName name = reader.getName();
287: if (knownHeaders != null && knownHeaders.contains(name)) {
288: QName headerName = reader.getName();
289: if (msg.isHeaderPresent(name)) {
290: // More than one instance of header whose QName is mapped to a
291: // method parameter. Generates a runtime error.
292: raiseFault(getSenderFaultCode(), DUPLICATE_HEADER
293: + headerName);
294: }
295: Object decoderInfo = rtCtxt.getDecoderInfo(name);
296: if (decoderInfo != null
297: && decoderInfo instanceof JAXBBridgeInfo) {
298: JAXBBridgeInfo bridgeInfo = (JAXBBridgeInfo) decoderInfo;
299: // JAXB leaves on </env:Header> or <nextHeaderElement>
300: bridgeInfo.deserialize(reader, bridgeContext);
301: HeaderBlock headerBlock = new HeaderBlock(bridgeInfo);
302: msg.addHeader(headerBlock);
303: }
304: } else {
305: XMLStreamReaderUtil.skipElement(reader); // Moves to END state
306: XMLStreamReaderUtil.nextElementContent(reader);
307: }
308: }
309:
310: protected void decodeBody(XMLStreamReader reader,
311: InternalMessage response, MessageInfo messageInfo) {
312: XMLStreamReaderUtil.verifyReaderState(reader, START_ELEMENT);
313: XMLStreamReaderUtil.verifyTag(reader, getBodyTag());
314: int state = XMLStreamReaderUtil.nextElementContent(reader);
315: decodeBodyContent(reader, response, messageInfo);
316: XMLStreamReaderUtil.verifyReaderState(reader, END_ELEMENT);
317: XMLStreamReaderUtil.verifyTag(reader, getBodyTag());
318: XMLStreamReaderUtil.nextElementContent(reader);
319: }
320:
321: protected void decodeBodyContent(XMLStreamReader reader,
322: InternalMessage response, MessageInfo messageInfo) {
323: RuntimeContext rtCtxt = MessageInfoUtil
324: .getRuntimeContext(messageInfo);
325: BridgeContext bridgeContext = rtCtxt.getBridgeContext();
326: decodeDispatchMethod(reader, response, messageInfo);
327: if (reader.getEventType() == START_ELEMENT) {
328: QName name = reader.getName(); // Operation name
329: if (name.getNamespaceURI().equals(
330: getEnvelopeTag().getNamespaceURI())
331: && name.getLocalPart().equals(
332: SOAPNamespaceConstants.TAG_FAULT)) {
333: SOAPFaultInfo soapFaultInfo = decodeFault(reader,
334: response, messageInfo);
335: BodyBlock responseBody = new BodyBlock(soapFaultInfo);
336: response.setBody(responseBody);
337: } else {
338: Object decoderInfo = rtCtxt.getDecoderInfo(name);
339: if (decoderInfo != null
340: && decoderInfo instanceof JAXBBridgeInfo) {
341: JAXBBridgeInfo bridgeInfo = (JAXBBridgeInfo) decoderInfo;
342: bridgeInfo.deserialize(reader, bridgeContext);
343: BodyBlock responseBody = new BodyBlock(bridgeInfo);
344: response.setBody(responseBody);
345: } else if (decoderInfo != null
346: && decoderInfo instanceof RpcLitPayload) {
347: RpcLitPayload rpcLitPayload = (RpcLitPayload) decoderInfo;
348: RpcLitPayloadSerializer.deserialize(reader,
349: rpcLitPayload, bridgeContext);
350: BodyBlock responseBody = new BodyBlock(
351: rpcLitPayload);
352: response.setBody(responseBody);
353: }
354: }
355: }
356: }
357:
358: public void decodeDispatchMethod(XMLStreamReader reader,
359: InternalMessage request, MessageInfo messageInfo) {
360: }
361:
362: protected SOAPFaultInfo decodeFault(XMLStreamReader reader,
363: InternalMessage internalMessage, MessageInfo messageInfo) {
364: return null;
365: }
366:
367: /*
368: *
369: */
370:
371: protected void convertBodyBlock(InternalMessage request,
372: MessageInfo messageInfo) {
373: BodyBlock bodyBlock = request.getBody();
374: if (bodyBlock != null) {
375: Object value = bodyBlock.getValue();
376: if (value instanceof JAXBBridgeInfo
377: || value instanceof RpcLitPayload) {
378: // Nothing to do
379: } else if (value instanceof Source) {
380: Source source = (Source) value;
381: XMLStreamReader reader = SourceReaderFactory
382: .createSourceReader(source, true);
383: XMLStreamReaderUtil.nextElementContent(reader);
384: decodeBodyContent(reader, request, messageInfo);
385: } else {
386: throw new WebServiceException(
387: "Shouldn't happen. Unknown type in BodyBlock ="
388: + value.getClass());
389: }
390: }
391: }
392:
393: /**
394: * @param mi
395: * @param im
396: * @param message
397: * @throws SOAPException
398: * @throws ParseException
399: */
400: protected void processAttachments(MessageInfo mi,
401: InternalMessage im, SOAPMessage message)
402: throws SOAPException, ParseException, IOException {
403: Iterator iter = message.getAttachments();
404: if (iter.hasNext()) {
405: JAXWSAttachmentUnmarshaller au = null;
406: if (MessageInfoUtil.getRuntimeContext(mi) != null)
407: au = (JAXWSAttachmentUnmarshaller) MessageInfoUtil
408: .getRuntimeContext(mi).getBridgeContext()
409: .getAttachmentUnmarshaller();
410: else {
411: //for dispatch
412: Unmarshaller m = (Unmarshaller) mi
413: .getMetaData(BindingProviderProperties.DISPATCH_UNMARSHALLER);
414: if (m != null)
415: au = (JAXWSAttachmentUnmarshaller) m
416: .getAttachmentUnmarshaller();
417: }
418: if (au != null) {
419: au.setXOPPackage(isXOPPackage(message));
420: au.setAttachments(im.getAttachments());
421: }
422: }
423:
424: while (iter.hasNext()) {
425: AttachmentPart ap = (AttachmentPart) iter.next();
426: im.addAttachment(AttachmentBlock.fromSAAJ(ap));
427: }
428: }
429:
430: /**
431: * From the SOAP message header find out if its a XOP package.
432: *
433: * @param sm
434: * @return
435: * @throws ParseException
436: */
437: private boolean isXOPPackage(SOAPMessage sm) throws ParseException {
438: String ct = getContentType(sm.getSOAPPart());
439: ContentType contentType = new ContentType(ct);
440: String primary = contentType.getPrimaryType();
441: String sub = contentType.getSubType();
442: if (primary.equalsIgnoreCase("application")
443: && sub.equalsIgnoreCase("xop+xml")) {
444: String type = contentType.getParameter("type");
445: if (type.toLowerCase().startsWith("text/xml")
446: || type.toLowerCase().startsWith(
447: "application/soap+xml"))
448: return true;
449: }
450: return false;
451: }
452:
453: private String getContentType(SOAPPart part) {
454: String[] values = part.getMimeHeader("Content-Type");
455: if (values == null)
456: return null;
457: else
458: return values[0];
459: }
460:
461: /*
462: * It does mustUnderstand processing, and does best guess of MEP
463: *
464: * Avoids SAAJ call that create DOM.
465: *
466: */
467:
468: public boolean doMustUnderstandProcessing(SOAPMessage soapMessage,
469: MessageInfo mi, HandlerContext handlerContext,
470: boolean getMEP) throws SOAPException, IOException {
471: try {
472: boolean oneway = false;
473: Source source = soapMessage.getSOAPPart().getContent();
474: ByteInputStream bis = null;
475:
476: if (source instanceof StreamSource) {
477: StreamSource streamSource = (StreamSource) source;
478: InputStream is = streamSource.getInputStream();
479: if (is != null && is instanceof ByteInputStream) {
480: bis = ((ByteInputStream) is);
481: } else {
482: logger
483: .fine("SAAJ StreamSource doesn't have ByteInputStream "
484: + is);
485: }
486: } else if (FastInfosetReflection
487: .isFastInfosetSource(source)) {
488: try {
489: bis = (ByteInputStream) FastInfosetReflection
490: .FastInfosetSource_getInputStream(source);
491: } catch (Exception e) {
492: throw new XMLReaderException(
493: "fastinfoset.noImplementation");
494: }
495: } else {
496: logger
497: .fine("Inefficient Use - SOAPMessage is already parsed");
498: }
499:
500: XMLStreamReader reader = SourceReaderFactory
501: .createSourceReader(source, true);
502: XMLStreamReaderUtil.nextElementContent(reader);
503: checkMustUnderstandHeaders(reader, mi, handlerContext);
504:
505: if (getMEP) {
506: oneway = isOneway(reader, mi);
507: }
508: XMLStreamReaderUtil.close(reader);
509: if (bis != null) {
510: bis.close(); // resets stream; SAAJ has whole stream
511: }
512:
513: return oneway;
514: } catch (XMLStreamReaderException xe) {
515: raiseBadXMLFault(handlerContext);
516: throw xe;
517: }
518: }
519:
520: /*
521: * returns Oneway or not. reader is on <Body>
522: *
523: * Peek into the body and make a best guess as to whether the request
524: * is one-way or not. Assume request-response if it cannot be determined.
525: *
526: */
527:
528: private boolean isOneway(XMLStreamReader reader, MessageInfo mi) {
529: XMLStreamReaderUtil.verifyReaderState(reader, START_ELEMENT);
530: XMLStreamReaderUtil.verifyTag(reader, getBodyTag()); // <Body>
531: int state = XMLStreamReaderUtil.nextElementContent(reader);
532: QName operationName = null;
533: if (state == START_ELEMENT) { // handles empty Body i.e. <Body/>
534: operationName = reader.getName();
535: }
536: RuntimeContext rtCtxt = MessageInfoUtil.getRuntimeContext(mi);
537: rtCtxt.setMethodAndMEP(operationName, mi);
538: return (mi.getMEP() == MessageStruct.ONE_WAY_MEP);
539: }
540:
541: /*
542: * Does MU processing. reader is on <Envelope>, at the end of this method
543: * leaves it on <Body>. Once the roles and understood headers are
544: * known, this calls a separate method to check the message headers
545: * since a different behavior is expected with different bindings.
546: *
547: * Also assume handler chain caller is null unless one is found.
548: */
549: private void checkMustUnderstandHeaders(XMLStreamReader reader,
550: MessageInfo mi, HandlerContext context) {
551:
552: // Decode envelope
553: XMLStreamReaderUtil.verifyReaderState(reader, START_ELEMENT);
554: QName got = reader.getName();
555: QName exp = getEnvelopeTag();
556: if (got.getLocalPart().equals(exp.getLocalPart())) {
557: if (!got.getNamespaceURI().equals(exp.getNamespaceURI())) {
558: raiseFault(getVersionMismatchFaultCode(),
559: "Invalid SOAP envelope version");
560: }
561: }
562: XMLStreamReaderUtil.verifyTag(reader, getEnvelopeTag());
563: XMLStreamReaderUtil.nextElementContent(reader);
564:
565: XMLStreamReaderUtil.verifyReaderState(reader, START_ELEMENT);
566: if (!SOAPNamespaceConstants.TAG_HEADER.equals(reader
567: .getLocalName())) {
568: return; // No Header, no MU processing
569: }
570: XMLStreamReaderUtil.verifyTag(reader, getHeaderTag());
571: XMLStreamReaderUtil.nextElementContent(reader);
572:
573: RuntimeContext rtCtxt = MessageInfoUtil.getRuntimeContext(mi);
574:
575: // start with just the endpoint roles
576: Set<String> roles = new HashSet<String>();
577: roles.addAll(getRequiredRoles());
578: HandlerChainCaller hcCaller = MessageInfoUtil
579: .getHandlerChainCaller(mi);
580: if (hcCaller != null) {
581: roles.addAll(hcCaller.getRoles());
582: }
583:
584: if (logger.isLoggable(Level.FINEST)) {
585: logger.finest("roles:");
586: for (String r : roles) {
587: logger.finest("\t\"" + r + "\"");
588: }
589: }
590:
591: // keep set=null if there are no understood headers
592: Set<QName> understoodHeaders = null;
593: if (rtCtxt != null) {
594: SOAPRuntimeModel model = (SOAPRuntimeModel) rtCtxt
595: .getModel();
596: if (model != null && model.getKnownHeaders() != null) {
597: understoodHeaders = new HashSet<QName>(
598: ((SOAPRuntimeModel) rtCtxt.getModel())
599: .getKnownHeaders());
600: }
601: }
602: if (understoodHeaders == null) {
603: if (hcCaller != null) {
604: understoodHeaders = hcCaller.getUnderstoodHeaders();
605: }
606: } else {
607: if (hcCaller != null) {
608: understoodHeaders.addAll(hcCaller
609: .getUnderstoodHeaders());
610: }
611: }
612:
613: if (logger.isLoggable(Level.FINEST)) {
614: logger.finest("understood headers:");
615: if (understoodHeaders == null
616: || understoodHeaders.isEmpty()) {
617: logger.finest("\tnone");
618: } else {
619: for (QName nameX : understoodHeaders) {
620: logger.finest("\t" + nameX.toString());
621: }
622: }
623: }
624:
625: checkHeadersAgainstKnown(reader, roles, understoodHeaders, mi);
626:
627: XMLStreamReaderUtil.verifyReaderState(reader, END_ELEMENT);
628: XMLStreamReaderUtil.verifyTag(reader, getHeaderTag());
629: XMLStreamReaderUtil.nextElementContent(reader);
630: }
631:
632: /*
633: * This method is overridden for other bindings
634: */
635: protected void checkHeadersAgainstKnown(XMLStreamReader reader,
636: Set<String> roles, Set<QName> understoodHeaders,
637: MessageInfo mi) {
638:
639: while (true) {
640: if (reader.getEventType() == START_ELEMENT) {
641: // check MU header for each role
642: QName qName = reader.getName();
643: String mu = reader.getAttributeValue(getMUAttrQName()
644: .getNamespaceURI(), getMUAttrQName()
645: .getLocalPart());
646: if (mu != null
647: && (mu.equals("1") || mu
648: .equalsIgnoreCase("true"))) {
649: String role = reader.getAttributeValue(
650: getRoleAttrQName().getNamespaceURI(),
651: getRoleAttrQName().getLocalPart());
652: if (role != null && roles.contains(role)) {
653: logger.finest("Element=" + qName
654: + " targeted at=" + role);
655: if (understoodHeaders == null
656: || !understoodHeaders.contains(qName)) {
657: logger.finest("Element not understood="
658: + qName);
659:
660: SOAPFault sf = SOAPUtil
661: .createSOAPFault(
662: MUST_UNDERSTAND_FAULT_MESSAGE_STRING,
663: SOAPConstants.FAULT_CODE_MUST_UNDERSTAND,
664: role,
665: null,
666: SOAPBinding.SOAP11HTTP_BINDING);
667: throw new SOAPFaultException(sf);
668: }
669: }
670: }
671: XMLStreamReaderUtil.skipElement(reader); // Moves to END state
672: XMLStreamReaderUtil.nextElementContent(reader);
673: } else {
674: break;
675: }
676: }
677: }
678:
679: protected boolean isDispatch(MessageInfo messageInfo) {
680:
681: DispatchContext context = (DispatchContext) messageInfo
682: .getMetaData(BindingProviderProperties.DISPATCH_CONTEXT);
683: if (context != null)
684: return true;
685: return false;
686: }
687:
688: protected String getSOAPMessageCharsetEncoding(SOAPMessage sm)
689: throws SOAPException {
690: String charset = (String) sm
691: .getProperty(SOAPMessage.CHARACTER_SET_ENCODING);
692: return (charset != null) ? charset : "UTF-8";
693: }
694:
695: protected final void raiseFault(QName faultCode, String faultString) {
696: throw new SOAPFaultException(SOAPUtil.createSOAPFault(
697: faultString, faultCode, null, null, getBindingId()));
698: }
699:
700: protected void raiseBadXMLFault(HandlerContext ctxt) {
701: }
702:
703: protected abstract QName getSenderFaultCode();
704:
705: protected abstract QName getReceiverFaultCode();
706:
707: protected abstract QName getVersionMismatchFaultCode();
708:
709: public abstract String getBindingId();
710:
711: private final static String DUPLICATE_HEADER = "Duplicate Header in the message:";
712:
713: public DispatchUtil getDispatchUtil() {
714: return dispatchUtil;
715: }
716:
717: protected DispatchUtil dispatchUtil = new DispatchUtil();
718:
719: }
|