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.binding.soap.interceptor;
019:
020: import java.io.InputStream;
021: import java.util.ResourceBundle;
022: import java.util.logging.Logger;
023:
024: import javax.xml.namespace.QName;
025: import javax.xml.stream.XMLStreamConstants;
026: import javax.xml.stream.XMLStreamException;
027: import javax.xml.stream.XMLStreamReader;
028:
029: import org.w3c.dom.Attr;
030: import org.w3c.dom.Document;
031: import org.w3c.dom.Element;
032: import org.w3c.dom.NamedNodeMap;
033: import org.w3c.dom.Node;
034: import org.w3c.dom.NodeList;
035:
036: import org.apache.cxf.Bus;
037: import org.apache.cxf.binding.soap.Soap11;
038: import org.apache.cxf.binding.soap.SoapFault;
039: import org.apache.cxf.binding.soap.SoapHeader;
040: import org.apache.cxf.binding.soap.SoapMessage;
041: import org.apache.cxf.binding.soap.SoapVersion;
042: import org.apache.cxf.binding.soap.SoapVersionFactory;
043: import org.apache.cxf.common.i18n.BundleUtils;
044: import org.apache.cxf.common.i18n.Message;
045: import org.apache.cxf.databinding.DataBinding;
046: import org.apache.cxf.endpoint.Endpoint;
047: import org.apache.cxf.headers.HeaderManager;
048: import org.apache.cxf.headers.HeaderProcessor;
049: import org.apache.cxf.phase.Phase;
050: import org.apache.cxf.staxutils.PartialXMLStreamReader;
051: import org.apache.cxf.staxutils.StaxUtils;
052:
053: import static org.apache.cxf.message.Message.DECOUPLED_CHANNEL_MESSAGE;
054:
055: public class ReadHeadersInterceptor extends AbstractSoapInterceptor {
056: private static final Logger LOG = Logger
057: .getLogger(ReadHeadersInterceptor.class.getName());
058: private static final ResourceBundle BUNDLE = BundleUtils
059: .getBundle(ReadHeadersInterceptor.class);
060:
061: private Bus bus;
062:
063: public ReadHeadersInterceptor(Bus b) {
064: super (Phase.READ);
065: bus = b;
066: }
067:
068: public ReadHeadersInterceptor(Bus b, String phase) {
069: super (phase);
070: bus = b;
071: }
072:
073: public void handleMessage(SoapMessage message) {
074: if (isGET(message)) {
075: LOG
076: .info("ReadHeadersInterceptor skipped in HTTP GET method");
077: return;
078: }
079: XMLStreamReader xmlReader = message
080: .getContent(XMLStreamReader.class);
081:
082: if (xmlReader == null) {
083: InputStream in = (InputStream) message
084: .getContent(InputStream.class);
085: if (in == null) {
086: throw new RuntimeException(
087: "Can't found input stream in message");
088: }
089: xmlReader = StaxUtils.createXMLStreamReader(in);
090: }
091:
092: try {
093: if (xmlReader.nextTag() == XMLStreamConstants.START_ELEMENT) {
094: String ns = xmlReader.getNamespaceURI();
095:
096: SoapVersion soapVersion = SoapVersionFactory
097: .getInstance().getSoapVersion(ns);
098: if (soapVersion == null) {
099: throw new SoapFault(new Message("INVALID_VERSION",
100: BUNDLE, ns), Soap11.getInstance()
101: .getVersionMismatch());
102: }
103: message.setVersion(soapVersion);
104:
105: XMLStreamReader filteredReader = new PartialXMLStreamReader(
106: xmlReader, message.getVersion().getBody());
107:
108: Document doc = StaxUtils.read(filteredReader);
109:
110: message.setContent(Node.class, doc);
111:
112: // Find header
113: // TODO - we could stream read the "known" headers and just DOM read the
114: // unknown ones
115: Element element = doc.getDocumentElement();
116: QName header = soapVersion.getHeader();
117: NodeList headerEls = element
118: .getElementsByTagNameNS(header
119: .getNamespaceURI(), header
120: .getLocalPart());
121: for (int i = 0; i < headerEls.getLength(); i++) {
122: Node currentHead = headerEls.item(i);
123: Node node = currentHead;
124: NodeList heads = node.getChildNodes();
125: int len = heads.getLength();
126: for (int x = 0; x < len; x++) {
127: node = (Node) heads.item(x);
128: if (node.getNodeType() == Node.ELEMENT_NODE) {
129: Element hel = (Element) node;
130: // Need to add any attributes that are present on the parent element
131: // which otherwise would be lost.
132: if (currentHead.hasAttributes()) {
133: NamedNodeMap nnp = currentHead
134: .getAttributes();
135: for (int ct = 0; ct < nnp.getLength(); ct++) {
136: Node attr = nnp.item(ct);
137: Node headerAttrNode = hel
138: .hasAttributes() ? hel
139: .getAttributes()
140: .getNamedItemNS(
141: attr
142: .getNamespaceURI(),
143: attr.getLocalName())
144: : null;
145:
146: if (headerAttrNode == null) {
147: Attr attribute = hel
148: .getOwnerDocument()
149: .createAttributeNS(
150: attr
151: .getNamespaceURI(),
152: attr
153: .getNodeName());
154: attribute.setNodeValue(attr
155: .getNodeValue());
156: hel
157: .setAttributeNodeNS(attribute);
158: }
159: }
160: }
161:
162: // System.out.println("READHEADERSINTERCEPTOR : node name : "
163: // + node.getLocalName() + " namespace URI" + node.getNamespaceURI());
164: HeaderProcessor p = bus.getExtension(
165: HeaderManager.class)
166: .getHeaderProcessor(
167: hel.getNamespaceURI());
168:
169: Object obj;
170: DataBinding dataBinding = null;
171: if (p == null || p.getDataBinding() == null) {
172: obj = node;
173: } else {
174: obj = p.getDataBinding().createReader(
175: Node.class).read(node);
176: }
177: //TODO - add the interceptors
178:
179: SoapHeader shead = new SoapHeader(
180: new QName(node.getNamespaceURI(),
181: node.getLocalName()), obj,
182: dataBinding);
183: String mu = hel.getAttributeNS(soapVersion
184: .getNamespace(), soapVersion
185: .getAttrNameMustUnderstand());
186: String act = hel.getAttributeNS(soapVersion
187: .getNamespace(), soapVersion
188: .getAttrNameRole());
189:
190: shead.setActor(act);
191: shead.setMustUnderstand(Boolean.valueOf(mu)
192: || "1".equals(mu));
193: //mark header as inbound header.(for distinguishing between the direction to
194: //avoid piggybacking of headers from request->server->response.
195: shead
196: .setDirection(SoapHeader.Direction.DIRECTION_IN);
197: message.getHeaders().add(shead);
198: }
199: }
200: }
201:
202: // advance just past body.
203: xmlReader.nextTag();
204: if (message.getVersion().getFault().equals(
205: xmlReader.getName())) {
206: Endpoint ep = message.getExchange().get(
207: Endpoint.class);
208: if (!isDecoupled(message)) {
209: message.getInterceptorChain().abort();
210: if (ep.getInFaultObserver() != null) {
211: ep.getInFaultObserver().onMessage(message);
212: }
213: } else {
214: message.getExchange().put(
215: "deferred.fault.observer.notification",
216: Boolean.TRUE);
217: }
218: }
219: }
220: } catch (XMLStreamException e) {
221: throw new SoapFault(new Message("XML_STREAM_EXC", BUNDLE),
222: e, message.getVersion().getSender());
223: }
224: }
225:
226: private boolean isDecoupled(SoapMessage message) {
227: Boolean decoupled = (Boolean) message
228: .get(DECOUPLED_CHANNEL_MESSAGE);
229: return decoupled != null && decoupled.booleanValue();
230: }
231: }
|