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.jaxws.interceptors;
019:
020: import java.io.IOException;
021: import java.io.InputStream;
022: import java.io.OutputStream;
023: import java.util.List;
024: import java.util.logging.Logger;
025:
026: import javax.activation.DataSource;
027: import javax.xml.parsers.ParserConfigurationException;
028: import javax.xml.soap.MessageFactory;
029: import javax.xml.soap.MimeHeaders;
030: import javax.xml.soap.SOAPConstants;
031: import javax.xml.soap.SOAPMessage;
032: import javax.xml.stream.XMLStreamWriter;
033: import javax.xml.transform.Source;
034: import javax.xml.transform.Transformer;
035: import javax.xml.transform.TransformerException;
036: import javax.xml.transform.dom.DOMSource;
037: import javax.xml.transform.stream.StreamResult;
038: import javax.xml.ws.Service;
039: import javax.xml.ws.Service.Mode;
040:
041: import org.w3c.dom.Node;
042:
043: import org.apache.cxf.binding.soap.Soap11;
044: import org.apache.cxf.binding.soap.Soap12;
045: import org.apache.cxf.binding.soap.SoapMessage;
046: import org.apache.cxf.binding.soap.SoapVersion;
047: import org.apache.cxf.common.logging.LogUtils;
048: import org.apache.cxf.databinding.DataWriter;
049: import org.apache.cxf.databinding.source.NodeDataWriter;
050: import org.apache.cxf.helpers.DOMUtils;
051: import org.apache.cxf.helpers.IOUtils;
052: import org.apache.cxf.helpers.XMLUtils;
053: import org.apache.cxf.interceptor.AbstractInDatabindingInterceptor;
054: import org.apache.cxf.interceptor.AbstractOutDatabindingInterceptor;
055: import org.apache.cxf.interceptor.Fault;
056: import org.apache.cxf.io.CachedOutputStream;
057: import org.apache.cxf.jaxws.handler.logical.DispatchLogicalHandlerInterceptor;
058: import org.apache.cxf.message.Message;
059: import org.apache.cxf.message.XMLMessage;
060: import org.apache.cxf.phase.Phase;
061: import org.apache.cxf.staxutils.W3CDOMStreamWriter;
062: import org.apache.cxf.wsdl.WSDLConstants;
063:
064: public class DispatchOutDatabindingInterceptor extends
065: AbstractOutDatabindingInterceptor {
066: private static final Logger LOG = LogUtils
067: .getL7dLogger(DispatchOutDatabindingInterceptor.class);
068: private DispatchOutDatabindingEndingInterceptor ending;
069:
070: private Service.Mode mode;
071:
072: public DispatchOutDatabindingInterceptor(Mode mode) {
073: super (Phase.WRITE);
074: ending = new DispatchOutDatabindingEndingInterceptor();
075:
076: this .mode = mode;
077: }
078:
079: public void handleMessage(Message message) throws Fault {
080: org.apache.cxf.service.Service service = message.getExchange()
081: .get(org.apache.cxf.service.Service.class);
082:
083: Object obj = null;
084: Object result = message.getContent(List.class);
085: if (result != null) {
086: obj = ((List) result).get(0);
087: message.setContent(Object.class, obj);
088: } else {
089: obj = message.getContent(Object.class);
090: }
091: message.removeContent(Object.class);
092:
093: if (obj == null) {
094: throw new Fault(new org.apache.cxf.common.i18n.Message(
095: "DISPATCH_OBJECT_CANNOT_BE_NULL", LOG));
096: }
097:
098: if (message instanceof SoapMessage) {
099: Source source = null;
100: if (mode == Service.Mode.PAYLOAD) {
101: if (obj instanceof SOAPMessage
102: || obj instanceof DataSource) {
103: throw new Fault(
104: new org.apache.cxf.common.i18n.Message(
105: "DISPATCH_OBJECT_NOT_SUPPORTED_SOAPBINDING",
106: LOG, obj.getClass(), "PAYLOAD"));
107: } else if (obj instanceof Source) {
108: source = (Source) obj;
109: } else {
110: //JAXB
111: try {
112: SOAPMessage msg = newSOAPMessage(null,
113: ((SoapMessage) message).getVersion());
114: DataWriter<Node> dataWriter = getDataWriter(
115: message, service, Node.class);
116: dataWriter.write(obj, msg.getSOAPBody());
117: //msg.writeTo(System.out);
118: source = new DOMSource(DOMUtils.getChild(msg
119: .getSOAPBody(), Node.ELEMENT_NODE));
120: } catch (Exception e) {
121: throw new Fault(
122: new org.apache.cxf.common.i18n.Message(
123: "EXCEPTION_WRITING_OBJECT", LOG),
124: e);
125: }
126: }
127: } else {
128: if (obj instanceof DataSource) {
129: throw new Fault(
130: new org.apache.cxf.common.i18n.Message(
131: "DISPATCH_OBJECT_NOT_SUPPORTED_SOAPBINDING",
132: LOG, "DataSource", "MESSAGE"));
133: } else if (obj instanceof SOAPMessage) {
134: source = new DOMSource(((SOAPMessage) obj)
135: .getSOAPPart());
136: } else if (obj instanceof Source) {
137: source = (Source) obj;
138: }
139: }
140:
141: PostDispatchOutLogicalHandlerInterceptor postSoap = new PostDispatchOutLogicalHandlerInterceptor();
142: message.getInterceptorChain().add(postSoap);
143:
144: message.setContent(Source.class, source);
145: } else if (message instanceof XMLMessage) {
146: if (obj instanceof SOAPMessage) {
147: throw new Fault(new org.apache.cxf.common.i18n.Message(
148: "DISPATCH_OBJECT_NOT_SUPPORTED_XMLBINDING",
149: LOG, "SOAPMessage", "PAYLOAD/MESSAGE"));
150: }
151:
152: if (mode == Service.Mode.PAYLOAD
153: && obj instanceof DataSource) {
154: throw new Fault(new org.apache.cxf.common.i18n.Message(
155: "DISPATCH_OBJECT_NOT_SUPPORTED_XMLBINDING",
156: LOG, "DataSource", "PAYLOAD"));
157: }
158:
159: if (obj instanceof DataSource) {
160: message.setContent(DataSource.class, obj);
161: } else if (obj instanceof Source) {
162: message.setContent(Source.class, obj);
163: } else {
164: // JAXB element
165: try {
166: DataWriter<XMLStreamWriter> dataWriter = getDataWriter(
167: message, service, XMLStreamWriter.class);
168: W3CDOMStreamWriter xmlWriter = new W3CDOMStreamWriter();
169: dataWriter.write(obj, xmlWriter);
170:
171: Source source = new DOMSource(xmlWriter
172: .getDocument().getDocumentElement());
173: message.setContent(Source.class, source);
174: } catch (ParserConfigurationException e) {
175: throw new Fault(
176: new org.apache.cxf.common.i18n.Message(
177: "EXCEPTION_WRITING_OBJECT", LOG), e);
178: }
179: }
180: }
181: message.getInterceptorChain().add(ending);
182: }
183:
184: private class DispatchOutDatabindingEndingInterceptor extends
185: AbstractOutDatabindingInterceptor {
186: public DispatchOutDatabindingEndingInterceptor() {
187: super (Phase.WRITE_ENDING);
188: }
189:
190: public void handleMessage(Message message) throws Fault {
191: OutputStream os = message.getContent(OutputStream.class);
192:
193: XMLStreamWriter xmlWriter = message
194: .getContent(XMLStreamWriter.class);
195: SOAPMessage soapMessage = message
196: .getContent(SOAPMessage.class);
197: Source source = message.getContent(Source.class);
198: DataSource dataSource = message
199: .getContent(DataSource.class);
200:
201: try {
202: if (xmlWriter != null) {
203: xmlWriter.flush();
204: } else if (soapMessage != null) {
205: soapMessage.writeTo(os);
206: } else if (source != null) {
207: doTransform(source, os);
208: } else if (dataSource != null) {
209: doTransform(dataSource, os);
210: }
211:
212: // Finish the message processing, do flush
213: os.flush();
214: } catch (Exception ex) {
215: throw new Fault(new org.apache.cxf.common.i18n.Message(
216: "EXCEPTION_WRITING_OBJECT", LOG, ex));
217: }
218: }
219: }
220:
221: //This interceptor is invoked after DispatchLogicalHandlerInterceptor, converts Source to SOAPMessage
222: private class PostDispatchOutLogicalHandlerInterceptor extends
223: AbstractInDatabindingInterceptor {
224:
225: public PostDispatchOutLogicalHandlerInterceptor() {
226: super (Phase.PRE_MARSHAL);
227: addAfter(DispatchLogicalHandlerInterceptor.class.getName());
228: }
229:
230: public void handleMessage(Message message) throws Fault {
231: Object obj = null;
232:
233: //Convert Source to SOAPMessage
234: if (message instanceof SoapMessage) {
235: Source source = message.getContent(Source.class);
236: message.removeContent(Source.class);
237:
238: if (mode == Service.Mode.PAYLOAD) {
239: // Input is Source in payload mode, need to wrap it
240: // with a SOAPMessage
241: try {
242: obj = newSOAPMessage(null,
243: ((SoapMessage) message).getVersion());
244: DataWriter<Node> dataWriter = new NodeDataWriter();
245: dataWriter.write(source, ((SOAPMessage) obj)
246: .getSOAPBody());
247: } catch (Exception e) {
248: throw new Fault(
249: new org.apache.cxf.common.i18n.Message(
250: "EXCEPTION_WRITING_OBJECT", LOG),
251: e);
252: }
253: } else {
254: try {
255: CachedOutputStream cos = new CachedOutputStream();
256: Transformer transformer = XMLUtils
257: .newTransformer();
258: transformer.transform(source, new StreamResult(
259: cos));
260: obj = newSOAPMessage(cos.getInputStream(),
261: ((SoapMessage) message).getVersion());
262: } catch (Exception e) {
263: throw new Fault(e);
264: }
265: }
266: message.setContent(SOAPMessage.class, obj);
267: }
268: }
269: }
270:
271: private SOAPMessage newSOAPMessage(InputStream is,
272: SoapVersion version) throws Exception {
273: SOAPMessage msg = null;
274:
275: MimeHeaders headers = new MimeHeaders();
276: MessageFactory msgFactory = null;
277: if (version == null || version instanceof Soap11) {
278: msgFactory = MessageFactory.newInstance();
279: } else if (version instanceof Soap12) {
280: msgFactory = MessageFactory
281: .newInstance(SOAPConstants.SOAP_1_2_PROTOCOL);
282: }
283:
284: if (is != null) {
285: msg = msgFactory.createMessage(headers, is);
286: } else {
287: msg = msgFactory.createMessage();
288: }
289: msg.setProperty(SOAPMessage.WRITE_XML_DECLARATION, "true");
290: msg.getSOAPPart().getEnvelope().addNamespaceDeclaration(
291: WSDLConstants.NP_SCHEMA_XSD,
292: WSDLConstants.NU_SCHEMA_XSD);
293: msg.getSOAPPart().getEnvelope().addNamespaceDeclaration(
294: WSDLConstants.NP_SCHEMA_XSI,
295: WSDLConstants.NU_SCHEMA_XSI);
296: return msg;
297: }
298:
299: private void doTransform(Object obj, OutputStream os)
300: throws TransformerException, IOException {
301: if (obj instanceof Source) {
302: Transformer transformer = XMLUtils.newTransformer();
303: transformer.transform((Source) obj, new StreamResult(os));
304: }
305: if (obj instanceof DataSource) {
306: InputStream is = ((DataSource) obj).getInputStream();
307: IOUtils.copy(((DataSource) obj).getInputStream(), os);
308: is.close();
309: }
310: }
311:
312: }
|