1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.springframework.ws.soap.axiom;
18
19 import java.io.IOException;
20 import java.io.OutputStream;
21 import java.io.StringWriter;
22 import java.io.UnsupportedEncodingException;
23 import java.util.Iterator;
24 import javax.activation.DataHandler;
25 import javax.xml.stream.XMLStreamException;
26
27 import org.apache.axiom.attachments.Attachments;
28 import org.apache.axiom.om.OMElement;
29 import org.apache.axiom.om.OMException;
30 import org.apache.axiom.om.OMOutputFormat;
31 import org.apache.axiom.om.impl.MIMEOutputUtils;
32 import org.apache.axiom.om.impl.MTOMConstants;
33 import org.apache.axiom.soap.SOAPBody;
34 import org.apache.axiom.soap.SOAPEnvelope;
35 import org.apache.axiom.soap.SOAPFactory;
36 import org.apache.axiom.soap.SOAPMessage;
37 import org.apache.axiom.soap.SOAPProcessingException;
38
39 import org.springframework.util.Assert;
40 import org.springframework.util.StringUtils;
41 import org.springframework.ws.mime.Attachment;
42 import org.springframework.ws.soap.AbstractSoapMessage;
43 import org.springframework.ws.soap.SoapEnvelope;
44 import org.springframework.ws.soap.SoapMessage;
45 import org.springframework.ws.soap.SoapVersion;
46 import org.springframework.ws.soap.support.SoapUtils;
47 import org.springframework.ws.transport.TransportConstants;
48 import org.springframework.ws.transport.TransportOutputStream;
49
50
51
52
53
54
55
56
57
58 public class AxiomSoapMessage extends AbstractSoapMessage {
59
60 private static final String EMPTY_SOAP_ACTION = "\"\"";
61
62 private SOAPMessage axiomMessage;
63
64 private final SOAPFactory axiomFactory;
65
66 private final Attachments attachments;
67
68 private final boolean payloadCaching;
69
70 private AxiomSoapEnvelope envelope;
71
72 private String soapAction;
73
74
75
76
77
78
79 public AxiomSoapMessage(SOAPFactory soapFactory) {
80 this(soapFactory, true);
81 }
82
83
84
85
86
87
88 public AxiomSoapMessage(SOAPFactory soapFactory, boolean payloadCaching) {
89 SOAPEnvelope soapEnvelope = soapFactory.getDefaultEnvelope();
90 axiomFactory = soapFactory;
91 axiomMessage = axiomFactory.createSOAPMessage(soapEnvelope, soapEnvelope.getBuilder());
92 attachments = new Attachments();
93 this.payloadCaching = payloadCaching;
94 soapAction = EMPTY_SOAP_ACTION;
95 }
96
97
98
99
100
101
102
103
104 public AxiomSoapMessage(SOAPMessage soapMessage, String soapAction, boolean payloadCaching) {
105 this(soapMessage, new Attachments(), soapAction, payloadCaching);
106 }
107
108
109
110
111
112
113
114
115
116 public AxiomSoapMessage(SOAPMessage soapMessage,
117 Attachments attachments,
118 String soapAction,
119 boolean payloadCaching) {
120 Assert.notNull(soapMessage, "'soapMessage' must not be null");
121 Assert.notNull(attachments, "'attachments' must not be null");
122 axiomMessage = soapMessage;
123 axiomFactory = (SOAPFactory) soapMessage.getSOAPEnvelope().getOMFactory();
124 this.attachments = attachments;
125 if (!StringUtils.hasLength(soapAction)) {
126 soapAction = EMPTY_SOAP_ACTION;
127 }
128 this.soapAction = soapAction;
129 this.payloadCaching = payloadCaching;
130 }
131
132
133 public final SOAPMessage getAxiomMessage() {
134 return axiomMessage;
135 }
136
137
138
139
140
141
142 public final void setAxiomMessage(SOAPMessage axiomMessage) {
143 Assert.notNull(axiomMessage, "'axiomMessage' must not be null");
144 this.axiomMessage = axiomMessage;
145 this.envelope = null;
146 this.soapAction = EMPTY_SOAP_ACTION;
147 }
148
149 public SoapEnvelope getEnvelope() {
150 if (envelope == null) {
151 try {
152 envelope = new AxiomSoapEnvelope(axiomMessage.getSOAPEnvelope(), axiomFactory, payloadCaching);
153 }
154 catch (SOAPProcessingException ex) {
155 throw new AxiomSoapEnvelopeException(ex);
156 }
157 }
158 return envelope;
159 }
160
161 public String getSoapAction() {
162 return soapAction;
163 }
164
165 public void setSoapAction(String soapAction) {
166 soapAction = SoapUtils.escapeAction(soapAction);
167 this.soapAction = soapAction;
168 }
169
170 public boolean isXopPackage() {
171 try {
172 return MTOMConstants.MTOM_TYPE.equals(attachments.getAttachmentSpecType());
173 }
174 catch (NullPointerException ex) {
175
176 return false;
177 }
178 }
179
180 public boolean convertToXopPackage() {
181 return false;
182 }
183
184 public Attachment getAttachment(String contentId) {
185 Assert.hasLength(contentId, "contentId must not be empty");
186 if (contentId.startsWith("<") && contentId.endsWith(">")) {
187 contentId = contentId.substring(1, contentId.length() - 1);
188 }
189 DataHandler dataHandler = attachments.getDataHandler(contentId);
190 return dataHandler != null ? new AxiomAttachment(contentId, dataHandler) : null;
191 }
192
193 public Iterator getAttachments() {
194 return new AxiomAttachmentIterator();
195 }
196
197 public Attachment addAttachment(String contentId, DataHandler dataHandler) {
198 Assert.hasLength(contentId, "contentId must not be empty");
199 Assert.notNull(dataHandler, "dataHandler must not be null");
200 attachments.addDataHandler(contentId, dataHandler);
201 return new AxiomAttachment(contentId, dataHandler);
202 }
203
204 public void writeTo(OutputStream outputStream) throws IOException {
205 try {
206 String charsetEncoding = axiomMessage.getCharsetEncoding();
207
208 OMOutputFormat format = new OMOutputFormat();
209 format.setCharSetEncoding(charsetEncoding);
210 format.setSOAP11(getVersion() == SoapVersion.SOAP_11);
211 boolean hasAttachments = !attachments.getContentIDSet().isEmpty();
212 if (hasAttachments) {
213 if (isXopPackage()) {
214 format.setDoOptimize(true);
215 }
216 else {
217 format.setDoingSWA(true);
218 }
219 }
220 if (outputStream instanceof TransportOutputStream) {
221 TransportOutputStream transportOutputStream = (TransportOutputStream) outputStream;
222 String contentType = format.getContentType();
223 if (!hasAttachments) {
224 contentType += "; charset=\"" + charsetEncoding + "\"";
225 }
226 if (SoapVersion.SOAP_11 == getVersion()) {
227 transportOutputStream.addHeader(TransportConstants.HEADER_SOAP_ACTION, soapAction);
228 }
229 else if (SoapVersion.SOAP_12 == getVersion()) {
230 contentType += "; action=" + soapAction;
231 }
232 transportOutputStream.addHeader(TransportConstants.HEADER_CONTENT_TYPE, contentType);
233 }
234 if (!(format.isOptimized()) & format.isDoingSWA()) {
235 writeSwAMessage(outputStream, format);
236 }
237 else {
238 if (payloadCaching) {
239 axiomMessage.serialize(outputStream, format);
240 }
241 else {
242 axiomMessage.serializeAndConsume(outputStream, format);
243 }
244 }
245 outputStream.flush();
246 }
247 catch (XMLStreamException ex) {
248 throw new AxiomSoapMessageException("Could not write message to OutputStream: " + ex.getMessage(), ex);
249 }
250 catch (OMException ex) {
251 throw new AxiomSoapMessageException("Could not write message to OutputStream: " + ex.getMessage(), ex);
252 }
253 }
254
255 private void writeSwAMessage(OutputStream outputStream, OMOutputFormat format)
256 throws XMLStreamException, UnsupportedEncodingException {
257 StringWriter writer = new StringWriter();
258 SOAPEnvelope envelope = axiomMessage.getSOAPEnvelope();
259 if (payloadCaching) {
260 envelope.serialize(writer, format);
261 }
262 else {
263 envelope.serializeAndConsume(writer, format);
264 }
265 MIMEOutputUtils.writeSOAPWithAttachmentsMessage(writer, outputStream, attachments, format);
266 }
267
268 public String toString() {
269 StringBuffer buffer = new StringBuffer("AxiomSoapMessage");
270 if (payloadCaching) {
271 try {
272 SOAPEnvelope envelope = axiomMessage.getSOAPEnvelope();
273 if (envelope != null) {
274 SOAPBody body = envelope.getBody();
275 if (body != null) {
276 OMElement bodyElement = body.getFirstElement();
277 if (bodyElement != null) {
278 buffer.append(' ');
279 buffer.append(bodyElement.getQName());
280 }
281 }
282 }
283 }
284 catch (OMException ex) {
285
286 }
287 }
288 return buffer.toString();
289 }
290
291 private class AxiomAttachmentIterator implements Iterator {
292
293 private final Iterator iterator;
294
295 private AxiomAttachmentIterator() {
296 iterator = attachments.getContentIDSet().iterator();
297 }
298
299 public boolean hasNext() {
300 return iterator.hasNext();
301 }
302
303 public Object next() {
304 String contentId = (String) iterator.next();
305 DataHandler dataHandler = attachments.getDataHandler(contentId);
306 return new AxiomAttachment(contentId, dataHandler);
307 }
308
309 public void remove() {
310 iterator.remove();
311 }
312 }
313
314 }