001: /*
002: * Copyright 2006 the original author or authors.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package org.springframework.ws.soap.axiom;
018:
019: import java.io.IOException;
020: import java.io.OutputStream;
021: import java.util.Iterator;
022: import javax.activation.DataHandler;
023: import javax.xml.stream.XMLStreamException;
024:
025: import org.apache.axiom.attachments.Attachments;
026: import org.apache.axiom.om.OMElement;
027: import org.apache.axiom.om.OMException;
028: import org.apache.axiom.om.OMOutputFormat;
029: import org.apache.axiom.om.impl.MTOMConstants;
030: import org.apache.axiom.soap.SOAPBody;
031: import org.apache.axiom.soap.SOAPEnvelope;
032: import org.apache.axiom.soap.SOAPFactory;
033: import org.apache.axiom.soap.SOAPMessage;
034: import org.apache.axiom.soap.SOAPProcessingException;
035: import org.springframework.util.Assert;
036: import org.springframework.ws.mime.Attachment;
037: import org.springframework.ws.soap.AbstractSoapMessage;
038: import org.springframework.ws.soap.SoapEnvelope;
039: import org.springframework.ws.soap.SoapMessage;
040: import org.springframework.ws.soap.SoapVersion;
041: import org.springframework.ws.transport.TransportConstants;
042: import org.springframework.ws.transport.TransportOutputStream;
043:
044: /**
045: * AXIOM-specific implementation of the {@link SoapMessage} interface. Created via the {@link AxiomSoapMessageFactory},
046: * wraps a {@link SOAPMessage}.
047: *
048: * @author Arjen Poutsma
049: * @see SOAPMessage
050: * @since 1.0.0
051: */
052: public class AxiomSoapMessage extends AbstractSoapMessage {
053:
054: private final SOAPMessage axiomMessage;
055:
056: private final SOAPFactory axiomFactory;
057:
058: private final Attachments attachments;
059:
060: private boolean payloadCaching;
061:
062: private AxiomSoapEnvelope envelope;
063:
064: private String soapAction;
065:
066: /**
067: * Create a new, empty <code>AxiomSoapMessage</code>.
068: *
069: * @param soapFactory the AXIOM SOAPFactory
070: */
071: public AxiomSoapMessage(SOAPFactory soapFactory) {
072: SOAPEnvelope soapEnvelope = soapFactory.getDefaultEnvelope();
073: axiomFactory = soapFactory;
074: axiomMessage = axiomFactory.createSOAPMessage(soapEnvelope,
075: soapEnvelope.getBuilder());
076: attachments = new Attachments();
077: payloadCaching = true;
078: soapAction = "";
079: }
080:
081: /**
082: * Create a new <code>AxiomSoapMessage</code> based on the given AXIOM <code>SOAPMessage</code>.
083: *
084: * @param soapMessage the AXIOM SOAPMessage
085: * @param soapAction the value of the SOAP Action header
086: * @param payloadCaching whether the contents of the SOAP body should be cached or not
087: */
088: public AxiomSoapMessage(SOAPMessage soapMessage, String soapAction,
089: boolean payloadCaching) {
090: this (soapMessage, new Attachments(), soapAction, payloadCaching);
091: }
092:
093: /**
094: * Create a new <code>AxiomSoapMessage</code> based on the given AXIOM <code>SOAPMessage</code> and attachments.
095: *
096: * @param soapMessage the AXIOM SOAPMessage
097: * @param attachments the attachments
098: * @param soapAction the value of the SOAP Action header
099: * @param payloadCaching whether the contents of the SOAP body should be cached or not
100: */
101: public AxiomSoapMessage(SOAPMessage soapMessage,
102: Attachments attachments, String soapAction,
103: boolean payloadCaching) {
104: Assert.notNull(soapMessage, "'soapMessage' must not be null");
105: Assert.notNull(attachments, "'attachments' must not be null");
106: axiomMessage = soapMessage;
107: axiomFactory = (SOAPFactory) soapMessage.getSOAPEnvelope()
108: .getOMFactory();
109: this .attachments = attachments;
110: this .soapAction = soapAction;
111: this .payloadCaching = payloadCaching;
112: }
113:
114: /** Return the AXIOM <code>SOAPMessage</code> that this <code>AxiomSoapMessage</code> is based on. */
115: public final SOAPMessage getAxiomMessage() {
116: return axiomMessage;
117: }
118:
119: public SoapEnvelope getEnvelope() {
120: if (envelope == null) {
121: try {
122: envelope = new AxiomSoapEnvelope(axiomMessage
123: .getSOAPEnvelope(), axiomFactory,
124: payloadCaching);
125: } catch (SOAPProcessingException ex) {
126: throw new AxiomSoapEnvelopeException(ex);
127: }
128: }
129: return envelope;
130: }
131:
132: public String getSoapAction() {
133: return soapAction;
134: }
135:
136: public void setSoapAction(String soapAction) {
137: if (soapAction == null) {
138: this .soapAction = "";
139: } else {
140: this .soapAction = soapAction;
141: }
142: }
143:
144: public boolean isXopPackage() {
145: try {
146: return MTOMConstants.MTOM_TYPE.equals(attachments
147: .getAttachmentSpecType());
148: } catch (NullPointerException ex) {
149: // gotta love Axis2
150: return false;
151: }
152: }
153:
154: public boolean convertToXopPackage() {
155: return false;
156: }
157:
158: public Attachment getAttachment(String contentId) {
159: Assert.hasLength(contentId, "contentId must not be empty");
160: if (contentId.startsWith("<") && contentId.endsWith(">")) {
161: contentId = contentId.substring(1, contentId.length() - 1);
162: }
163: DataHandler dataHandler = attachments.getDataHandler(contentId);
164: return dataHandler != null ? new AxiomAttachment(contentId,
165: dataHandler) : null;
166: }
167:
168: public Iterator getAttachments() {
169: return new AxiomAttachmentIterator();
170: }
171:
172: public Attachment addAttachment(String contentId,
173: DataHandler dataHandler) {
174: Assert.hasLength(contentId, "contentId must not be empty");
175: Assert.notNull(dataHandler, "dataHandler must not be null");
176: attachments.addDataHandler(contentId, dataHandler);
177: return new AxiomAttachment(contentId, dataHandler);
178: }
179:
180: public void writeTo(OutputStream outputStream) throws IOException {
181: try {
182: String charsetEncoding = axiomMessage.getCharsetEncoding();
183:
184: OMOutputFormat format = new OMOutputFormat();
185: format.setCharSetEncoding(charsetEncoding);
186: format.setSOAP11(getVersion() == SoapVersion.SOAP_11);
187: if (!attachments.getContentIDSet().isEmpty()) {
188: format.setDoingSWA(true);
189: }
190: if (outputStream instanceof TransportOutputStream) {
191: TransportOutputStream transportOutputStream = (TransportOutputStream) outputStream;
192: String contentType = format.getContentType();
193: contentType += "; charset=\"" + charsetEncoding + "\"";
194: transportOutputStream.addHeader(
195: TransportConstants.HEADER_CONTENT_TYPE,
196: contentType);
197: transportOutputStream.addHeader(
198: TransportConstants.HEADER_SOAP_ACTION,
199: soapAction);
200: }
201: axiomMessage.serializeAndConsume(outputStream, format);
202: outputStream.flush();
203: } catch (XMLStreamException ex) {
204: throw new AxiomSoapMessageException(
205: "Could not write message to OutputStream: "
206: + ex.getMessage(), ex);
207: } catch (OMException ex) {
208: throw new AxiomSoapMessageException(
209: "Could not write message to OutputStream: "
210: + ex.getMessage(), ex);
211: }
212: }
213:
214: public String toString() {
215: StringBuffer buffer = new StringBuffer("AxiomSoapMessage");
216: try {
217: SOAPEnvelope envelope = axiomMessage.getSOAPEnvelope();
218: if (envelope != null) {
219: SOAPBody body = envelope.getBody();
220: if (body != null) {
221: OMElement bodyElement = body.getFirstElement();
222: if (bodyElement != null) {
223: buffer.append(' ');
224: buffer.append(bodyElement.getQName());
225: }
226: }
227: }
228: } catch (OMException ex) {
229: // ignore
230: }
231: return buffer.toString();
232: }
233:
234: private class AxiomAttachmentIterator implements Iterator {
235:
236: private final Iterator iterator;
237:
238: private AxiomAttachmentIterator() {
239: iterator = attachments.getContentIDSet().iterator();
240: }
241:
242: public boolean hasNext() {
243: return iterator.hasNext();
244: }
245:
246: public Object next() {
247: String contentId = (String) iterator.next();
248: DataHandler dataHandler = attachments
249: .getDataHandler(contentId);
250: return new AxiomAttachment(contentId, dataHandler);
251: }
252:
253: public void remove() {
254: iterator.remove();
255: }
256: }
257:
258: }
|