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: */
019: package org.apache.axis2.jaxws.handler;
020:
021: import org.apache.axiom.om.util.StAXUtils;
022: import org.apache.axiom.soap.SOAPEnvelope;
023: import org.apache.axis2.jaxws.ExceptionFactory;
024: import org.apache.axis2.jaxws.message.Block;
025: import org.apache.axis2.jaxws.message.Message;
026: import org.apache.axis2.jaxws.message.databinding.JAXBBlockContext;
027: import org.apache.axis2.jaxws.message.factory.BlockFactory;
028: import org.apache.axis2.jaxws.message.factory.JAXBBlockFactory;
029: import org.apache.axis2.jaxws.message.factory.MessageFactory;
030: import org.apache.axis2.jaxws.message.factory.SourceBlockFactory;
031: import org.apache.axis2.jaxws.registry.FactoryRegistry;
032: import org.apache.commons.logging.Log;
033: import org.apache.commons.logging.LogFactory;
034: import org.w3c.dom.Document;
035: import org.xml.sax.SAXException;
036:
037: import javax.xml.bind.JAXBContext;
038: import javax.xml.parsers.DocumentBuilder;
039: import javax.xml.parsers.DocumentBuilderFactory;
040: import javax.xml.parsers.ParserConfigurationException;
041: import javax.xml.stream.XMLStreamException;
042: import javax.xml.stream.XMLStreamReader;
043: import javax.xml.transform.OutputKeys;
044: import javax.xml.transform.Source;
045: import javax.xml.transform.Transformer;
046: import javax.xml.transform.TransformerConfigurationException;
047: import javax.xml.transform.TransformerException;
048: import javax.xml.transform.TransformerFactory;
049: import javax.xml.transform.TransformerFactoryConfigurationError;
050: import javax.xml.transform.dom.DOMSource;
051: import javax.xml.transform.stream.StreamResult;
052: import javax.xml.transform.stream.StreamSource;
053: import javax.xml.ws.LogicalMessage;
054:
055: import java.io.ByteArrayInputStream;
056: import java.io.ByteArrayOutputStream;
057: import java.io.IOException;
058: import java.io.StringReader;
059:
060: public class LogicalMessageImpl implements LogicalMessage {
061:
062: private static final Log log = LogFactory
063: .getLog(LogicalMessageImpl.class);
064:
065: private MEPContext mepCtx;
066:
067: protected LogicalMessageImpl(MEPContext m) {
068: mepCtx = m;
069: }
070:
071: /*
072: * (non-Javadoc)
073: * @see javax.xml.ws.LogicalMessage#getPayload()
074: */
075: public Source getPayload() {
076: BlockFactory factory = (SourceBlockFactory) FactoryRegistry
077: .getFactory(SourceBlockFactory.class);
078: Source payload = (Source) _getPayload(null, factory);
079: return payload;
080: }
081:
082: /*
083: * (non-Javadoc)
084: * @see javax.xml.ws.LogicalMessage#getPayload(javax.xml.bind.JAXBContext)
085: */
086: public Object getPayload(JAXBContext context) {
087: if (log.isDebugEnabled()) {
088: log
089: .debug("Retreiving the message payload as a Source object");
090: }
091:
092: BlockFactory factory = (JAXBBlockFactory) FactoryRegistry
093: .getFactory(JAXBBlockFactory.class);
094: JAXBBlockContext jbc = new JAXBBlockContext(context);
095: Object payload = _getPayload(jbc, factory);
096: return payload;
097: }
098:
099: private Object _getPayload(Object context, BlockFactory factory) {
100: Object payload = null;
101: try {
102: Block block = mepCtx.getMessageObject().getBodyBlock(
103: context, factory);
104: if (block != null) {
105: if (log.isDebugEnabled()) {
106: log.debug("A message payload was found.");
107: }
108: Object content = block.getBusinessObject(true);
109:
110: // For now, we have to create a new Block from the original content
111: // and set that back on the message. The Block is not currently
112: // able to create a copy of itself just yet.
113: Payloads payloads = createPayloads(content);
114: _setPayload(payloads.CACHE_PAYLOAD, context, factory);
115:
116: payload = payloads.HANDLER_PAYLOAD;
117: } else {
118: // If the block was null, then let's return an empty
119: // Source object rather than a null.
120: if (log.isDebugEnabled()) {
121: log
122: .debug("There was no payload to be found. Returning an empty Source object");
123: }
124: byte[] bytes = new byte[0];
125: payload = new StreamSource(new ByteArrayInputStream(
126: bytes));
127: }
128:
129: } catch (XMLStreamException e) {
130: throw ExceptionFactory.makeWebServiceException(e);
131: }
132:
133: return payload;
134: }
135:
136: /*
137: * (non-Javadoc)
138: * @see javax.xml.ws.LogicalMessage#setPayload(java.lang.Object, javax.xml.bind.JAXBContext)
139: */
140: public void setPayload(Object obj, JAXBContext context) {
141: BlockFactory factory = (JAXBBlockFactory) FactoryRegistry
142: .getFactory(JAXBBlockFactory.class);
143: JAXBBlockContext jbc = new JAXBBlockContext(context);
144: _setPayload(obj, jbc, factory);
145: }
146:
147: /*
148: * (non-Javadoc)
149: * @see javax.xml.ws.LogicalMessage#setPayload(javax.xml.transform.Source)
150: */
151: public void setPayload(Source source) {
152: BlockFactory factory = (SourceBlockFactory) FactoryRegistry
153: .getFactory(SourceBlockFactory.class);
154: _setPayload(source, null, factory);
155: }
156:
157: private void _setPayload(Object object, Object context,
158: BlockFactory factory) {
159: Block block = factory.createFrom(object, context, null);
160:
161: if (mepCtx.getMessageObject() != null) {
162: if (!mepCtx.getMessageObject().isFault()) {
163: mepCtx.getMessageObject().setBodyBlock(block);
164: } else {
165: if (log.isDebugEnabled()) {
166: log.debug("The payload contains a fault");
167: }
168:
169: mepCtx.getMessageObject().setBodyBlock(block);
170:
171: // If the payload is a fault, then we can't set it back on the message
172: // as a block. Blocks are OMSourcedElements, and faults cannot be OMSourcedElements.
173: try {
174: SOAPEnvelope env = (SOAPEnvelope) mepCtx
175: .getMessageObject().getAsOMElement();
176: String content = env.toStringWithConsume();
177:
178: MessageFactory mf = (MessageFactory) FactoryRegistry
179: .getFactory(MessageFactory.class);
180: StringReader sr = new StringReader(content);
181: XMLStreamReader stream = StAXUtils
182: .createXMLStreamReader(sr);
183: Message msg = mf.createFrom(stream, mepCtx
184: .getMessageObject().getProtocol());
185:
186: // This is required for proper serialization of the OM structure.
187: msg.getAsOMElement().build();
188:
189: mepCtx.setMessage(msg);
190: } catch (Exception e) {
191: throw ExceptionFactory.makeWebServiceException(e);
192: }
193: }
194: }
195: }
196:
197: private Payloads createPayloads(Object content) {
198: if (content == null) {
199: return null;
200: }
201:
202: Payloads payloads = new Payloads();
203:
204: if (Source.class.isAssignableFrom(content.getClass())) {
205: try {
206: Transformer trans = TransformerFactory.newInstance()
207: .newTransformer();
208:
209: // First we have to get the content out of the original
210: // Source object so we can build the cache from there.
211: ByteArrayOutputStream baos = new ByteArrayOutputStream();
212: StreamResult result = new StreamResult(baos);
213:
214: Source source = (Source) content;
215: trans.transform(source, result);
216: trans.setOutputProperty(
217: OutputKeys.OMIT_XML_DECLARATION, "yes");
218: byte[] bytes = baos.toByteArray();
219:
220: // Given that we've consumed the original Source object,
221: // we need to create another one with the original content
222: // and assign it back.
223: ByteArrayInputStream bais = new ByteArrayInputStream(
224: bytes);
225: try {
226: // The Source object returned to the handler should be a
227: // DOMSource so that the handler programmer can read the data
228: // multiple times and (as opposed to using a StreamSource) and
229: // they can more easily access the data in DOM form.
230: DocumentBuilderFactory dbf = DocumentBuilderFactory
231: .newInstance();
232: dbf.setNamespaceAware(true);
233:
234: DocumentBuilder db = dbf.newDocumentBuilder();
235: Document dom = db.parse(bais);
236: payloads.HANDLER_PAYLOAD = new DOMSource(dom);
237: } catch (ParserConfigurationException e) {
238: throw ExceptionFactory.makeWebServiceException(e);
239: } catch (IOException e) {
240: throw ExceptionFactory.makeWebServiceException(e);
241: } catch (SAXException e) {
242: throw ExceptionFactory.makeWebServiceException(e);
243: }
244:
245: // We need a different byte[] for the cache so that we're not just
246: // building two Source objects that point to the same array.
247: byte[] cacheBytes = new byte[bytes.length];
248: System.arraycopy(bytes, 0, cacheBytes, 0, bytes.length);
249:
250: // Now build the Soure object for the cache.
251: ByteArrayInputStream cacheBais = new ByteArrayInputStream(
252: cacheBytes);
253: payloads.CACHE_PAYLOAD = new StreamSource(cacheBais);
254: } catch (TransformerConfigurationException e) {
255: throw ExceptionFactory.makeWebServiceException(e);
256: } catch (TransformerFactoryConfigurationError e) {
257: throw ExceptionFactory.makeWebServiceException(e);
258: } catch (TransformerException e) {
259: throw ExceptionFactory.makeWebServiceException(e);
260: }
261: } else {
262: // no cache implemented yet
263: payloads.HANDLER_PAYLOAD = content;
264: payloads.CACHE_PAYLOAD = content;
265: }
266:
267: return payloads;
268: }
269:
270: /*
271: * A simple holder for the different payload objects.
272: */
273: class Payloads {
274: Object HANDLER_PAYLOAD; // The payload object that will be returned to the handler
275: Object CACHE_PAYLOAD; // The payload object that will be used for the cache
276: }
277:
278: }
|