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 private final boolean langAttributeOnSoap11FaultString;
75
76 private OMOutputFormat outputFormat;
77
78
79
80
81
82
83 public AxiomSoapMessage(SOAPFactory soapFactory) {
84 this(soapFactory, true, true);
85 }
86
87
88
89
90
91
92 public AxiomSoapMessage(SOAPFactory soapFactory, boolean payloadCaching, boolean langAttributeOnSoap11FaultString) {
93 SOAPEnvelope soapEnvelope = soapFactory.getDefaultEnvelope();
94 axiomFactory = soapFactory;
95 axiomMessage = axiomFactory.createSOAPMessage(soapEnvelope, soapEnvelope.getBuilder());
96 attachments = new Attachments();
97 this.payloadCaching = payloadCaching;
98 this.langAttributeOnSoap11FaultString = langAttributeOnSoap11FaultString;
99 soapAction = EMPTY_SOAP_ACTION;
100 }
101
102
103
104
105
106
107
108
109 public AxiomSoapMessage(SOAPMessage soapMessage,
110 String soapAction,
111 boolean payloadCaching,
112 boolean langAttributeOnSoap11FaultString) {
113 this(soapMessage, new Attachments(), soapAction, payloadCaching, langAttributeOnSoap11FaultString);
114 }
115
116
117
118
119
120
121
122
123
124 public AxiomSoapMessage(SOAPMessage soapMessage,
125 Attachments attachments,
126 String soapAction,
127 boolean payloadCaching,
128 boolean langAttributeOnSoap11FaultString) {
129 Assert.notNull(soapMessage, "'soapMessage' must not be null");
130 Assert.notNull(attachments, "'attachments' must not be null");
131 axiomMessage = soapMessage;
132 axiomFactory = (SOAPFactory) soapMessage.getSOAPEnvelope().getOMFactory();
133 this.attachments = attachments;
134 if (!StringUtils.hasLength(soapAction)) {
135 soapAction = EMPTY_SOAP_ACTION;
136 }
137 this.soapAction = soapAction;
138 this.payloadCaching = payloadCaching;
139 this.langAttributeOnSoap11FaultString = langAttributeOnSoap11FaultString;
140 }
141
142
143 public final SOAPMessage getAxiomMessage() {
144 return axiomMessage;
145 }
146
147
148
149
150
151
152 public final void setAxiomMessage(SOAPMessage axiomMessage) {
153 Assert.notNull(axiomMessage, "'axiomMessage' must not be null");
154 this.axiomMessage = axiomMessage;
155 this.envelope = null;
156 this.soapAction = EMPTY_SOAP_ACTION;
157 }
158
159
160
161
162
163
164 public void setOutputFormat(OMOutputFormat outputFormat) {
165 this.outputFormat = outputFormat;
166 }
167
168 public SoapEnvelope getEnvelope() {
169 if (envelope == null) {
170 try {
171 envelope = new AxiomSoapEnvelope(axiomMessage.getSOAPEnvelope(), axiomFactory, payloadCaching,
172 langAttributeOnSoap11FaultString);
173 }
174 catch (SOAPProcessingException ex) {
175 throw new AxiomSoapEnvelopeException(ex);
176 }
177 }
178 return envelope;
179 }
180
181 public String getSoapAction() {
182 return soapAction;
183 }
184
185 public void setSoapAction(String soapAction) {
186 soapAction = SoapUtils.escapeAction(soapAction);
187 this.soapAction = soapAction;
188 }
189
190 public boolean isXopPackage() {
191 try {
192 return MTOMConstants.MTOM_TYPE.equals(attachments.getAttachmentSpecType());
193 }
194 catch (NullPointerException ex) {
195
196 return false;
197 }
198 }
199
200 public boolean convertToXopPackage() {
201 return false;
202 }
203
204 public Attachment getAttachment(String contentId) {
205 Assert.hasLength(contentId, "contentId must not be empty");
206 if (contentId.startsWith("<") && contentId.endsWith(">")) {
207 contentId = contentId.substring(1, contentId.length() - 1);
208 }
209 DataHandler dataHandler = attachments.getDataHandler(contentId);
210 return dataHandler != null ? new AxiomAttachment(contentId, dataHandler) : null;
211 }
212
213 public Iterator getAttachments() {
214 return new AxiomAttachmentIterator();
215 }
216
217 public Attachment addAttachment(String contentId, DataHandler dataHandler) {
218 Assert.hasLength(contentId, "contentId must not be empty");
219 Assert.notNull(dataHandler, "dataHandler must not be null");
220 attachments.addDataHandler(contentId, dataHandler);
221 return new AxiomAttachment(contentId, dataHandler);
222 }
223
224 public void writeTo(OutputStream outputStream) throws IOException {
225 try {
226
227 OMOutputFormat outputFormat = getOutputFormat();
228 if (outputStream instanceof TransportOutputStream) {
229 TransportOutputStream transportOutputStream = (TransportOutputStream) outputStream;
230 String contentType = outputFormat.getContentType();
231 if (!(outputFormat.isDoingSWA() || outputFormat.isOptimized())) {
232 String charsetEncoding = axiomMessage.getCharsetEncoding();
233 contentType += "; charset=" + charsetEncoding;
234 }
235 SoapVersion version = getVersion();
236 if (SoapVersion.SOAP_11 == version) {
237 transportOutputStream.addHeader(TransportConstants.HEADER_SOAP_ACTION, soapAction);
238 transportOutputStream.addHeader(TransportConstants.HEADER_ACCEPT, version.getContentType());
239 }
240 else if (SoapVersion.SOAP_12 == version) {
241 contentType += "; action=" + soapAction;
242 transportOutputStream.addHeader(TransportConstants.HEADER_ACCEPT, version.getContentType());
243 }
244 transportOutputStream.addHeader(TransportConstants.HEADER_CONTENT_TYPE, contentType);
245
246 }
247 if (!(outputFormat.isOptimized()) & outputFormat.isDoingSWA()) {
248 writeSwAMessage(outputStream, outputFormat);
249 }
250 else {
251 if (payloadCaching) {
252 axiomMessage.serialize(outputStream, outputFormat);
253 }
254 else {
255 axiomMessage.serializeAndConsume(outputStream, outputFormat);
256 }
257 }
258 outputStream.flush();
259 }
260 catch (XMLStreamException ex) {
261 throw new AxiomSoapMessageException("Could not write message to OutputStream: " + ex.getMessage(), ex);
262 }
263 catch (OMException ex) {
264 throw new AxiomSoapMessageException("Could not write message to OutputStream: " + ex.getMessage(), ex);
265 }
266 }
267
268 private OMOutputFormat getOutputFormat() {
269 if (outputFormat != null) {
270 return outputFormat;
271 }
272 else {
273 String charsetEncoding = axiomMessage.getCharsetEncoding();
274
275 OMOutputFormat outputFormat = new OMOutputFormat();
276 outputFormat.setCharSetEncoding(charsetEncoding);
277 outputFormat.setSOAP11(getVersion() == SoapVersion.SOAP_11);
278 if (isXopPackage()) {
279 outputFormat.setDoOptimize(true);
280 }
281 else if (!attachments.getContentIDSet().isEmpty()) {
282 outputFormat.setDoingSWA(true);
283 }
284 return outputFormat;
285 }
286 }
287
288 private void writeSwAMessage(OutputStream outputStream, OMOutputFormat format)
289 throws XMLStreamException, UnsupportedEncodingException {
290 StringWriter writer = new StringWriter();
291 SOAPEnvelope envelope = axiomMessage.getSOAPEnvelope();
292 if (payloadCaching) {
293 envelope.serialize(writer, format);
294 }
295 else {
296 envelope.serializeAndConsume(writer, format);
297 }
298 MIMEOutputUtils.writeSOAPWithAttachmentsMessage(writer, outputStream, attachments, format);
299 }
300
301 public String toString() {
302 StringBuffer buffer = new StringBuffer("AxiomSoapMessage");
303 if (payloadCaching) {
304 try {
305 SOAPEnvelope envelope = axiomMessage.getSOAPEnvelope();
306 if (envelope != null) {
307 SOAPBody body = envelope.getBody();
308 if (body != null) {
309 OMElement bodyElement = body.getFirstElement();
310 if (bodyElement != null) {
311 buffer.append(' ');
312 buffer.append(bodyElement.getQName());
313 }
314 }
315 }
316 }
317 catch (OMException ex) {
318
319 }
320 }
321 return buffer.toString();
322 }
323
324 private class AxiomAttachmentIterator implements Iterator {
325
326 private final Iterator iterator;
327
328 private AxiomAttachmentIterator() {
329 iterator = attachments.getContentIDSet().iterator();
330 }
331
332 public boolean hasNext() {
333 return iterator.hasNext();
334 }
335
336 public Object next() {
337 String contentId = (String) iterator.next();
338 DataHandler dataHandler = attachments.getDataHandler(contentId);
339 return new AxiomAttachment(contentId, dataHandler);
340 }
341
342 public void remove() {
343 iterator.remove();
344 }
345 }
346
347 }