View Javadoc

1   /*
2    * Copyright 2002-2009 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.axiom.support;
18  
19  import java.io.ByteArrayInputStream;
20  import java.io.ByteArrayOutputStream;
21  import java.io.IOException;
22  import java.io.OutputStream;
23  import java.util.Iterator;
24  import java.util.Locale;
25  import javax.xml.namespace.QName;
26  import javax.xml.parsers.DocumentBuilderFactory;
27  import javax.xml.stream.XMLInputFactory;
28  
29  import org.apache.axiom.om.OMContainer;
30  import org.apache.axiom.om.OMElement;
31  import org.apache.axiom.om.OMException;
32  import org.apache.axiom.om.OMNamespace;
33  import org.apache.axiom.om.OMNode;
34  import org.apache.axiom.soap.SOAPEnvelope;
35  import org.apache.axiom.soap.impl.builder.StAXSOAPModelBuilder;
36  import org.w3c.dom.DOMImplementation;
37  import org.w3c.dom.Document;
38  import org.w3c.dom.Element;
39  import org.w3c.dom.ls.DOMImplementationLS;
40  import org.w3c.dom.ls.LSOutput;
41  import org.w3c.dom.ls.LSSerializer;
42  
43  import org.springframework.util.Assert;
44  import org.springframework.util.StringUtils;
45  import org.springframework.xml.namespace.QNameUtils;
46  
47  /**
48   * Collection of generic utility methods to work with Axiom. Includes conversion from <code>OMNamespace</code>s to
49   * <code>QName</code>s.
50   *
51   * @author Arjen Poutsma
52   * @author Tareq Abed Rabbo
53   * @see org.apache.axiom.om.OMNamespace
54   * @see javax.xml.namespace.QName
55   * @since 1.0.0
56   */
57  public abstract class AxiomUtils {
58  
59      /**
60       * Converts a <code>javax.xml.namespace.QName</code> to a <code>org.apache.axiom.om.OMNamespace</code>. A
61       * <code>OMElement</code> is used to resolve the namespace, or to declare a new one.
62       *
63       * @param qName          the <code>QName</code> to convert
64       * @param resolveElement the element used to resolve the Q
65       * @return the converted SAAJ Name
66       * @throws OMException              if conversion is unsuccessful
67       * @throws IllegalArgumentException if <code>qName</code> is not fully qualified
68       */
69      public static OMNamespace toNamespace(QName qName, OMElement resolveElement) throws OMException {
70          String prefix = QNameUtils.getPrefix(qName);
71          if (StringUtils.hasLength(qName.getNamespaceURI()) && StringUtils.hasLength(prefix)) {
72              return resolveElement.declareNamespace(qName.getNamespaceURI(), prefix);
73          }
74          else if (StringUtils.hasLength(qName.getNamespaceURI())) {
75              // check for existing namespace, and declare if necessary
76              return resolveElement.declareNamespace(qName.getNamespaceURI(), "");
77          }
78          else {
79              throw new IllegalArgumentException("qName [" + qName + "] does not contain a namespace");
80          }
81      }
82  
83      /**
84       * Converts the given locale to a <code>xml:lang</code> string, as used in Axiom Faults.
85       *
86       * @param locale the locale
87       * @return the language string
88       */
89      public static String toLanguage(Locale locale) {
90          return locale.toString().replace('_', '-');
91      }
92  
93      /**
94       * Converts the given locale to a <code>xml:lang</code> string, as used in Axiom Faults.
95       *
96       * @param language the language string
97       * @return the locale
98       */
99      public static Locale toLocale(String language) {
100         language = language.replace('-', '_');
101         return StringUtils.parseLocaleString(language);
102     }
103 
104     /** Removes the contents (i.e. children) of the container. */
105     public static void removeContents(OMContainer container) {
106         for (Iterator iterator = container.getChildren(); iterator.hasNext();) {
107             OMNode child = (OMNode) iterator.next();
108             child.detach();
109         }
110     }
111 
112     /**
113      * Converts a given AXIOM {@link org.apache.axiom.soap.SOAPEnvelope} to a {@link Document}.
114      *
115      * @param envelope the SOAP envelope to be converted
116      * @return the converted document
117      * @throws IllegalArgumentException in case of errors
118      * @see org.apache.rampart.util.Axis2Util.getDocumentFromSOAPEnvelope(SOAPEnvelope, boolean)
119      */
120     public static Document toDocument(SOAPEnvelope envelope) {
121         try {
122             if (envelope instanceof Element) {
123                 return ((Element) envelope).getOwnerDocument();
124             }
125             else {
126                 ByteArrayOutputStream bos = new ByteArrayOutputStream();
127                 envelope.build();
128                 envelope.serialize(bos);
129 
130                 ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
131                 DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
132                 documentBuilderFactory.setNamespaceAware(true);
133                 return documentBuilderFactory.newDocumentBuilder().parse(bis);
134             }
135         }
136         catch (Exception ex) {
137             IllegalArgumentException iaex =
138                     new IllegalArgumentException("Error in converting SOAP Envelope to Document");
139             iaex.initCause(ex);
140             throw iaex;
141         }
142     }
143 
144     /**
145      * Converts a given {@link Document} to an AXIOM {@link org.apache.axiom.soap.SOAPEnvelope}.
146      *
147      * @param document the document to be converted
148      * @return the converted envelope
149      * @throws IllegalArgumentException in case of errors
150      * @see org.apache.rampart.util.Axis2Util.getSOAPEnvelopeFromDOMDocument(Document, boolean)
151      */
152     public static SOAPEnvelope toEnvelope(Document document) {
153         try {
154             DOMImplementation implementation = document.getImplementation();
155             Assert.isInstanceOf(DOMImplementationLS.class, implementation);
156 
157             DOMImplementationLS loadSaveImplementation = (DOMImplementationLS) implementation;
158             LSOutput output = loadSaveImplementation.createLSOutput();
159             ByteArrayOutputStream bos = new ByteArrayOutputStream();
160             output.setByteStream(bos);
161 
162             LSSerializer serializer = loadSaveImplementation.createLSSerializer();
163             serializer.write(document, output);
164 
165             ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
166 
167             StAXSOAPModelBuilder stAXSOAPModelBuilder =
168                     new StAXSOAPModelBuilder(XMLInputFactory.newInstance().createXMLStreamReader(bis), null);
169             SOAPEnvelope envelope = stAXSOAPModelBuilder.getSOAPEnvelope();
170 
171             // Necessary to build a correct Axiom tree, see SWS-483
172             envelope.serialize(new NullOutputStream());
173 
174             return envelope;
175         }
176         catch (Exception ex) {
177             IllegalArgumentException iaex =
178                     new IllegalArgumentException("Error in converting Document to SOAP Envelope");
179             iaex.initCause(ex);
180             throw iaex;
181         }
182     }
183 
184     /** OutputStream that does nothing. */
185     private static class NullOutputStream extends OutputStream {
186 
187         public void write(int b) throws IOException {
188         }
189 
190         public void write(byte[] b) throws IOException {
191         }
192 
193         public void write(byte[] b, int off, int len) throws IOException {
194         }
195     }
196 
197 }