1 17 package org.apache.servicemix.soap.marshalers; 18 19 import java.io.ByteArrayInputStream ; 20 import java.io.InputStream ; 21 import java.io.SequenceInputStream ; 22 import java.net.URI ; 23 import java.util.Properties ; 24 25 import javax.mail.Session ; 26 import javax.mail.internet.ContentType ; 27 import javax.mail.internet.MimeBodyPart ; 28 import javax.mail.internet.MimeMessage ; 29 import javax.mail.internet.MimeMultipart ; 30 import javax.xml.namespace.QName ; 31 import javax.xml.parsers.DocumentBuilderFactory ; 32 import javax.xml.stream.XMLStreamConstants; 33 import javax.xml.stream.XMLStreamReader; 34 import javax.xml.transform.Source ; 35 import javax.xml.transform.dom.DOMSource ; 36 import javax.xml.transform.stream.StreamSource ; 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 ; 45 import org.w3c.dom.DocumentFragment ; 46 import org.w3c.dom.Element ; 47 48 54 public class SoapReader { 55 56 private SoapMarshaler marshaler; 57 58 protected static final Source EMPTY_CONTENT = new StringSource("<payload/>"); 59 60 public SoapReader(SoapMarshaler marshaler) { 61 this.marshaler = marshaler; 62 } 63 64 public SoapMessage read(InputStream is, String contentType) 65 throws Exception { 66 if (contentType != null && contentType.toLowerCase().startsWith(SoapMarshaler.MULTIPART_CONTENT)) { 67 Session session = Session.getDefaultInstance(new Properties ()); 68 is = new SequenceInputStream (new ByteArrayInputStream (new byte[] { 13, 10 }), is); 69 MimeMessage mime = new MimeMessage (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 is) throws Exception { 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 (is)); 87 return message; 88 } 89 } 90 91 private SoapMessage readSoapUsingDom(InputStream is) throws Exception { 92 SoapMessage message = new SoapMessage(); 93 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 94 factory.setNamespaceAware(true); 95 Document doc = factory.newDocumentBuilder().parse(is); 96 message.setDocument(doc); 97 Element env = doc.getDocumentElement(); 98 QName 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 String 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 Element child = DOMUtil.getFirstChildElement(env); 112 if (DOMUtil.getQName(child).equals(new QName (soapUri, SoapMarshaler.HEADER))) { 113 parseHeaders(message, child); 114 child = DOMUtil.getNextSiblingElement(child); 115 } 116 if (!DOMUtil.getQName(child).equals(new QName (soapUri, SoapMarshaler.BODY))) { 118 throw new SoapFault(SoapFault.SENDER, "Unrecognized element: " 119 + DOMUtil.getQName(child) + ". Expecting 'Body'."); 120 } 121 child = DOMUtil.getFirstChildElement(child); 123 if (child != null) { 124 QName childName = DOMUtil.getQName(child); 125 message.setBodyName(childName); 126 if (childName.equals(new QName (soapUri, SoapMarshaler.FAULT))) { 128 message.setFault(readFaultUsingDom(child)); 129 } else { 130 message.setSource(new DOMSource (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 headers) { 141 for (Element child = DOMUtil.getFirstChildElement(headers); 142 child != null; 143 child = DOMUtil.getNextSiblingElement(child)) { 144 DocumentFragment 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 is) throws Exception { 151 SoapMessage message = new SoapMessage(); 152 XMLStreamReader reader = marshaler.getInputFactory().createXMLStreamReader(is); 153 reader = new ExtendedXMLStreamReader(reader); 154 reader.nextTag(); 155 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 String 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 reader.nextTag(); 175 if (reader.getName().equals(new QName (soapUri, SoapMarshaler.HEADER))) { 176 parseHeaders(message, reader); 177 reader.nextTag(); 178 } 179 if (!reader.getName().equals(new QName (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 if (reader.nextTag() != XMLStreamConstants.END_ELEMENT) { 189 QName childName = reader.getName(); 190 message.setBodyName(childName); 191 if (childName.equals(new QName (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 element) throws SoapFault { 202 QName code = null; 203 QName subcode = null; 204 String reason = null; 205 URI node = null; 206 URI role = null; 207 Source details = null; 208 if (element.getNamespaceURI().equals(SoapMarshaler.SOAP_11_URI)) { 210 Element child = DOMUtil.getFirstChildElement(element); 212 checkElementName(child, SoapMarshaler.SOAP_11_FAULTCODE); 213 code = DOMUtil.createQName(child, DOMUtil.getElementText(child)); 214 child = DOMUtil.getNextSiblingElement(child); 216 checkElementName(child, SoapMarshaler.SOAP_11_FAULTSTRING); 217 reason = DOMUtil.getElementText(child); 218 child = DOMUtil.getNextSiblingElement(child); 219 QName childname = DOMUtil.getQName(child); 220 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 if (SoapMarshaler.SOAP_11_FAULTDETAIL.equals(childname)) { 228 Element subchild = DOMUtil.getFirstChildElement(child); 229 if (subchild != null) { 230 details = new DOMSource (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 if (childname != null) { 241 throw new SoapFault(SoapFault.SENDER, "Unexpected element: " + childname); 242 } 243 } else { 245 Element child = DOMUtil.getFirstChildElement(element); 247 checkElementName(child, SoapMarshaler.SOAP_12_FAULTCODE); 248 Element 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 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 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 child = DOMUtil.getNextSiblingElement(child); 282 QName 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 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 if (SoapMarshaler.SOAP_12_FAULTDETAIL.equals(childname)) { 296 subchild = DOMUtil.getFirstChildElement(child); 297 if (subchild != null) { 298 details = new DOMSource (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 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 doc = (Document ) marshaler.getSourceTransformer().toDOMNode( 320 new StaxSource(rh)); 321 return readFaultUsingDom(doc.getDocumentElement()); 322 } catch (SoapFault e) { 323 throw e; 324 } catch (Exception e) { 325 throw new SoapFault(e); 326 } 327 } 328 329 private void checkElementName(Element element, QName expected) throws SoapFault { 330 QName 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 { 338 while (reader.nextTag() != XMLStreamConstants.END_ELEMENT) { 339 QName hn = reader.getName(); 340 FragmentStreamReader rh = new FragmentStreamReader(reader); 341 Document doc = (Document ) marshaler.getSourceTransformer().toDOMNode( 342 new StaxSource(rh)); 343 DocumentFragment df = doc.createDocumentFragment(); 344 df.appendChild(doc.getDocumentElement()); 345 message.addHeader(hn, df); 346 } 347 } 348 349 public SoapMessage read(MimeMessage mime) throws Exception { 350 final Object content = mime.getContent(); 351 if (content instanceof MimeMultipart ) { 352 MimeMultipart multipart = (MimeMultipart ) content; 353 ContentType type = new ContentType (mime.getContentType()); 354 String contentId = type.getParameter("start"); 355 MimeBodyPart contentPart = null; 357 if (contentId != null) { 358 contentPart = (MimeBodyPart ) multipart.getBodyPart(contentId); 359 } else { 360 for (int i = 0; i < multipart.getCount(); i++) { 361 MimeBodyPart contentPart2 = (MimeBodyPart ) multipart.getBodyPart(i); 362 String 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 for (int i = 0; i < multipart.getCount(); i++) { 381 MimeBodyPart part = (MimeBodyPart ) multipart.getBodyPart(i); 382 if (part != contentPart) { 383 String 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 ( 395 "Expected a javax.mail.internet.MimeMultipart object"); 396 } 397 } 398 399 } 400 | Popular Tags |