View Javadoc

1   /*
2    * Copyright 2007 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.xml.sax.InputSource;
47  
48  import org.springframework.util.ObjectUtils;
49  import org.springframework.util.StringUtils;
50  import org.springframework.ws.soap.SoapVersion;
51  import org.springframework.ws.soap.saaj.support.SaajContentHandler;
52  import org.springframework.ws.soap.saaj.support.SaajUtils;
53  import org.springframework.ws.soap.saaj.support.SaajXmlReader;
54  import org.springframework.ws.transport.TransportConstants;
55  import org.springframework.ws.transport.TransportOutputStream;
56  import org.springframework.xml.namespace.QNameUtils;
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      public QName getName(SOAPElement element) {
76          return SaajUtils.toQName(element.getElementName());
77      }
78  
79      public Source getSource(SOAPElement element) {
80          return new SAXSource(new SaajXmlReader(element), new InputSource());
81      }
82  
83      public Result getResult(SOAPElement element) {
84          return new SAXResult(new SaajContentHandler(element));
85      }
86  
87      public String getText(SOAPElement element) {
88          return element.getValue();
89      }
90  
91      public void setText(SOAPElement element, String content) throws SOAPException {
92          element.addTextNode(content);
93      }
94  
95      public void addAttribute(SOAPElement element, QName name, String value) throws SOAPException {
96          Name attributeName = SaajUtils.toName(name, element);
97          element.addAttribute(attributeName, value);
98      }
99  
100     public void removeAttribute(SOAPElement element, QName name) throws SOAPException {
101         Name attributeName = SaajUtils.toName(name, element);
102         element.removeAttribute(attributeName);
103     }
104 
105     public String getAttributeValue(SOAPElement element, QName name) throws SOAPException {
106         Name attributeName = SaajUtils.toName(name, element);
107         return element.getAttributeValue(attributeName);
108     }
109 
110     public Iterator getAllAttibutes(SOAPElement element) {
111         List results = new ArrayList();
112         for (Iterator iterator = element.getAllAttributes(); iterator.hasNext();) {
113             Name attributeName = (Name) iterator.next();
114             results.add(SaajUtils.toQName(attributeName));
115         }
116         return results.iterator();
117     }
118 
119     public QName getFaultCode(SOAPFault fault) {
120         String code = fault.getFaultCode();
121         int idx = code.indexOf(':');
122         if (idx != -1) {
123             String prefix = code.substring(0, idx);
124             String namespace = fault.getNamespaceURI(prefix);
125             if (StringUtils.hasLength(namespace)) {
126                 return QNameUtils.createQName(namespace, code.substring(idx + 1), prefix);
127             }
128         }
129         return new QName(code);
130     }
131 
132     public boolean isSoap11(SOAPElement element) {
133         return true;
134     }
135 
136     public DetailEntry addDetailEntry(Detail detail, QName name) throws SOAPException {
137         Name detailEntryName = SaajUtils.toName(name, detail);
138         return detail.addDetailEntry(detailEntryName);
139     }
140 
141     public SOAPHeaderElement addHeaderElement(SOAPHeader header, QName name) throws SOAPException {
142         Name saajName = SaajUtils.toName(name, header);
143         return header.addHeaderElement(saajName);
144     }
145 
146     public SOAPFault addFault(SOAPBody body, QName faultCode, String faultString, Locale locale) throws SOAPException {
147         SOAPFault fault = body.addFault();
148         if (StringUtils.hasLength(faultCode.getNamespaceURI()) &&
149                 StringUtils.hasLength(QNameUtils.getPrefix(faultCode))) {
150             fault.addNamespaceDeclaration(faultCode.getPrefix(), faultCode.getNamespaceURI());
151             fault.setFaultCode(faultCode.getPrefix() + ":" + faultCode.getLocalPart());
152         }
153         else if (faultCode.getNamespaceURI().equals(body.getElementName().getURI())) {
154             fault.setFaultCode(body.getElementName().getPrefix() + ":" + faultCode.getLocalPart());
155         }
156         else {
157             fault.setFaultCode(faultCode.getLocalPart());
158         }
159         fault.setFaultString(faultString);
160         return fault;
161     }
162 
163     /** Returns the envelope of the given message. */
164     public SOAPEnvelope getEnvelope(SOAPMessage message) throws SOAPException {
165         return message.getSOAPPart().getEnvelope();
166     }
167 
168     /** Returns the header of the given envelope. */
169     public SOAPHeader getHeader(SOAPEnvelope envelope) throws SOAPException {
170         return envelope.getHeader();
171     }
172 
173     /** Returns the body of the given envelope. */
174     public SOAPBody getBody(SOAPEnvelope envelope) throws SOAPException {
175         return envelope.getBody();
176     }
177 
178     /** Returns all header elements. */
179     public Iterator examineAllHeaderElements(SOAPHeader header) {
180         return header.getChildElements();
181     }
182 
183     /** Returns all header elements for which the must understand attribute is true, given the actor or role. */
184     public Iterator examineMustUnderstandHeaderElements(SOAPHeader header, String actorOrRole) {
185         List result = new ArrayList();
186         for (Iterator iterator = header.examineHeaderElements(actorOrRole); iterator.hasNext();) {
187             SOAPHeaderElement headerElement = (SOAPHeaderElement) iterator.next();
188             if (headerElement.getMustUnderstand()) {
189                 result.add(headerElement);
190             }
191         }
192         return result.iterator();
193     }
194 
195     /** Returns the SOAP 1.1 actor or SOAP 1.2 role attribute for the given header element. */
196     public String getActorOrRole(SOAPHeaderElement headerElement) {
197         return headerElement.getActor();
198     }
199 
200     /** Sets the SOAP 1.1 actor or SOAP 1.2 role attribute for the given header element. */
201     public void setActorOrRole(SOAPHeaderElement headerElement, String actorOrRole) {
202         headerElement.setActor(actorOrRole);
203     }
204 
205     /** Gets the must understand attribute for the given header element. */
206     public boolean getMustUnderstand(SOAPHeaderElement headerElement) {
207         return headerElement.getMustUnderstand();
208     }
209 
210     /** Sets the must understand attribute for the given header element. */
211     public void setMustUnderstand(SOAPHeaderElement headerElement, boolean mustUnderstand) {
212         headerElement.setMustUnderstand(mustUnderstand);
213     }
214 
215     /** Returns <code>true</code> if the body has a fault, <code>false</code> otherwise. */
216     public boolean hasFault(SOAPBody body) {
217         return body.hasFault();
218     }
219 
220     /** Returns the fault for the given body, if any. */
221     public SOAPFault getFault(SOAPBody body) {
222         return body.getFault();
223     }
224 
225     /** Returns the actor for the given fault. */
226     public String getFaultActor(SOAPFault fault) {
227         return fault.getFaultActor();
228     }
229 
230     /** Sets the actor for the given fault. */
231     public void setFaultActor(SOAPFault fault, String actorOrRole) throws SOAPException {
232         fault.setFaultActor(actorOrRole);
233     }
234 
235     /** Returns the fault string for the given fault. */
236     public String getFaultString(SOAPFault fault) {
237         return fault.getFaultString();
238     }
239 
240     /** Returns the fault string language for the given fault. */
241     public Locale getFaultStringLocale(SOAPFault fault) {
242         return Locale.ENGLISH;
243     }
244 
245     /** Returns the fault detail for the given fault. */
246     public Detail getFaultDetail(SOAPFault fault) {
247         return fault.getDetail();
248     }
249 
250     /** Adds a fault detail for the given fault. */
251     public Detail addFaultDetail(SOAPFault fault) throws SOAPException {
252         return fault.addDetail();
253     }
254 
255     public void addTextNode(DetailEntry detailEntry, String text) throws SOAPException {
256         detailEntry.addTextNode(text);
257     }
258 
259     /** Returns an iteration over all detail entries. */
260     public Iterator getDetailEntries(Detail detail) {
261         return detail.getDetailEntries();
262     }
263 
264     public SOAPElement getFirstBodyElement(SOAPBody body) {
265         for (Iterator iterator = body.getChildElements(); iterator.hasNext();) {
266             Object child = iterator.next();
267             if (child instanceof SOAPElement) {
268                 return (SOAPElement) child;
269             }
270         }
271         return null;
272     }
273 
274     public void removeContents(SOAPElement element) {
275         for (Iterator iterator = element.getChildElements(); iterator.hasNext();) {
276             iterator.next();
277             iterator.remove();
278         }
279     }
280 
281     Iterator getChildElements(SOAPElement element, QName name) throws SOAPException {
282         Name elementName = SaajUtils.toName(name, element);
283         return element.getChildElements(elementName);
284     }
285 
286     void addNamespaceDeclaration(SOAPElement element, String prefix, String namespaceUri) throws SOAPException {
287         element.addNamespaceDeclaration(prefix, namespaceUri);
288     }
289 
290     public void writeTo(SOAPMessage message, OutputStream outputStream) throws SOAPException, IOException {
291         if (message.saveRequired()) {
292             message.saveChanges();
293         }
294         if (outputStream instanceof TransportOutputStream) {
295             TransportOutputStream transportOutputStream = (TransportOutputStream) outputStream;
296             // some SAAJ implementations (Axis 1) do not have a Content-Type header by default
297             MimeHeaders headers = message.getMimeHeaders();
298             if (ObjectUtils.isEmpty(headers.getHeader(TransportConstants.HEADER_CONTENT_TYPE))) {
299                 headers.addHeader(TransportConstants.HEADER_CONTENT_TYPE, SoapVersion.SOAP_11.getContentType());
300                 if (message.saveRequired()) {
301                     message.saveChanges();
302                 }
303             }
304             for (Iterator iterator = headers.getAllHeaders(); iterator.hasNext();) {
305                 MimeHeader mimeHeader = (MimeHeader) iterator.next();
306                 transportOutputStream.addHeader(mimeHeader.getName(), mimeHeader.getValue());
307             }
308         }
309         message.writeTo(outputStream);
310 
311     }
312 
313     public MimeHeaders getMimeHeaders(SOAPMessage message) {
314         return message.getMimeHeaders();
315     }
316 
317     public Iterator getAttachments(SOAPMessage message) {
318         return message.getAttachments();
319     }
320 
321     public Iterator getAttachment(SOAPMessage message, MimeHeaders mimeHeaders) {
322         return message.getAttachments(mimeHeaders);
323     }
324 
325     public AttachmentPart addAttachmentPart(SOAPMessage message, DataHandler dataHandler) {
326         AttachmentPart attachmentPart = message.createAttachmentPart(dataHandler);
327         message.addAttachmentPart(attachmentPart);
328         return attachmentPart;
329     }
330 
331     //
332     // Unsupported
333     //
334 
335     public String getFaultRole(SOAPFault fault) {
336         throw new UnsupportedOperationException("SAAJ 1.1 does not support SOAP 1.2");
337     }
338 
339     public void setFaultRole(SOAPFault fault, String role) {
340         throw new UnsupportedOperationException("SAAJ 1.1 does not support SOAP 1.2");
341     }
342 
343     public SOAPHeaderElement addNotUnderstoodHeaderElement(SOAPHeader header, QName name) {
344         throw new UnsupportedOperationException("SAAJ 1.1 does not support SOAP 1.2");
345     }
346 
347     public SOAPHeaderElement addUpgradeHeaderElement(SOAPHeader header, String[] supportedSoapUris) {
348         throw new UnsupportedOperationException("SAAJ 1.1 does not support SOAP 1.2");
349     }
350 
351     public Iterator getFaultSubcodes(SOAPFault fault) {
352         throw new UnsupportedOperationException("SAAJ 1.1 does not support SOAP 1.2");
353     }
354 
355     public void appendFaultSubcode(SOAPFault fault, QName subcode) {
356         throw new UnsupportedOperationException("SAAJ 1.1 does not support SOAP 1.2");
357     }
358 
359     public String getFaultNode(SOAPFault fault) {
360         throw new UnsupportedOperationException("SAAJ 1.1 does not support SOAP 1.2");
361     }
362 
363     public void setFaultNode(SOAPFault fault, String uri) {
364         throw new UnsupportedOperationException("SAAJ 1.1 does not support SOAP 1.2");
365     }
366 
367     public String getFaultReasonText(SOAPFault fault, Locale locale) {
368         throw new UnsupportedOperationException("SAAJ 1.1 does not support SOAP 1.2");
369     }
370 
371     public void setFaultReasonText(SOAPFault fault, Locale locale, String text) {
372         throw new UnsupportedOperationException("SAAJ 1.1 does not support SOAP 1.2");
373     }
374 
375 }