KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > servicemix > soap > marshalers > SoapReader


1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements. See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License. You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */

17 package org.apache.servicemix.soap.marshalers;
18
19 import java.io.ByteArrayInputStream JavaDoc;
20 import java.io.InputStream JavaDoc;
21 import java.io.SequenceInputStream JavaDoc;
22 import java.net.URI JavaDoc;
23 import java.util.Properties JavaDoc;
24
25 import javax.mail.Session JavaDoc;
26 import javax.mail.internet.ContentType JavaDoc;
27 import javax.mail.internet.MimeBodyPart JavaDoc;
28 import javax.mail.internet.MimeMessage JavaDoc;
29 import javax.mail.internet.MimeMultipart JavaDoc;
30 import javax.xml.namespace.QName JavaDoc;
31 import javax.xml.parsers.DocumentBuilderFactory JavaDoc;
32 import javax.xml.stream.XMLStreamConstants;
33 import javax.xml.stream.XMLStreamReader;
34 import javax.xml.transform.Source JavaDoc;
35 import javax.xml.transform.dom.DOMSource JavaDoc;
36 import javax.xml.transform.stream.StreamSource JavaDoc;
37
38 import org.apache.servicemix.jbi.jaxp.ExtendedXMLStreamReader;
39 import org.apache.servicemix.jbi.jaxp.FragmentStreamReader;
40 import org.apache.servicemix.jbi.jaxp.StaxSource;
41 import org.apache.servicemix.jbi.jaxp.StringSource;
42 import org.apache.servicemix.jbi.util.DOMUtil;
43 import org.apache.servicemix.soap.SoapFault;
44 import org.w3c.dom.Document JavaDoc;
45 import org.w3c.dom.DocumentFragment JavaDoc;
46 import org.w3c.dom.Element JavaDoc;
47
48 /**
49  *
50  * @author Guillaume Nodet
51  * @version $Revision: 1.5 $
52  * @since 3.0
53  */

54 public class SoapReader {
55
56     private SoapMarshaler marshaler;
57   
58     protected static final Source JavaDoc EMPTY_CONTENT = new StringSource("<payload/>");
59
60     public SoapReader(SoapMarshaler marshaler) {
61         this.marshaler = marshaler;
62     }
63
64     public SoapMessage read(InputStream JavaDoc is, String JavaDoc contentType)
65             throws Exception JavaDoc {
66         if (contentType != null && contentType.toLowerCase().startsWith(SoapMarshaler.MULTIPART_CONTENT)) {
67             Session JavaDoc session = Session.getDefaultInstance(new Properties JavaDoc());
68             is = new SequenceInputStream JavaDoc(new ByteArrayInputStream JavaDoc(new byte[] { 13, 10 }), is);
69             MimeMessage JavaDoc mime = new MimeMessage JavaDoc(session, is);
70             mime.setHeader(SoapMarshaler.MIME_CONTENT_TYPE, contentType);
71             return read(mime);
72         } else {
73             return read(is);
74         }
75     }
76
77     public SoapMessage read(InputStream JavaDoc is) throws Exception JavaDoc {
78         if (marshaler.isSoap()) {
79             if (marshaler.isUseDom()) {
80                 return readSoapUsingDom(is);
81             } else {
82                 return readSoapUsingStax(is);
83             }
84         } else {
85             SoapMessage message = new SoapMessage();
86             message.setSource(new StreamSource JavaDoc(is));
87             return message;
88         }
89     }
90
91     private SoapMessage readSoapUsingDom(InputStream JavaDoc is) throws Exception JavaDoc {
92         SoapMessage message = new SoapMessage();
93         DocumentBuilderFactory JavaDoc factory = DocumentBuilderFactory.newInstance();
94         factory.setNamespaceAware(true);
95         Document JavaDoc doc = factory.newDocumentBuilder().parse(is);
96         message.setDocument(doc);
97         Element JavaDoc env = doc.getDocumentElement();
98         QName JavaDoc envName = DOMUtil.getQName(env);
99         if (!envName.getLocalPart().equals(SoapMarshaler.ENVELOPE)) {
100             throw new SoapFault(SoapFault.SENDER, "Unrecognized element: "
101                     + envName + ". Expecting 'Envelope'.");
102         }
103         message.setEnvelopeName(envName);
104         // Check soap 1.1 or 1.2
105
String JavaDoc soapUri = envName.getNamespaceURI();
106         if (!SoapMarshaler.SOAP_11_URI.equals(soapUri) && !SoapMarshaler.SOAP_12_URI.equals(soapUri)) {
107             throw new SoapFault(SoapFault.SENDER, "Unrecognized namespace: " + soapUri
108                     + " for element 'Envelope'.");
109         }
110         // Check Headers
111
Element JavaDoc child = DOMUtil.getFirstChildElement(env);
112         if (DOMUtil.getQName(child).equals(new QName JavaDoc(soapUri, SoapMarshaler.HEADER))) {
113             parseHeaders(message, child);
114             child = DOMUtil.getNextSiblingElement(child);
115         }
116         // Check Body
117
if (!DOMUtil.getQName(child).equals(new QName JavaDoc(soapUri, SoapMarshaler.BODY))) {
118             throw new SoapFault(SoapFault.SENDER, "Unrecognized element: "
119                     + DOMUtil.getQName(child) + ". Expecting 'Body'.");
120         }
121         // Create Source for content
122
child = DOMUtil.getFirstChildElement(child);
123         if (child != null) {
124             QName JavaDoc childName = DOMUtil.getQName(child);
125             message.setBodyName(childName);
126             // Check for fault
127
if (childName.equals(new QName JavaDoc(soapUri, SoapMarshaler.FAULT))) {
128                 message.setFault(readFaultUsingDom(child));
129             } else {
130                 message.setSource(new DOMSource JavaDoc(child));
131             }
132         }
133         child = DOMUtil.getNextSiblingElement(child);
134         if (child != null) {
135             throw new SoapFault(SoapFault.RECEIVER, "Body element has more than one child element.");
136         }
137         return message;
138     }
139     
140     private void parseHeaders(SoapMessage message, Element JavaDoc headers) {
141         for (Element JavaDoc child = DOMUtil.getFirstChildElement(headers);
142              child != null;
143              child = DOMUtil.getNextSiblingElement(child)) {
144             DocumentFragment JavaDoc df = child.getOwnerDocument().createDocumentFragment();
145             df.appendChild(child.cloneNode(true));
146             message.addHeader(DOMUtil.getQName(child), df);
147         }
148     }
149     
150     private SoapMessage readSoapUsingStax(InputStream JavaDoc is) throws Exception JavaDoc {
151         SoapMessage message = new SoapMessage();
152         XMLStreamReader reader = marshaler.getInputFactory().createXMLStreamReader(is);
153         reader = new ExtendedXMLStreamReader(reader);
154         reader.nextTag();
155         // Check Envelope tag
156
if (!reader.getLocalName().equals(SoapMarshaler.ENVELOPE)) {
157             throw new SoapFault(SoapFault.SENDER, "Unrecognized element: "
158                     + reader.getName() + " at ["
159                     + reader.getLocation().getLineNumber() + ","
160                     + reader.getLocation().getColumnNumber()
161                     + "]. Expecting 'Envelope'.");
162         }
163         message.setEnvelopeName(reader.getName());
164         // Check soap 1.1 or 1.2
165
String JavaDoc soapUri = reader.getNamespaceURI();
166         if (!SoapMarshaler.SOAP_11_URI.equals(soapUri) && !SoapMarshaler.SOAP_12_URI.equals(soapUri)) {
167             throw new SoapFault(SoapFault.SENDER, "Unrecognized namespace: " + soapUri
168                     + " for element 'Envelope' at ["
169                     + reader.getLocation().getLineNumber() + ","
170                     + reader.getLocation().getColumnNumber()
171                     + "]. Expecting 'Envelope'.");
172         }
173         // Check Headers
174
reader.nextTag();
175         if (reader.getName().equals(new QName JavaDoc(soapUri, SoapMarshaler.HEADER))) {
176             parseHeaders(message, reader);
177             reader.nextTag();
178         }
179         // Check Body
180
if (!reader.getName().equals(new QName JavaDoc(soapUri, SoapMarshaler.BODY))) {
181             throw new SoapFault(SoapFault.SENDER, "Unrecognized element: "
182                     + reader.getName() + " at ["
183                     + reader.getLocation().getLineNumber() + ","
184                     + reader.getLocation().getColumnNumber()
185                     + "]. Expecting 'Body'.");
186         }
187         // Create Source for content
188
if (reader.nextTag() != XMLStreamConstants.END_ELEMENT) {
189             QName JavaDoc childName = reader.getName();
190             message.setBodyName(childName);
191             // Check for fault
192
if (childName.equals(new QName JavaDoc(soapUri, SoapMarshaler.FAULT))) {
193                 message.setFault(readFaultUsingStax(reader));
194             } else {
195                 message.setSource(new StaxSource(new FragmentStreamReader(reader)));
196             }
197         }
198         return message;
199     }
200     
201     private SoapFault readFaultUsingDom(Element JavaDoc element) throws SoapFault {
202         QName JavaDoc code = null;
203         QName JavaDoc subcode = null;
204         String JavaDoc reason = null;
205         URI JavaDoc node = null;
206         URI JavaDoc role = null;
207         Source JavaDoc details = null;
208         // Parse soap 1.1 faults
209
if (element.getNamespaceURI().equals(SoapMarshaler.SOAP_11_URI)) {
210             // Fault code
211
Element JavaDoc child = DOMUtil.getFirstChildElement(element);
212             checkElementName(child, SoapMarshaler.SOAP_11_FAULTCODE);
213             code = DOMUtil.createQName(child, DOMUtil.getElementText(child));
214             // Fault string
215
child = DOMUtil.getNextSiblingElement(child);
216             checkElementName(child, SoapMarshaler.SOAP_11_FAULTSTRING);
217             reason = DOMUtil.getElementText(child);
218             child = DOMUtil.getNextSiblingElement(child);
219             QName JavaDoc childname = DOMUtil.getQName(child);
220             // Fault actor
221
if (SoapMarshaler.SOAP_11_FAULTACTOR.equals(childname)) {
222                 node = URI.create(DOMUtil.getElementText(child));
223                 child = DOMUtil.getNextSiblingElement(child);
224                 childname = DOMUtil.getQName(child);
225             }
226             // Fault details
227
if (SoapMarshaler.SOAP_11_FAULTDETAIL.equals(childname)) {
228                 Element JavaDoc subchild = DOMUtil.getFirstChildElement(child);
229                 if (subchild != null) {
230                     details = new DOMSource JavaDoc(subchild);
231                     subchild = DOMUtil.getNextSiblingElement(subchild);
232                     if (subchild != null) {
233                         throw new SoapFault(SoapFault.RECEIVER, "Multiple elements are not supported in Detail");
234                     }
235                 }
236                 child = DOMUtil.getNextSiblingElement(child);
237                 childname = DOMUtil.getQName(child);
238             }
239             // Nothing should be left
240
if (childname != null) {
241                 throw new SoapFault(SoapFault.SENDER, "Unexpected element: " + childname);
242             }
243         // Parse soap 1.2 faults
244
} else {
245             // Fault code
246
Element JavaDoc child = DOMUtil.getFirstChildElement(element);
247             checkElementName(child, SoapMarshaler.SOAP_12_FAULTCODE);
248             Element JavaDoc subchild = DOMUtil.getFirstChildElement(child);
249             checkElementName(subchild, SoapMarshaler.SOAP_12_FAULTVALUE);
250             code = DOMUtil.createQName(subchild, DOMUtil.getElementText(subchild));
251             if (!SoapMarshaler.SOAP_12_CODE_DATAENCODINGUNKNOWN.equals(code) &&
252                 !SoapMarshaler.SOAP_12_CODE_MUSTUNDERSTAND.equals(code) &&
253                 !SoapMarshaler.SOAP_12_CODE_RECEIVER.equals(code) &&
254                 !SoapMarshaler.SOAP_12_CODE_SENDER.equals(code) &&
255                 !SoapMarshaler.SOAP_12_CODE_VERSIONMISMATCH.equals(code)) {
256                 throw new SoapFault(SoapFault.SENDER, "Unexpected fault code: " + code);
257             }
258             subchild = DOMUtil.getNextSiblingElement(subchild);
259             if (subchild != null) {
260                 checkElementName(subchild, SoapMarshaler.SOAP_12_FAULTSUBCODE);
261                 Element JavaDoc subsubchild = DOMUtil.getFirstChildElement(subchild);
262                 checkElementName(subsubchild, SoapMarshaler.SOAP_12_FAULTVALUE);
263                 subcode = DOMUtil.createQName(subsubchild, DOMUtil.getElementText(subsubchild));
264                 subsubchild = DOMUtil.getNextSiblingElement(subsubchild);
265                 if (subsubchild != null) {
266                     checkElementName(subsubchild, SoapMarshaler.SOAP_12_FAULTSUBCODE);
267                     throw new SoapFault(SoapFault.RECEIVER, "Unsupported nested subcodes");
268                 }
269             }
270             // Fault reason
271
child = DOMUtil.getNextSiblingElement(child);
272             checkElementName(child, SoapMarshaler.SOAP_12_FAULTREASON);
273             subchild = DOMUtil.getFirstChildElement(child);
274             checkElementName(subchild, SoapMarshaler.SOAP_12_FAULTTEXT);
275             reason = DOMUtil.getElementText(subchild);
276             subchild = DOMUtil.getNextSiblingElement(subchild);
277             if (subchild != null) {
278                 throw new SoapFault(SoapFault.RECEIVER, "Unsupported multiple reasons");
279             }
280             // Fault node
281
child = DOMUtil.getNextSiblingElement(child);
282             QName JavaDoc childname = DOMUtil.getQName(child);
283             if (SoapMarshaler.SOAP_12_FAULTNODE.equals(childname)) {
284                 node = URI.create(DOMUtil.getElementText(child));
285                 child = DOMUtil.getNextSiblingElement(child);
286                 childname = DOMUtil.getQName(child);
287             }
288             // Fault role
289
if (SoapMarshaler.SOAP_12_FAULTROLE.equals(childname)) {
290                 role = URI.create(DOMUtil.getElementText(child));
291                 child = DOMUtil.getNextSiblingElement(child);
292                 childname = DOMUtil.getQName(child);
293             }
294             // Fault details
295
if (SoapMarshaler.SOAP_12_FAULTDETAIL.equals(childname)) {
296                 subchild = DOMUtil.getFirstChildElement(child);
297                 if (subchild != null) {
298                     details = new DOMSource JavaDoc(subchild);
299                     subchild = DOMUtil.getNextSiblingElement(subchild);
300                     if (subchild != null) {
301                         throw new SoapFault(SoapFault.RECEIVER, "Multiple elements are not supported in Detail");
302                     }
303                 }
304                 child = DOMUtil.getNextSiblingElement(child);
305                 childname = DOMUtil.getQName(child);
306             }
307             // Nothing should be left
308
if (childname != null) {
309                 throw new SoapFault(SoapFault.SENDER, "Unexpected element: " + childname);
310             }
311         }
312         SoapFault fault = new SoapFault(code, subcode, reason, node, role, details);
313         return fault;
314     }
315     
316     private SoapFault readFaultUsingStax(XMLStreamReader reader) throws SoapFault {
317         try {
318             FragmentStreamReader rh = new FragmentStreamReader(reader);
319             Document JavaDoc doc = (Document JavaDoc) marshaler.getSourceTransformer().toDOMNode(
320                     new StaxSource(rh));
321             return readFaultUsingDom(doc.getDocumentElement());
322         } catch (SoapFault e) {
323             throw e;
324         } catch (Exception JavaDoc e) {
325             throw new SoapFault(e);
326         }
327     }
328     
329     private void checkElementName(Element JavaDoc element, QName JavaDoc expected) throws SoapFault {
330         QName JavaDoc name= DOMUtil.getQName(element);
331         if (!expected.equals(name)) {
332             throw new SoapFault(SoapFault.SENDER, "Expected element: " + expected + " but found " + name);
333         }
334     }
335
336     private void parseHeaders(SoapMessage message, XMLStreamReader reader)
337             throws Exception JavaDoc {
338         while (reader.nextTag() != XMLStreamConstants.END_ELEMENT) {
339             QName JavaDoc hn = reader.getName();
340             FragmentStreamReader rh = new FragmentStreamReader(reader);
341             Document JavaDoc doc = (Document JavaDoc) marshaler.getSourceTransformer().toDOMNode(
342                     new StaxSource(rh));
343             DocumentFragment JavaDoc df = doc.createDocumentFragment();
344             df.appendChild(doc.getDocumentElement());
345             message.addHeader(hn, df);
346         }
347     }
348
349     public SoapMessage read(MimeMessage JavaDoc mime) throws Exception JavaDoc {
350         final Object JavaDoc content = mime.getContent();
351         if (content instanceof MimeMultipart JavaDoc) {
352             MimeMultipart JavaDoc multipart = (MimeMultipart JavaDoc) content;
353             ContentType JavaDoc type = new ContentType JavaDoc(mime.getContentType());
354             String JavaDoc contentId = type.getParameter("start");
355             // Get request
356
MimeBodyPart JavaDoc contentPart = null;
357             if (contentId != null) {
358                 contentPart = (MimeBodyPart JavaDoc) multipart.getBodyPart(contentId);
359             } else {
360                 for (int i = 0; i < multipart.getCount(); i++) {
361                   MimeBodyPart JavaDoc contentPart2 = (MimeBodyPart JavaDoc) multipart.getBodyPart(i);
362                   String JavaDoc contentType = contentPart2.getContentType();
363                   
364                   if (contentType.indexOf("xml") >= 0) {
365                     contentPart = contentPart2;
366                     break;
367                   }
368                 }
369             }
370             
371             SoapMessage message = null;
372             if (contentPart != null) {
373               message = read(contentPart.getInputStream());
374             } else {
375               message = new SoapMessage();
376               message.setSource(EMPTY_CONTENT);
377             }
378             
379             // Get attachments
380
for (int i = 0; i < multipart.getCount(); i++) {
381                 MimeBodyPart JavaDoc part = (MimeBodyPart JavaDoc) multipart.getBodyPart(i);
382                 if (part != contentPart) {
383                     String JavaDoc id = part.getContentID();
384                     if (id == null) {
385                         id = "Part" + i;
386                     } else if (id.startsWith("<")) {
387                         id = id.substring(1, id.length() - 1);
388                     }
389                     message.addAttachment(id, part.getDataHandler());
390                 }
391             }
392             return message;
393         } else {
394             throw new UnsupportedOperationException JavaDoc(
395                     "Expected a javax.mail.internet.MimeMultipart object");
396         }
397     }
398
399 }
400
Popular Tags