View Javadoc

1   /*
2    * Copyright 2005-2010 the original author or authors.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package org.springframework.ws.soap.saaj;
18  
19  import java.io.IOException;
20  import java.io.OutputStream;
21  import java.util.ArrayList;
22  import java.util.Iterator;
23  import java.util.List;
24  import java.util.Locale;
25  import javax.activation.DataHandler;
26  import javax.xml.namespace.QName;
27  import javax.xml.soap.AttachmentPart;
28  import javax.xml.soap.Detail;
29  import javax.xml.soap.DetailEntry;
30  import javax.xml.soap.MimeHeader;
31  import javax.xml.soap.MimeHeaders;
32  import javax.xml.soap.Name;
33  import javax.xml.soap.SOAPBody;
34  import javax.xml.soap.SOAPElement;
35  import javax.xml.soap.SOAPEnvelope;
36  import javax.xml.soap.SOAPException;
37  import javax.xml.soap.SOAPFault;
38  import javax.xml.soap.SOAPHeader;
39  import javax.xml.soap.SOAPHeaderElement;
40  import javax.xml.soap.SOAPMessage;
41  import javax.xml.transform.Result;
42  import javax.xml.transform.Source;
43  import javax.xml.transform.sax.SAXResult;
44  import javax.xml.transform.sax.SAXSource;
45  
46  import org.springframework.util.ObjectUtils;
47  import org.springframework.util.StringUtils;
48  import org.springframework.ws.soap.SoapVersion;
49  import org.springframework.ws.soap.saaj.support.SaajContentHandler;
50  import org.springframework.ws.soap.saaj.support.SaajUtils;
51  import org.springframework.ws.soap.saaj.support.SaajXmlReader;
52  import org.springframework.ws.transport.TransportConstants;
53  import org.springframework.ws.transport.TransportOutputStream;
54  import org.springframework.xml.namespace.QNameUtils;
55  
56  import org.xml.sax.InputSource;
57  
58  /**
59   * SAAJ 1.1 specific implementation of the <code>SaajImplementation</code> interface.
60   *
61   * @author Arjen Poutsma
62   * @since 1.0.0
63   */
64  class Saaj11Implementation extends SaajImplementation {
65  
66      private static final Saaj11Implementation INSTANCE = new Saaj11Implementation();
67  
68      private Saaj11Implementation() {
69      }
70  
71      public static Saaj11Implementation getInstance() {
72          return INSTANCE;
73      }
74  
75      @Override
76      public QName getName(SOAPElement element) {
77          return SaajUtils.toQName(element.getElementName());
78      }
79  
80      @Override
81      public Source getSource(SOAPElement element) {
82          return new SAXSource(new SaajXmlReader(element), new InputSource());
83      }
84  
85      @Override
86      public Result getResult(SOAPElement element) {
87          return new SAXResult(new SaajContentHandler(element));
88      }
89  
90      @Override
91      public String getText(SOAPElement element) {
92          return element.getValue();
93      }
94  
95      @Override
96      public void setText(SOAPElement element, String content) throws SOAPException {
97          element.addTextNode(content);
98      }
99  
100     @Override
101     public void addAttribute(SOAPElement element, QName name, String value) throws SOAPException {
102         Name attributeName = SaajUtils.toName(name, element);
103         element.addAttribute(attributeName, value);
104     }
105 
106     @Override
107     public void removeAttribute(SOAPElement element, QName name) throws SOAPException {
108         Name attributeName = SaajUtils.toName(name, element);
109         element.removeAttribute(attributeName);
110     }
111 
112     @Override
113     public String getAttributeValue(SOAPElement element, QName name) throws SOAPException {
114         Name attributeName = SaajUtils.toName(name, element);
115         return element.getAttributeValue(attributeName);
116     }
117 
118     @Override
119     public Iterator<QName> getAllAttributes(SOAPElement element) {
120         List<QName> results = new ArrayList<QName>();
121         for (Iterator<?> iterator = element.getAllAttributes(); iterator.hasNext();) {
122             Name attributeName = (Name) iterator.next();
123             results.add(SaajUtils.toQName(attributeName));
124         }
125         return results.iterator();
126     }
127 
128     @Override
129     public QName getFaultCode(SOAPFault fault) {
130         String code = fault.getFaultCode();
131         int idx = code.indexOf(':');
132         if (idx != -1) {
133             String prefix = code.substring(0, idx);
134             String namespace = fault.getNamespaceURI(prefix);
135             if (StringUtils.hasLength(namespace)) {
136                 return QNameUtils.createQName(namespace, code.substring(idx + 1), prefix);
137             }
138         }
139         return new QName(code);
140     }
141 
142     public boolean isSoap11(SOAPElement element) {
143         return true;
144     }
145 
146     @Override
147     public DetailEntry addDetailEntry(Detail detail, QName name) throws SOAPException {
148         Name detailEntryName = SaajUtils.toName(name, detail);
149         return detail.addDetailEntry(detailEntryName);
150     }
151 
152     @Override
153     public SOAPHeaderElement addHeaderElement(SOAPHeader header, QName name) throws SOAPException {
154         Name saajName = SaajUtils.toName(name, header);
155         return header.addHeaderElement(saajName);
156     }
157 
158     @Override
159     public SOAPFault addFault(SOAPBody body, QName faultCode, String faultString, Locale locale) throws SOAPException {
160         SOAPFault fault = body.addFault();
161         if (StringUtils.hasLength(faultCode.getNamespaceURI()) &&
162                 StringUtils.hasLength(QNameUtils.getPrefix(faultCode))) {
163             fault.addNamespaceDeclaration(faultCode.getPrefix(), faultCode.getNamespaceURI());
164             fault.setFaultCode(faultCode.getPrefix() + ":" + faultCode.getLocalPart());
165         }
166         else if (faultCode.getNamespaceURI().equals(body.getElementName().getURI())) {
167             fault.setFaultCode(body.getElementName().getPrefix() + ":" + faultCode.getLocalPart());
168         }
169         else {
170             fault.setFaultCode(faultCode.getLocalPart());
171         }
172         fault.setFaultString(faultString);
173         return fault;
174     }
175 
176     /** Returns the envelope of the given message. */
177     @Override
178     public SOAPEnvelope getEnvelope(SOAPMessage message) throws SOAPException {
179         return message.getSOAPPart().getEnvelope();
180     }
181 
182     /** Returns the header of the given envelope. */
183     @Override
184     public SOAPHeader getHeader(SOAPEnvelope envelope) throws SOAPException {
185         return envelope.getHeader();
186     }
187 
188     /** Returns the body of the given envelope. */
189     @Override
190     public SOAPBody getBody(SOAPEnvelope envelope) throws SOAPException {
191         return envelope.getBody();
192     }
193 
194     /** Returns all header elements. */
195     @Override
196     @SuppressWarnings("unchecked")
197     public Iterator<SOAPHeaderElement> examineAllHeaderElements(SOAPHeader header) {
198         List<SOAPHeaderElement> result = new ArrayList<SOAPHeaderElement>();
199         for (Iterator<?> iterator = header.getChildElements(); iterator.hasNext();) {
200             Object o = iterator.next();
201             if (o instanceof SOAPHeaderElement) {
202                 result.add((SOAPHeaderElement) o);
203             }
204         }
205         return result.iterator();
206     }
207 
208     /** Returns all header elements for which the must understand attribute is true, given the actor or role. */
209     @Override
210     public Iterator<SOAPHeaderElement> examineMustUnderstandHeaderElements(SOAPHeader header, String actorOrRole) {
211         List<SOAPHeaderElement> result = new ArrayList<SOAPHeaderElement>();
212         for (Iterator<?> iterator = header.examineHeaderElements(actorOrRole); iterator.hasNext();) {
213             SOAPHeaderElement headerElement = (SOAPHeaderElement) iterator.next();
214             if (headerElement.getMustUnderstand()) {
215                 result.add(headerElement);
216             }
217         }
218         return result.iterator();
219     }
220 
221     /** Returns the SOAP 1.1 actor or SOAP 1.2 role attribute for the given header element. */
222     @Override
223     public String getActorOrRole(SOAPHeaderElement headerElement) {
224         return headerElement.getActor();
225     }
226 
227     /** Sets the SOAP 1.1 actor or SOAP 1.2 role attribute for the given header element. */
228     @Override
229     public void setActorOrRole(SOAPHeaderElement headerElement, String actorOrRole) {
230         headerElement.setActor(actorOrRole);
231     }
232 
233     /** Gets the must understand attribute for the given header element. */
234     @Override
235     public boolean getMustUnderstand(SOAPHeaderElement headerElement) {
236         return headerElement.getMustUnderstand();
237     }
238 
239     /** Sets the must understand attribute for the given header element. */
240     @Override
241     public void setMustUnderstand(SOAPHeaderElement headerElement, boolean mustUnderstand) {
242         headerElement.setMustUnderstand(mustUnderstand);
243     }
244 
245     /** Returns <code>true</code> if the body has a fault, <code>false</code> otherwise. */
246     @Override
247     public boolean hasFault(SOAPBody body) {
248         return body.hasFault();
249     }
250 
251     /** Returns the fault for the given body, if any. */
252     @Override
253     public SOAPFault getFault(SOAPBody body) {
254         return body.getFault();
255     }
256 
257     /** Returns the actor for the given fault. */
258     @Override
259     public String getFaultActor(SOAPFault fault) {
260         return fault.getFaultActor();
261     }
262 
263     /** Sets the actor for the given fault. */
264     @Override
265     public void setFaultActor(SOAPFault fault, String actorOrRole) throws SOAPException {
266         fault.setFaultActor(actorOrRole);
267     }
268 
269     /** Returns the fault string for the given fault. */
270     @Override
271     public String getFaultString(SOAPFault fault) {
272         return fault.getFaultString();
273     }
274 
275     /** Returns the fault string language for the given fault. */
276     @Override
277     public Locale getFaultStringLocale(SOAPFault fault) {
278         return Locale.ENGLISH;
279     }
280 
281     /** Returns the fault detail for the given fault. */
282     @Override
283     public Detail getFaultDetail(SOAPFault fault) {
284         return fault.getDetail();
285     }
286 
287     /** Adds a fault detail for the given fault. */
288     @Override
289     public Detail addFaultDetail(SOAPFault fault) throws SOAPException {
290         return fault.addDetail();
291     }
292 
293     @Override
294     public void addTextNode(DetailEntry detailEntry, String text) throws SOAPException {
295         detailEntry.addTextNode(text);
296     }
297 
298     /** Returns an iteration over all detail entries. */
299     @Override
300     @SuppressWarnings("unchecked")
301     public Iterator<DetailEntry> getDetailEntries(Detail detail) {
302         return detail.getDetailEntries();
303     }
304 
305     @Override
306     public SOAPElement getFirstBodyElement(SOAPBody body) {
307         for (Iterator<?> iterator = body.getChildElements(); iterator.hasNext();) {
308             Object child = iterator.next();
309             if (child instanceof SOAPElement) {
310                 return (SOAPElement) child;
311             }
312         }
313         return null;
314     }
315 
316     @Override
317     public void removeContents(SOAPElement element) {
318         for (Iterator<?> iterator = element.getChildElements(); iterator.hasNext();) {
319             iterator.next();
320             iterator.remove();
321         }
322     }
323 
324     @Override
325     @SuppressWarnings("unchecked")
326     Iterator<SOAPElement> getChildElements(SOAPElement element, QName name) throws SOAPException {
327         Name elementName = SaajUtils.toName(name, element);
328         return element.getChildElements(elementName);
329     }
330 
331     @Override
332     void addNamespaceDeclaration(SOAPElement element, String prefix, String namespaceUri) throws SOAPException {
333         element.addNamespaceDeclaration(prefix, namespaceUri);
334     }
335 
336     @Override
337     public void writeTo(SOAPMessage message, OutputStream outputStream) throws SOAPException, IOException {
338         if (message.saveRequired()) {
339             message.saveChanges();
340         }
341         if (outputStream instanceof TransportOutputStream) {
342             TransportOutputStream transportOutputStream = (TransportOutputStream) outputStream;
343             // some SAAJ implementations (Axis 1) do not have a Content-Type header by default
344             MimeHeaders headers = message.getMimeHeaders();
345             if (ObjectUtils.isEmpty(headers.getHeader(TransportConstants.HEADER_CONTENT_TYPE))) {
346                 headers.addHeader(TransportConstants.HEADER_CONTENT_TYPE, SoapVersion.SOAP_11.getContentType());
347                 if (message.saveRequired()) {
348                     message.saveChanges();
349                 }
350             }
351             for (Iterator<?> iterator = headers.getAllHeaders(); iterator.hasNext();) {
352                 MimeHeader mimeHeader = (MimeHeader) iterator.next();
353                 transportOutputStream.addHeader(mimeHeader.getName(), mimeHeader.getValue());
354             }
355         }
356         message.writeTo(outputStream);
357 
358     }
359 
360     @Override
361     public MimeHeaders getMimeHeaders(SOAPMessage message) {
362         return message.getMimeHeaders();
363     }
364 
365     @Override
366     @SuppressWarnings("unchecked")
367     public Iterator<AttachmentPart> getAttachments(SOAPMessage message) {
368         return message.getAttachments();
369     }
370 
371     @Override
372     @SuppressWarnings("unchecked")
373     public Iterator<AttachmentPart> getAttachment(SOAPMessage message, MimeHeaders mimeHeaders) {
374         return message.getAttachments(mimeHeaders);
375     }
376 
377     @Override
378     public AttachmentPart addAttachmentPart(SOAPMessage message, DataHandler dataHandler) {
379         AttachmentPart attachmentPart = message.createAttachmentPart(dataHandler);
380         message.addAttachmentPart(attachmentPart);
381         return attachmentPart;
382     }
383 
384     //
385     // Unsupported
386     //
387 
388     @Override
389     public String getFaultRole(SOAPFault fault) {
390         throw new UnsupportedOperationException("SAAJ 1.1 does not support SOAP 1.2");
391     }
392 
393     @Override
394     public void setFaultRole(SOAPFault fault, String role) {
395         throw new UnsupportedOperationException("SAAJ 1.1 does not support SOAP 1.2");
396     }
397 
398     @Override
399     public SOAPHeaderElement addNotUnderstoodHeaderElement(SOAPHeader header, QName name) {
400         throw new UnsupportedOperationException("SAAJ 1.1 does not support SOAP 1.2");
401     }
402 
403     @Override
404     public SOAPHeaderElement addUpgradeHeaderElement(SOAPHeader header, String[] supportedSoapUris) {
405         throw new UnsupportedOperationException("SAAJ 1.1 does not support SOAP 1.2");
406     }
407 
408     @Override
409     public Iterator<QName> getFaultSubcodes(SOAPFault fault) {
410         throw new UnsupportedOperationException("SAAJ 1.1 does not support SOAP 1.2");
411     }
412 
413     @Override
414     public void appendFaultSubcode(SOAPFault fault, QName subcode) {
415         throw new UnsupportedOperationException("SAAJ 1.1 does not support SOAP 1.2");
416     }
417 
418     @Override
419     public String getFaultNode(SOAPFault fault) {
420         throw new UnsupportedOperationException("SAAJ 1.1 does not support SOAP 1.2");
421     }
422 
423     @Override
424     public void setFaultNode(SOAPFault fault, String uri) {
425         throw new UnsupportedOperationException("SAAJ 1.1 does not support SOAP 1.2");
426     }
427 
428     @Override
429     public String getFaultReasonText(SOAPFault fault, Locale locale) {
430         throw new UnsupportedOperationException("SAAJ 1.1 does not support SOAP 1.2");
431     }
432 
433     @Override
434     public void setFaultReasonText(SOAPFault fault, Locale locale, String text) {
435         throw new UnsupportedOperationException("SAAJ 1.1 does not support SOAP 1.2");
436     }
437 
438 }