1 /* 2 * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package com.sun.xml.internal.messaging.saaj.soap; 27 28 import java.io.*; 29 import java.util.*; 30 import java.util.logging.Level; 31 import java.util.logging.Logger; 32 33 import javax.activation.DataHandler; 34 import javax.activation.DataSource; 35 import javax.xml.soap.*; 36 import javax.xml.stream.XMLStreamReader; 37 import javax.xml.transform.Source; 38 import javax.xml.transform.stax.StAXSource; 39 import javax.xml.transform.stream.StreamSource; 40 41 import com.sun.xml.internal.messaging.saaj.packaging.mime.Header; 42 import com.sun.xml.internal.messaging.saaj.packaging.mime.internet.*; 43 import com.sun.xml.internal.messaging.saaj.packaging.mime.util.*; 44 import com.sun.xml.internal.messaging.saaj.packaging.mime.MessagingException; 45 46 import com.sun.xml.internal.messaging.saaj.SOAPExceptionImpl; 47 import com.sun.xml.internal.messaging.saaj.soap.impl.EnvelopeImpl; 48 import com.sun.xml.internal.messaging.saaj.util.*; 49 import com.sun.xml.internal.org.jvnet.mimepull.MIMEPart; 50 51 /** 52 * The message implementation for SOAP messages with 53 * attachments. Messages for specific profiles will likely extend this 54 * MessageImpl class and add more value for that particular profile. 55 * 56 * @author Anil Vijendran (akv@eng.sun.com) 57 * @author Rajiv Mordani (rajiv.mordani@sun.com) 58 * @author Manveen Kaur (manveen.kaur@sun.com) 59 */ 60 61 public abstract class MessageImpl 62 extends SOAPMessage 63 implements SOAPConstants { 64 65 66 public static final String CONTENT_ID = "Content-ID"; 67 public static final String CONTENT_LOCATION = "Content-Location"; 68 69 protected static final Logger log = 70 Logger.getLogger(LogDomainConstants.SOAP_DOMAIN, 71 "com.sun.xml.internal.messaging.saaj.soap.LocalStrings"); 72 73 protected static final int PLAIN_XML_FLAG = 1; // 00001 74 protected static final int MIME_MULTIPART_FLAG = 2; // 00010 75 protected static final int SOAP1_1_FLAG = 4; // 00100 76 protected static final int SOAP1_2_FLAG = 8; // 01000 77 //protected static final int MIME_MULTIPART_XOP_FLAG = 14; // 01110 78 protected static final int MIME_MULTIPART_XOP_SOAP1_1_FLAG = 6; // 00110 79 protected static final int MIME_MULTIPART_XOP_SOAP1_2_FLAG = 10; // 01010 80 protected static final int XOP_FLAG = 13; // 01101 81 protected static final int FI_ENCODED_FLAG = 16; // 10000 82 83 protected MimeHeaders headers; 84 protected ContentType contentType; 85 protected SOAPPartImpl soapPartImpl; 86 protected FinalArrayList<AttachmentPart> attachments; 87 protected boolean saved = false; 88 protected byte[] messageBytes; 89 protected int messageByteCount; 90 protected Map<String, Object> properties = new HashMap<>(); 91 92 // used for lazy attachment initialization 93 protected MimeMultipart multiPart = null; 94 protected boolean attachmentsInitialized = false; 95 96 /** 97 * True if this part is encoded using Fast Infoset. 98 * MIME -> application/fastinfoset 99 */ 100 protected boolean isFastInfoset = false; 101 102 /** 103 * True if the Accept header of this message includes 104 * application/fastinfoset 105 */ 106 protected boolean acceptFastInfoset = false; 107 108 protected MimeMultipart mmp = null; 109 110 // if attachments are present, don't read the entire message in byte stream in saveTo() 111 private boolean optimizeAttachmentProcessing = true; 112 113 private InputStream inputStreamAfterSaveChanges = null; 114 115 public static final String LAZY_SOAP_BODY_PARSING = "saaj.lazy.soap.body"; 116 117 // switch back to old MimeMultipart incase of problem 118 private static boolean switchOffBM = false; 119 private static boolean switchOffLazyAttachment = false; 120 private static boolean useMimePull = false; 121 122 static { 123 String s = SAAJUtil.getSystemProperty("saaj.mime.optimization"); 124 if ((s != null) && s.equals("false")) { 125 switchOffBM = true; 126 } 127 s = SAAJUtil.getSystemProperty("saaj.lazy.mime.optimization"); 128 if ((s != null) && s.equals("false")) { 129 switchOffLazyAttachment = true; 130 } 131 useMimePull = SAAJUtil.getSystemBoolean("saaj.use.mimepull"); 132 133 } 134 135 //property to indicate optimized serialization for lazy attachments 136 private boolean lazyAttachments = false; 137 138 // most of the times, Content-Types are already all lower cased. 139 // String.toLowerCase() works faster in this case, so even if you 140 // are only doing one comparison, it pays off to use String.toLowerCase() 141 // than String.equalsIgnoreCase(). When you do more than one comparison, 142 // the benefits of String.toLowerCase() dominates. 143 // 144 // 145 // for FI, 146 // use application/fastinfoset for SOAP 1.1 147 // use application/soap+fastinfoset for SOAP 1.2 148 // to speed up comparisons, test methods always use lower cases. 149 150 /** 151 * @param primary 152 * must be all lower case 153 * @param sub 154 * must be all lower case 155 */ 156 private static boolean isSoap1_1Type(String primary, String sub) { 157 return primary.equalsIgnoreCase("text") && sub.equalsIgnoreCase("xml") 158 || primary.equalsIgnoreCase("text") && sub.equalsIgnoreCase("xml-soap") 159 || primary.equals("application") 160 && sub.equals("fastinfoset"); 161 } 162 163 /** 164 * @param type 165 * must be all lower case 166 */ 167 private static boolean isEqualToSoap1_1Type(String type) { 168 return type.startsWith("text/xml") || 169 type.startsWith("application/fastinfoset"); 170 } 171 172 /** 173 * @param primary 174 * must be all lower case 175 * @param sub 176 * must be all lower case 177 */ 178 private static boolean isSoap1_2Type(String primary, String sub) { 179 return primary.equals("application") 180 && (sub.equals("soap+xml") 181 || sub.equals("soap+fastinfoset")); 182 } 183 184 /** 185 * @param type 186 * must be all lower case 187 */ 188 private static boolean isEqualToSoap1_2Type(String type) { 189 return type.startsWith("application/soap+xml") || 190 type.startsWith("application/soap+fastinfoset"); 191 } 192 193 /** 194 * Construct a new message. This will be invoked before message 195 * sends. 196 */ 197 protected MessageImpl() { 198 this(false, false); 199 attachmentsInitialized = true; 200 } 201 202 /** 203 * Construct a new message. This will be invoked before message 204 * sends. 205 * 206 * @param isFastInfoset whether it is fast infoset 207 * @param acceptFastInfoset whether to accept fast infoset 208 */ 209 protected MessageImpl(boolean isFastInfoset, boolean acceptFastInfoset) { 210 this.isFastInfoset = isFastInfoset; 211 this.acceptFastInfoset = acceptFastInfoset; 212 213 headers = new MimeHeaders(); 214 headers.setHeader("Accept", getExpectedAcceptHeader()); 215 contentType = new ContentType(); 216 } 217 218 /** 219 * Shallow copy. 220 * 221 * @param msg SoapMessage 222 */ 223 protected MessageImpl(SOAPMessage msg) { 224 if (!(msg instanceof MessageImpl)) { 225 // don't know how to handle this. 226 } 227 MessageImpl src = (MessageImpl) msg; 228 this.headers = src.headers; 229 this.soapPartImpl = src.soapPartImpl; 230 this.attachments = src.attachments; 231 this.saved = src.saved; 232 this.messageBytes = src.messageBytes; 233 this.messageByteCount = src.messageByteCount; 234 this.properties = src.properties; 235 this.contentType = src.contentType; 236 } 237 238 /** 239 * @param stat 240 * the mask value obtained from {@link #identifyContentType(ContentType)} 241 * @return true if SOAP 1.1 Content 242 */ 243 protected static boolean isSoap1_1Content(int stat) { 244 return (stat & SOAP1_1_FLAG) != 0; 245 } 246 247 /** 248 * Check whether it is SOAP 1.2 content. 249 * @param stat 250 * the mask value obtained from {@link #identifyContentType(ContentType)} 251 * @return true if it is SOAP 1.2 content 252 */ 253 protected static boolean isSoap1_2Content(int stat) { 254 return (stat & SOAP1_2_FLAG) != 0; 255 } 256 257 private static boolean isMimeMultipartXOPSoap1_2Package(ContentType contentType) { 258 String type = contentType.getParameter("type"); 259 if (type == null) { 260 return false; 261 } 262 type = type.toLowerCase(); 263 if (!type.startsWith("application/xop+xml")) { 264 return false; 265 } 266 String startinfo = contentType.getParameter("start-info"); 267 if (startinfo == null) { 268 return false; 269 } 270 startinfo = startinfo.toLowerCase(); 271 return isEqualToSoap1_2Type(startinfo); 272 } 273 274 275 //private static boolean isMimeMultipartXOPPackage(ContentType contentType) { 276 private static boolean isMimeMultipartXOPSoap1_1Package(ContentType contentType) { 277 String type = contentType.getParameter("type"); 278 if(type==null) 279 return false; 280 281 type = type.toLowerCase(); 282 if(!type.startsWith("application/xop+xml")) 283 return false; 284 285 String startinfo = contentType.getParameter("start-info"); 286 if(startinfo == null) 287 return false; 288 startinfo = startinfo.toLowerCase(); 289 return isEqualToSoap1_1Type(startinfo); 290 } 291 292 private static boolean isSOAPBodyXOPPackage(ContentType contentType){ 293 String primary = contentType.getPrimaryType(); 294 String sub = contentType.getSubType(); 295 296 if (primary.equalsIgnoreCase("application")) { 297 if (sub.equalsIgnoreCase("xop+xml")) { 298 String type = getTypeParameter(contentType); 299 return isEqualToSoap1_2Type(type) || isEqualToSoap1_1Type(type); 300 } 301 } 302 return false; 303 } 304 305 /** 306 * Construct a message from an input stream. When messages are 307 * received, there's two parts -- the transport headers and the 308 * message content in a transport specific stream. 309 * @param headers MimeHeaders 310 * @param in InputStream 311 * @exception SOAPExceptionImpl in case of I/O error 312 */ 313 protected MessageImpl(MimeHeaders headers, final InputStream in) 314 throws SOAPExceptionImpl { 315 contentType = parseContentType(headers); 316 init(headers,identifyContentType(contentType),contentType,in); 317 } 318 319 private static ContentType parseContentType(MimeHeaders headers) throws SOAPExceptionImpl { 320 final String ct; 321 if (headers != null) 322 ct = getContentType(headers); 323 else { 324 log.severe("SAAJ0550.soap.null.headers"); 325 throw new SOAPExceptionImpl("Cannot create message: " + 326 "Headers can't be null"); 327 } 328 329 if (ct == null) { 330 log.severe("SAAJ0532.soap.no.Content-Type"); 331 throw new SOAPExceptionImpl("Absent Content-Type"); 332 } 333 try { 334 return new ContentType(ct); 335 } catch (Throwable ex) { 336 log.severe("SAAJ0535.soap.cannot.internalize.message"); 337 throw new SOAPExceptionImpl("Unable to internalize message", ex); 338 } 339 } 340 341 /** 342 * Construct a message from an input stream. When messages are 343 * received, there's two parts -- the transport headers and the 344 * message content in a transport specific stream. 345 * 346 * @param headers headers 347 * @param contentType 348 * The parsed content type header from the headers variable. 349 * This is redundant parameter, but it avoids reparsing this header again. 350 * @param stat 351 * The result of {@link #identifyContentType(ContentType)} over 352 * the contentType parameter. This redundant parameter, but it avoids 353 * recomputing this information again. 354 * @param in input stream 355 * @exception SOAPExceptionImpl in case of an error 356 */ 357 protected MessageImpl(MimeHeaders headers, final ContentType contentType, int stat, final InputStream in) throws SOAPExceptionImpl { 358 init(headers, stat, contentType, in); 359 360 } 361 362 public MessageImpl(MimeHeaders headers, ContentType ct, int stat, 363 XMLStreamReader reader) throws SOAPExceptionImpl { 364 init(headers, stat, ct, reader); 365 } 366 367 private void init(MimeHeaders headers, int stat, final ContentType contentType, final Object input) throws SOAPExceptionImpl { 368 this.headers = headers; 369 370 try { 371 372 // Set isFastInfoset/acceptFastInfoset flag based on MIME type 373 if ((stat & FI_ENCODED_FLAG) > 0) { 374 isFastInfoset = acceptFastInfoset = true; 375 } 376 377 // If necessary, inspect Accept header to set acceptFastInfoset 378 if (!isFastInfoset) { 379 String[] values = headers.getHeader("Accept"); 380 if (values != null) { 381 for (int i = 0; i < values.length; i++) { 382 StringTokenizer st = new StringTokenizer(values[i], ","); 383 while (st.hasMoreTokens()) { 384 final String token = st.nextToken().trim(); 385 if (token.equalsIgnoreCase("application/fastinfoset") || 386 token.equalsIgnoreCase("application/soap+fastinfoset")) { 387 acceptFastInfoset = true; 388 break; 389 } 390 } 391 } 392 } 393 } 394 395 if (!isCorrectSoapVersion(stat)) { 396 log.log( 397 Level.SEVERE, 398 "SAAJ0533.soap.incorrect.Content-Type", 399 new String[] { 400 contentType.toString(), 401 getExpectedContentType()}); 402 throw new SOAPVersionMismatchException( 403 "Cannot create message: incorrect content-type for SOAP version. Got: " 404 + contentType 405 + " Expected: " 406 + getExpectedContentType()); 407 } 408 InputStream in = null; 409 XMLStreamReader rdr = null; 410 if (input instanceof InputStream) { 411 in = (InputStream) input; 412 } else { 413 //is a StAX reader 414 rdr = (XMLStreamReader) input; 415 } 416 if ((stat & PLAIN_XML_FLAG) != 0) { 417 if (in != null) { 418 if (isFastInfoset) { 419 getSOAPPart().setContent( 420 FastInfosetReflection.FastInfosetSource_new(in)); 421 } else { 422 initCharsetProperty(contentType); 423 getSOAPPart().setContent(new StreamSource(in)); 424 } 425 } else { 426 //is a StAX reader 427 if (isFastInfoset) { 428 //need to get FI stax reader 429 } else { 430 initCharsetProperty(contentType); 431 getSOAPPart().setContent(new StAXSource(rdr)); 432 } 433 } 434 } 435 else if ((stat & MIME_MULTIPART_FLAG) != 0 && in == null) { 436 //only parse multipart in the inputstream case 437 //in stax reader case, we would be given the attachments separately 438 getSOAPPart().setContent(new StAXSource(rdr)); 439 } else if ((stat & MIME_MULTIPART_FLAG) != 0) { 440 final InputStream finalIn = in; 441 DataSource ds = new DataSource() { 442 @Override 443 public InputStream getInputStream() { 444 return finalIn; 445 } 446 447 @Override 448 public OutputStream getOutputStream() { 449 return null; 450 } 451 452 @Override 453 public String getContentType() { 454 return contentType.toString(); 455 } 456 457 @Override 458 public String getName() { 459 return ""; 460 } 461 }; 462 463 multiPart = null; 464 if (useMimePull) { 465 multiPart = new MimePullMultipart(ds,contentType); 466 } else if (switchOffBM) { 467 multiPart = new MimeMultipart(ds,contentType); 468 } else { 469 multiPart = new BMMimeMultipart(ds,contentType); 470 } 471 472 String startParam = contentType.getParameter("start"); 473 MimeBodyPart soapMessagePart = null; 474 InputStream soapPartInputStream = null; 475 String contentID = null; 476 String contentIDNoAngle = null; 477 if (switchOffBM || switchOffLazyAttachment) { 478 if(startParam == null) { 479 soapMessagePart = multiPart.getBodyPart(0); 480 for (int i = 1; i < multiPart.getCount(); i++) { 481 initializeAttachment(multiPart, i); 482 } 483 } else { 484 soapMessagePart = multiPart.getBodyPart(startParam); 485 for (int i = 0; i < multiPart.getCount(); i++) { 486 contentID = multiPart.getBodyPart(i).getContentID(); 487 // Old versions of AXIS2 put angle brackets around the content 488 // id but not the start param 489 contentIDNoAngle = (contentID != null) ? 490 contentID.replaceFirst("^<", "").replaceFirst(">$", "") : null; 491 if(!startParam.equals(contentID) && !startParam.equals(contentIDNoAngle)) 492 initializeAttachment(multiPart, i); 493 } 494 } 495 } else { 496 if (useMimePull) { 497 MimePullMultipart mpMultipart = (MimePullMultipart)multiPart; 498 MIMEPart sp = mpMultipart.readAndReturnSOAPPart(); 499 soapMessagePart = new MimeBodyPart(sp); 500 soapPartInputStream = sp.readOnce(); 501 } else { 502 BMMimeMultipart bmMultipart = 503 (BMMimeMultipart) multiPart; 504 InputStream stream = bmMultipart.initStream(); 505 506 SharedInputStream sin = null; 507 if (stream instanceof SharedInputStream) { 508 sin = (SharedInputStream) stream; 509 } 510 511 String boundary = "--" + 512 contentType.getParameter("boundary"); 513 byte[] bndbytes = ASCIIUtility.getBytes(boundary); 514 if (startParam == null) { 515 soapMessagePart = 516 bmMultipart.getNextPart(stream, bndbytes, sin); 517 bmMultipart.removeBodyPart(soapMessagePart); 518 } else { 519 MimeBodyPart bp = null; 520 try { 521 while (!startParam.equals(contentID) && !startParam.equals(contentIDNoAngle)) { 522 bp = bmMultipart.getNextPart( 523 stream, bndbytes, sin); 524 contentID = bp.getContentID(); 525 // Old versions of AXIS2 put angle brackets around the content 526 // id but not the start param 527 contentIDNoAngle = (contentID != null) ? 528 contentID.replaceFirst("^<", "").replaceFirst(">$", "") : null; 529 } 530 soapMessagePart = bp; 531 bmMultipart.removeBodyPart(bp); 532 } catch (Exception e) { 533 throw new SOAPExceptionImpl(e); 534 } 535 } 536 } 537 } 538 539 // findbugs correctly points out that we'd NPE instantiating 540 // the ContentType (just below here) if soapMessagePart were 541 // null. Hence are better off throwing a controlled exception 542 // at this point if it is null. 543 if (soapMessagePart == null) { 544 log.severe("SAAJ0510.soap.cannot.create.envelope"); 545 throw new SOAPExceptionImpl( 546 "Unable to create envelope from given source: SOAP part not found"); 547 } 548 549 if (soapPartInputStream == null) { 550 soapPartInputStream = soapMessagePart.getInputStream(); 551 } 552 553 ContentType soapPartCType = new ContentType( 554 soapMessagePart.getContentType()); 555 initCharsetProperty(soapPartCType); 556 String baseType = soapPartCType.getBaseType().toLowerCase(); 557 if(!(isEqualToSoap1_1Type(baseType) 558 || isEqualToSoap1_2Type(baseType) 559 || isSOAPBodyXOPPackage(soapPartCType))) { 560 log.log(Level.SEVERE, 561 "SAAJ0549.soap.part.invalid.Content-Type", 562 new Object[] {baseType}); 563 throw new SOAPExceptionImpl( 564 "Bad Content-Type for SOAP Part : " + 565 baseType); 566 } 567 568 SOAPPart soapPart = getSOAPPart(); 569 setMimeHeaders(soapPart, soapMessagePart); 570 soapPart.setContent(isFastInfoset ? 571 (Source) FastInfosetReflection.FastInfosetSource_new( 572 soapPartInputStream) : 573 (Source) new StreamSource(soapPartInputStream)); 574 } else { 575 log.severe("SAAJ0534.soap.unknown.Content-Type"); 576 throw new SOAPExceptionImpl("Unrecognized Content-Type"); 577 } 578 } catch (Throwable ex) { 579 log.severe("SAAJ0535.soap.cannot.internalize.message"); 580 throw new SOAPExceptionImpl("Unable to internalize message", ex); 581 } 582 needsSave(); 583 } 584 585 public boolean isFastInfoset() { 586 return isFastInfoset; 587 } 588 589 public boolean acceptFastInfoset() { 590 return acceptFastInfoset; 591 } 592 593 public void setIsFastInfoset(boolean value) { 594 if (value != isFastInfoset) { 595 isFastInfoset = value; 596 if (isFastInfoset) { 597 acceptFastInfoset = true; 598 } 599 saved = false; // ensure transcoding if necessary 600 } 601 } 602 603 public boolean isLazySoapBodyParsing() { 604 Object lazyParsingProp = getProperty(LAZY_SOAP_BODY_PARSING); 605 if (lazyParsingProp == null) return false; 606 if (lazyParsingProp instanceof Boolean) { 607 return ((Boolean) lazyParsingProp).booleanValue(); 608 } else { 609 return Boolean.valueOf(lazyParsingProp.toString()); 610 } 611 } 612 @Override 613 public Object getProperty(String property) { 614 return properties.get(property); 615 } 616 617 @Override 618 public void setProperty(String property, Object value) { 619 verify(property, value); 620 properties.put(property, value); 621 } 622 623 private void verify(String property, Object value) { 624 if (property.equalsIgnoreCase(SOAPMessage.WRITE_XML_DECLARATION)) { 625 if (!("true".equals(value) || "false".equals(value))) 626 throw new RuntimeException( 627 property + " must have value false or true"); 628 629 try { 630 EnvelopeImpl env = (EnvelopeImpl) getSOAPPart().getEnvelope(); 631 if ("true".equalsIgnoreCase((String)value)) { 632 env.setOmitXmlDecl("no"); 633 } else if ("false".equalsIgnoreCase((String)value)) { 634 env.setOmitXmlDecl("yes"); 635 } 636 } catch (Exception e) { 637 log.log(Level.SEVERE, "SAAJ0591.soap.exception.in.set.property", 638 new Object[] {e.getMessage(), "javax.xml.soap.write-xml-declaration"}); 639 throw new RuntimeException(e); 640 } 641 return; 642 } 643 644 if (property.equalsIgnoreCase(SOAPMessage.CHARACTER_SET_ENCODING)) { 645 try { 646 ((EnvelopeImpl) getSOAPPart().getEnvelope()).setCharsetEncoding((String)value); 647 } catch (Exception e) { 648 log.log(Level.SEVERE, "SAAJ0591.soap.exception.in.set.property", 649 new Object[] {e.getMessage(), "javax.xml.soap.character-set-encoding"}); 650 throw new RuntimeException(e); 651 } 652 } 653 } 654 655 protected abstract boolean isCorrectSoapVersion(int contentTypeId); 656 657 protected abstract String getExpectedContentType(); 658 protected abstract String getExpectedAcceptHeader(); 659 660 /** 661 * Sniffs the Content-Type header so that we can determine how to process. 662 * 663 * <p> 664 * In the absence of type attribute we assume it to be text/xml. 665 * That would mean we're easy on accepting the message and 666 * generate the correct thing (as the SWA spec also specifies 667 * that the type parameter should always be text/xml) 668 * 669 * @return 670 * combination of flags, such as PLAIN_XML_CODE and MIME_MULTIPART_CODE. 671 */ 672 // SOAP1.2 allow SOAP1.2 content type 673 static int identifyContentType(ContentType ct) 674 throws SOAPExceptionImpl { 675 // TBD 676 // Is there anything else we need to verify here? 677 678 String primary = ct.getPrimaryType().toLowerCase(); 679 String sub = ct.getSubType().toLowerCase(); 680 681 if (primary.equals("multipart")) { 682 if (sub.equals("related")) { 683 String type = getTypeParameter(ct); 684 if (isEqualToSoap1_1Type(type)) { 685 return (type.equals("application/fastinfoset") ? 686 FI_ENCODED_FLAG : 0) | MIME_MULTIPART_FLAG | SOAP1_1_FLAG; 687 } 688 else if (isEqualToSoap1_2Type(type)) { 689 return (type.equals("application/soap+fastinfoset") ? 690 FI_ENCODED_FLAG : 0) | MIME_MULTIPART_FLAG | SOAP1_2_FLAG; 691 /*} else if (isMimeMultipartXOPPackage(ct)) { 692 return MIME_MULTIPART_XOP_FLAG;*/ 693 } else if (isMimeMultipartXOPSoap1_1Package(ct)) { 694 return MIME_MULTIPART_XOP_SOAP1_1_FLAG; 695 } else if (isMimeMultipartXOPSoap1_2Package(ct)) { 696 return MIME_MULTIPART_XOP_SOAP1_2_FLAG; 697 } else { 698 log.severe("SAAJ0536.soap.content-type.mustbe.multipart"); 699 throw new SOAPExceptionImpl( 700 "Content-Type needs to be Multipart/Related " 701 + "and with \"type=text/xml\" " 702 + "or \"type=application/soap+xml\""); 703 } 704 } else { 705 log.severe("SAAJ0537.soap.invalid.content-type"); 706 throw new SOAPExceptionImpl( 707 "Invalid Content-Type: " + primary + '/' + sub); 708 } 709 } 710 else if (isSoap1_1Type(primary, sub)) { 711 return (primary.equalsIgnoreCase("application") 712 && sub.equalsIgnoreCase("fastinfoset") ? 713 FI_ENCODED_FLAG : 0) 714 | PLAIN_XML_FLAG | SOAP1_1_FLAG; 715 } 716 else if (isSoap1_2Type(primary, sub)) { 717 return (primary.equalsIgnoreCase("application") 718 && sub.equalsIgnoreCase("soap+fastinfoset") ? 719 FI_ENCODED_FLAG : 0) 720 | PLAIN_XML_FLAG | SOAP1_2_FLAG; 721 } else if(isSOAPBodyXOPPackage(ct)){ 722 return XOP_FLAG; 723 } else { 724 log.severe("SAAJ0537.soap.invalid.content-type"); 725 throw new SOAPExceptionImpl( 726 "Invalid Content-Type:" 727 + primary 728 + '/' 729 + sub 730 + ". Is this an error message instead of a SOAP response?"); 731 } 732 } 733 734 /** 735 * Obtains the type parameter of the Content-Type header. Defaults to "text/xml". 736 */ 737 private static String getTypeParameter(ContentType contentType) { 738 String p = contentType.getParameter("type"); 739 if(p!=null) 740 return p.toLowerCase(); 741 else 742 return "text/xml"; 743 } 744 745 @Override 746 public MimeHeaders getMimeHeaders() { 747 return this.headers; 748 } 749 750 final static String getContentType(MimeHeaders headers) { 751 String[] values = headers.getHeader("Content-Type"); 752 if (values == null) 753 return null; 754 else 755 return values[0]; 756 } 757 758 /* 759 * Get the complete ContentType value along with optional parameters. 760 */ 761 public String getContentType() { 762 return getContentType(this.headers); 763 } 764 765 public void setContentType(String type) { 766 headers.setHeader("Content-Type", type); 767 needsSave(); 768 } 769 770 private ContentType contentType() { 771 ContentType ct = null; 772 try { 773 String currentContent = getContentType(); 774 if (currentContent == null) { 775 return this.contentType; 776 } 777 ct = new ContentType(currentContent); 778 } catch (Exception e) { 779 // what to do here? 780 } 781 return ct; 782 } 783 784 /* 785 * Return the MIME type string, without the parameters. 786 */ 787 public String getBaseType() { 788 return contentType().getBaseType(); 789 } 790 791 public void setBaseType(String type) { 792 ContentType ct = contentType(); 793 ct.setParameter("type", type); 794 headers.setHeader("Content-Type", ct.toString()); 795 needsSave(); 796 } 797 798 public String getAction() { 799 return contentType().getParameter("action"); 800 } 801 802 public void setAction(String action) { 803 ContentType ct = contentType(); 804 ct.setParameter("action", action); 805 headers.setHeader("Content-Type", ct.toString()); 806 needsSave(); 807 } 808 809 public String getCharset() { 810 return contentType().getParameter("charset"); 811 } 812 813 public void setCharset(String charset) { 814 ContentType ct = contentType(); 815 ct.setParameter("charset", charset); 816 headers.setHeader("Content-Type", ct.toString()); 817 needsSave(); 818 } 819 820 /** 821 * All write methods (i.e setters) should call this method in 822 * order to make sure that a save is necessary since the state 823 * has been modified. 824 */ 825 private final void needsSave() { 826 saved = false; 827 } 828 829 @Override 830 public boolean saveRequired() { 831 return saved != true; 832 } 833 834 @Override 835 public String getContentDescription() { 836 String[] values = headers.getHeader("Content-Description"); 837 if (values != null && values.length > 0) 838 return values[0]; 839 return null; 840 } 841 842 @Override 843 public void setContentDescription(String description) { 844 headers.setHeader("Content-Description", description); 845 needsSave(); 846 } 847 848 @Override 849 public abstract SOAPPart getSOAPPart(); 850 851 @Override 852 public void removeAllAttachments() { 853 try { 854 initializeAllAttachments(); 855 } catch (Exception e) { 856 throw new RuntimeException(e); 857 } 858 859 if (attachments != null) { 860 attachments.clear(); 861 needsSave(); 862 } 863 } 864 865 @Override 866 public int countAttachments() { 867 try { 868 initializeAllAttachments(); 869 } catch (Exception e) { 870 throw new RuntimeException(e); 871 } 872 if (attachments != null) 873 return attachments.size(); 874 return 0; 875 } 876 877 @Override 878 public void addAttachmentPart(AttachmentPart attachment) { 879 try { 880 initializeAllAttachments(); 881 this.optimizeAttachmentProcessing = true; 882 } catch (Exception e) { 883 throw new RuntimeException(e); 884 } 885 if (attachments == null) 886 attachments = new FinalArrayList<>(); 887 888 attachments.add(attachment); 889 890 needsSave(); 891 } 892 893 static private final Iterator<AttachmentPart> nullIter = Collections.<AttachmentPart>EMPTY_LIST.iterator(); 894 895 @Override 896 public Iterator<AttachmentPart> getAttachments() { 897 try { 898 initializeAllAttachments(); 899 } catch (Exception e) { 900 throw new RuntimeException(e); 901 } 902 if (attachments == null) 903 return nullIter; 904 return attachments.iterator(); 905 } 906 907 private void setFinalContentType(String charset) { 908 ContentType ct = contentType(); 909 if (ct == null) { 910 ct = new ContentType(); 911 } 912 String[] split = getExpectedContentType().split("/"); 913 ct.setPrimaryType(split[0]); 914 ct.setSubType(split[1]); 915 ct.setParameter("charset", charset); 916 headers.setHeader("Content-Type", ct.toString()); 917 } 918 919 private class MimeMatchingIterator implements Iterator<AttachmentPart> { 920 public MimeMatchingIterator(MimeHeaders headers) { 921 this.headers = headers; 922 this.iter = attachments.iterator(); 923 } 924 925 private Iterator<AttachmentPart> iter; 926 private MimeHeaders headers; 927 private AttachmentPart nextAttachment; 928 929 @Override 930 public boolean hasNext() { 931 if (nextAttachment == null) 932 nextAttachment = nextMatch(); 933 return nextAttachment != null; 934 } 935 936 @Override 937 public AttachmentPart next() { 938 if (nextAttachment != null) { 939 AttachmentPart ret = nextAttachment; 940 nextAttachment = null; 941 return ret; 942 } 943 944 if (hasNext()) 945 return nextAttachment; 946 947 return null; 948 } 949 950 AttachmentPart nextMatch() { 951 while (iter.hasNext()) { 952 AttachmentPartImpl ap = (AttachmentPartImpl) iter.next(); 953 if (ap.hasAllHeaders(headers)) 954 return ap; 955 } 956 return null; 957 } 958 959 @Override 960 public void remove() { 961 iter.remove(); 962 } 963 } 964 965 @Override 966 public Iterator<AttachmentPart> getAttachments(MimeHeaders headers) { 967 try { 968 initializeAllAttachments(); 969 } catch (Exception e) { 970 throw new RuntimeException(e); 971 } 972 if (attachments == null) 973 return nullIter; 974 975 return new MimeMatchingIterator(headers); 976 } 977 978 @Override 979 public void removeAttachments(MimeHeaders headers) { 980 try { 981 initializeAllAttachments(); 982 } catch (Exception e) { 983 throw new RuntimeException(e); 984 } 985 if (attachments == null) 986 return ; 987 988 Iterator<AttachmentPart> it = new MimeMatchingIterator(headers); 989 while (it.hasNext()) { 990 int index = attachments.indexOf(it.next()); 991 attachments.set(index, null); 992 } 993 FinalArrayList<AttachmentPart> f = new FinalArrayList<AttachmentPart>(); 994 for (int i = 0; i < attachments.size(); i++) { 995 if (attachments.get(i) != null) { 996 f.add(attachments.get(i)); 997 } 998 } 999 attachments = f; 1000 // needsSave(); 1001 } 1002 1003 @Override 1004 public AttachmentPart createAttachmentPart() { 1005 return new AttachmentPartImpl(); 1006 } 1007 1008 @Override 1009 public AttachmentPart getAttachment(SOAPElement element) 1010 throws SOAPException { 1011 try { 1012 initializeAllAttachments(); 1013 } catch (Exception e) { 1014 throw new RuntimeException(e); 1015 } 1016 String uri; 1017 String hrefAttr = element.getAttribute("href"); 1018 if ("".equals(hrefAttr)) { 1019 Node node = getValueNodeStrict(element); 1020 String swaRef = null; 1021 if (node != null) { 1022 swaRef = node.getValue(); 1023 } 1024 if (swaRef == null || "".equals(swaRef)) { 1025 return null; 1026 } else { 1027 uri = swaRef; 1028 } 1029 } else { 1030 uri = hrefAttr; 1031 } 1032 return getAttachmentPart(uri); 1033 } 1034 1035 private Node getValueNodeStrict(SOAPElement element) { 1036 Node node = (Node)element.getFirstChild(); 1037 if (node != null) { 1038 if (node.getNextSibling() == null 1039 && node.getNodeType() == org.w3c.dom.Node.TEXT_NODE) { 1040 return node; 1041 } else { 1042 return null; 1043 } 1044 } 1045 return null; 1046 } 1047 1048 1049 private AttachmentPart getAttachmentPart(String uri) throws SOAPException { 1050 AttachmentPart _part; 1051 try { 1052 if (uri.startsWith("cid:")) { 1053 // rfc2392 1054 uri = '<'+uri.substring("cid:".length())+'>'; 1055 1056 MimeHeaders headersToMatch = new MimeHeaders(); 1057 headersToMatch.addHeader(CONTENT_ID, uri); 1058 1059 Iterator i = this.getAttachments(headersToMatch); 1060 _part = (i == null) ? null : (AttachmentPart)i.next(); 1061 } else { 1062 // try content-location 1063 MimeHeaders headersToMatch = new MimeHeaders(); 1064 headersToMatch.addHeader(CONTENT_LOCATION, uri); 1065 1066 Iterator i = this.getAttachments(headersToMatch); 1067 _part = (i == null) ? null : (AttachmentPart)i.next(); 1068 } 1069 1070 // try auto-generated JAXRPC CID 1071 if (_part == null) { 1072 Iterator j = this.getAttachments(); 1073 1074 while (j.hasNext()) { 1075 AttachmentPart p = (AttachmentPart)j.next(); 1076 String cl = p.getContentId(); 1077 if (cl != null) { 1078 // obtain the partname 1079 int eqIndex = cl.indexOf("="); 1080 if (eqIndex > -1) { 1081 cl = cl.substring(1, eqIndex); 1082 if (cl.equalsIgnoreCase(uri)) { 1083 _part = p; 1084 break; 1085 } 1086 } 1087 } 1088 } 1089 } 1090 1091 } catch (Exception se) { 1092 log.log(Level.SEVERE, "SAAJ0590.soap.unable.to.locate.attachment", new Object[] {uri}); 1093 throw new SOAPExceptionImpl(se); 1094 } 1095 return _part; 1096 } 1097 1098 private final InputStream getHeaderBytes() 1099 throws IOException { 1100 SOAPPartImpl sp = (SOAPPartImpl) getSOAPPart(); 1101 return sp.getContentAsStream(); 1102 } 1103 1104 private String convertToSingleLine(String contentType) { 1105 StringBuilder buffer = new StringBuilder(); 1106 for (int i = 0; i < contentType.length(); i ++) { 1107 char c = contentType.charAt(i); 1108 if (c != '\r' && c != '\n' && c != '\t') 1109 buffer.append(c); 1110 } 1111 return buffer.toString(); 1112 } 1113 1114 private MimeMultipart getMimeMessage() throws SOAPException { 1115 try { 1116 SOAPPartImpl soapPart = (SOAPPartImpl) getSOAPPart(); 1117 MimeBodyPart mimeSoapPart = soapPart.getMimePart(); 1118 1119 /* 1120 * Get content type from this message instead of soapPart 1121 * to ensure agreement if soapPart is transcoded (XML <-> FI) 1122 */ 1123 ContentType soapPartCtype = new ContentType(getExpectedContentType()); 1124 1125 if (!isFastInfoset) { 1126 soapPartCtype.setParameter("charset", initCharset()); 1127 } 1128 mimeSoapPart.setHeader("Content-Type", soapPartCtype.toString()); 1129 1130 MimeMultipart headerAndBody = null; 1131 1132 if (!switchOffBM && !switchOffLazyAttachment && 1133 (multiPart != null) && !attachmentsInitialized) { 1134 headerAndBody = new BMMimeMultipart(); 1135 headerAndBody.addBodyPart(mimeSoapPart); 1136 if (attachments != null) { 1137 for (Iterator<AttachmentPart> eachAttachment = attachments.iterator(); 1138 eachAttachment.hasNext();) { 1139 headerAndBody.addBodyPart( 1140 ((AttachmentPartImpl) eachAttachment.next()) 1141 .getMimePart()); 1142 } 1143 } 1144 InputStream in = ((BMMimeMultipart)multiPart).getInputStream(); 1145 if (!((BMMimeMultipart)multiPart).lastBodyPartFound() && 1146 !((BMMimeMultipart)multiPart).isEndOfStream()) { 1147 ((BMMimeMultipart)headerAndBody).setInputStream(in); 1148 ((BMMimeMultipart)headerAndBody).setBoundary( 1149 ((BMMimeMultipart)multiPart).getBoundary()); 1150 ((BMMimeMultipart)headerAndBody). 1151 setLazyAttachments(lazyAttachments); 1152 } 1153 1154 } else { 1155 headerAndBody = new MimeMultipart(); 1156 headerAndBody.addBodyPart(mimeSoapPart); 1157 1158 for (Iterator eachAttachement = getAttachments(); 1159 eachAttachement.hasNext(); 1160 ) { 1161 headerAndBody.addBodyPart( 1162 ((AttachmentPartImpl) eachAttachement.next()) 1163 .getMimePart()); 1164 } 1165 } 1166 1167 ContentType contentType = headerAndBody.getContentType(); 1168 1169 ParameterList l = contentType.getParameterList(); 1170 1171 // set content type depending on SOAP version 1172 l.set("type", getExpectedContentType()); 1173 l.set("boundary", contentType.getParameter("boundary")); 1174 ContentType nct = new ContentType("multipart", "related", l); 1175 1176 headers.setHeader( 1177 "Content-Type", 1178 convertToSingleLine(nct.toString())); 1179 // TBD 1180 // Set content length MIME header here. 1181 1182 return headerAndBody; 1183 } catch (SOAPException ex) { 1184 throw ex; 1185 } catch (Throwable ex) { 1186 log.severe("SAAJ0538.soap.cannot.convert.msg.to.multipart.obj"); 1187 throw new SOAPExceptionImpl( 1188 "Unable to convert SOAP message into " 1189 + "a MimeMultipart object", 1190 ex); 1191 } 1192 } 1193 1194 private String initCharset() { 1195 1196 String charset = null; 1197 1198 String[] cts = getMimeHeaders().getHeader("Content-Type"); 1199 if ((cts != null) && (cts[0] != null)) { 1200 charset = getCharsetString(cts[0]); 1201 } 1202 1203 if (charset == null) { 1204 charset = (String) getProperty(CHARACTER_SET_ENCODING); 1205 } 1206 1207 if (charset != null) { 1208 return charset; 1209 } 1210 1211 return "utf-8"; 1212 } 1213 1214 private String getCharsetString(String s) { 1215 try { 1216 int index = s.indexOf(";"); 1217 if(index < 0) 1218 return null; 1219 ParameterList pl = new ParameterList(s.substring(index)); 1220 return pl.get("charset"); 1221 } catch(Exception e) { 1222 return null; 1223 } 1224 } 1225 1226 @Override 1227 public void saveChanges() throws SOAPException { 1228 1229 // suck in all the data from the attachments and have it 1230 // ready for writing/sending etc. 1231 1232 String charset = initCharset(); 1233 1234 /*if (countAttachments() == 0) {*/ 1235 int attachmentCount = (attachments == null) ? 0 : attachments.size(); 1236 if (attachmentCount == 0) { 1237 if (!switchOffBM && !switchOffLazyAttachment && 1238 !attachmentsInitialized && (multiPart != null)) { 1239 // so there might be attachments 1240 attachmentCount = 1; 1241 } 1242 } 1243 1244 try { 1245 if ((attachmentCount == 0) && !hasXOPContent()) { 1246 InputStream in; 1247 try{ 1248 /* 1249 * Not sure why this is called getHeaderBytes(), but it actually 1250 * returns the whole message as a byte stream. This stream could 1251 * be either XML of Fast depending on the mode. 1252 */ 1253 in = getHeaderBytes(); 1254 // no attachments, hence this property can be false 1255 this.optimizeAttachmentProcessing = false; 1256 if (SOAPPartImpl.lazyContentLength) { 1257 inputStreamAfterSaveChanges = in; 1258 } 1259 } catch (IOException ex) { 1260 log.severe("SAAJ0539.soap.cannot.get.header.stream"); 1261 throw new SOAPExceptionImpl( 1262 "Unable to get header stream in saveChanges: ", 1263 ex); 1264 } 1265 1266 if (in instanceof ByteInputStream) { 1267 ByteInputStream bIn = (ByteInputStream)in; 1268 messageBytes = bIn.getBytes(); 1269 messageByteCount = bIn.getCount(); 1270 } 1271 1272 setFinalContentType(charset); 1273 /* 1274 headers.setHeader( 1275 "Content-Type", 1276 getExpectedContentType() + 1277 (isFastInfoset ? "" : "; charset=" + charset));*/ 1278 if (messageByteCount > 0) { 1279 headers.setHeader( 1280 "Content-Length", 1281 Integer.toString(messageByteCount)); 1282 } 1283 } else { 1284 if(hasXOPContent()) 1285 mmp = getXOPMessage(); 1286 else 1287 mmp = getMimeMessage(); 1288 } 1289 } catch (Throwable ex) { 1290 log.severe("SAAJ0540.soap.err.saving.multipart.msg"); 1291 throw new SOAPExceptionImpl( 1292 "Error during saving a multipart message", 1293 ex); 1294 } 1295 1296 // FIX ME -- SOAP Action replaced by Content-Type optional parameter action 1297 /* 1298 if(isCorrectSoapVersion(SOAP1_1_FLAG)) { 1299 1300 String[] soapAction = headers.getHeader("SOAPAction"); 1301 1302 if (soapAction == null || soapAction.length == 0) 1303 headers.setHeader("SOAPAction", "\"\""); 1304 1305 } 1306 */ 1307 1308 saved = true; 1309 } 1310 1311 private MimeMultipart getXOPMessage() throws SOAPException { 1312 try { 1313 MimeMultipart headerAndBody = new MimeMultipart(); 1314 SOAPPartImpl soapPart = (SOAPPartImpl)getSOAPPart(); 1315 MimeBodyPart mimeSoapPart = soapPart.getMimePart(); 1316 ContentType soapPartCtype = 1317 new ContentType("application/xop+xml"); 1318 soapPartCtype.setParameter("type", getExpectedContentType()); 1319 String charset = initCharset(); 1320 soapPartCtype.setParameter("charset", charset); 1321 mimeSoapPart.setHeader("Content-Type", soapPartCtype.toString()); 1322 headerAndBody.addBodyPart(mimeSoapPart); 1323 1324 for (Iterator eachAttachement = getAttachments(); 1325 eachAttachement.hasNext(); 1326 ) { 1327 headerAndBody.addBodyPart( 1328 ((AttachmentPartImpl) eachAttachement.next()) 1329 .getMimePart()); 1330 } 1331 1332 ContentType contentType = headerAndBody.getContentType(); 1333 1334 ParameterList l = contentType.getParameterList(); 1335 1336 //lets not write start-info for now till we get servlet fix done 1337 l.set("start-info", getExpectedContentType());//+";charset="+initCharset()); 1338 1339 // set content type depending on SOAP version 1340 l.set("type", "application/xop+xml"); 1341 1342 if (isCorrectSoapVersion(SOAP1_2_FLAG)) { 1343 String action = getAction(); 1344 if(action != null) 1345 l.set("action", action); 1346 } 1347 1348 l.set("boundary", contentType.getParameter("boundary")); 1349 ContentType nct = new ContentType("Multipart", "Related", l); 1350 headers.setHeader( 1351 "Content-Type", 1352 convertToSingleLine(nct.toString())); 1353 // TBD 1354 // Set content length MIME header here. 1355 1356 return headerAndBody; 1357 } catch (SOAPException ex) { 1358 throw ex; 1359 } catch (Throwable ex) { 1360 log.severe("SAAJ0538.soap.cannot.convert.msg.to.multipart.obj"); 1361 throw new SOAPExceptionImpl( 1362 "Unable to convert SOAP message into " 1363 + "a MimeMultipart object", 1364 ex); 1365 } 1366 1367 } 1368 1369 private boolean hasXOPContent() throws ParseException { 1370 String type = getContentType(); 1371 if(type == null) 1372 return false; 1373 ContentType ct = new ContentType(type); 1374 //return isMimeMultipartXOPPackage(ct) || isSOAPBodyXOPPackage(ct); 1375 return isMimeMultipartXOPSoap1_1Package(ct) || 1376 isMimeMultipartXOPSoap1_2Package(ct) || isSOAPBodyXOPPackage(ct); 1377 1378 } 1379 1380 @Override 1381 public void writeTo(OutputStream out) throws SOAPException, IOException { 1382 if (saveRequired()){ 1383 this.optimizeAttachmentProcessing = true; 1384 saveChanges(); 1385 } 1386 1387 if(!optimizeAttachmentProcessing){ 1388 if (SOAPPartImpl.lazyContentLength && messageByteCount <= 0) { 1389 byte[] buf = new byte[1024]; 1390 1391 int length = 0; 1392 while( (length = inputStreamAfterSaveChanges.read(buf)) != -1) { 1393 out.write(buf,0, length); 1394 messageByteCount += length; 1395 } 1396 if (messageByteCount > 0) { 1397 headers.setHeader( 1398 "Content-Length", 1399 Integer.toString(messageByteCount)); 1400 } 1401 } else { 1402 out.write(messageBytes, 0, messageByteCount); 1403 } 1404 } 1405 else{ 1406 try{ 1407 if(hasXOPContent()){ 1408 mmp.writeTo(out); 1409 }else{ 1410 mmp.writeTo(out); 1411 if (!switchOffBM && !switchOffLazyAttachment && 1412 (multiPart != null) && !attachmentsInitialized) { 1413 ((BMMimeMultipart)multiPart).setInputStream( 1414 ((BMMimeMultipart)mmp).getInputStream()); 1415 } 1416 } 1417 } catch(Exception ex){ 1418 log.severe("SAAJ0540.soap.err.saving.multipart.msg"); 1419 throw new SOAPExceptionImpl( 1420 "Error during saving a multipart message", 1421 ex); 1422 } 1423 } 1424 1425 if(isCorrectSoapVersion(SOAP1_1_FLAG)) { 1426 1427 String[] soapAction = headers.getHeader("SOAPAction"); 1428 1429 if (soapAction == null || soapAction.length == 0) 1430 headers.setHeader("SOAPAction", "\"\""); 1431 1432 } 1433 1434 messageBytes = null; 1435 needsSave(); 1436 } 1437 1438 @Override 1439 public SOAPBody getSOAPBody() throws SOAPException { 1440 SOAPBody body = getSOAPPart().getEnvelope().getBody(); 1441 /*if (body == null) { 1442 throw new SOAPException("No SOAP Body was found in the SOAP Message"); 1443 }*/ 1444 return body; 1445 } 1446 1447 @Override 1448 public SOAPHeader getSOAPHeader() throws SOAPException { 1449 SOAPHeader hdr = getSOAPPart().getEnvelope().getHeader(); 1450 /*if (hdr == null) { 1451 throw new SOAPException("No SOAP Header was found in the SOAP Message"); 1452 }*/ 1453 return hdr; 1454 } 1455 1456 private void initializeAllAttachments () 1457 throws MessagingException, SOAPException { 1458 if (switchOffBM || switchOffLazyAttachment) { 1459 return; 1460 } 1461 1462 if (attachmentsInitialized || (multiPart == null)) { 1463 return; 1464 } 1465 1466 if (attachments == null) 1467 attachments = new FinalArrayList<AttachmentPart>(); 1468 1469 int count = multiPart.getCount(); 1470 for (int i=0; i < count; i++ ) { 1471 initializeAttachment(multiPart.getBodyPart(i)); 1472 } 1473 attachmentsInitialized = true; 1474 //multiPart = null; 1475 needsSave(); 1476 } 1477 1478 private void initializeAttachment(MimeBodyPart mbp) throws SOAPException { 1479 AttachmentPartImpl attachmentPart = new AttachmentPartImpl(); 1480 DataHandler attachmentHandler = mbp.getDataHandler(); 1481 attachmentPart.setDataHandler(attachmentHandler); 1482 1483 AttachmentPartImpl.copyMimeHeaders(mbp, attachmentPart); 1484 attachments.add(attachmentPart); 1485 } 1486 1487 private void initializeAttachment(MimeMultipart multiPart, int i) 1488 throws Exception { 1489 MimeBodyPart currentBodyPart = multiPart.getBodyPart(i); 1490 AttachmentPartImpl attachmentPart = new AttachmentPartImpl(); 1491 1492 DataHandler attachmentHandler = currentBodyPart.getDataHandler(); 1493 attachmentPart.setDataHandler(attachmentHandler); 1494 1495 AttachmentPartImpl.copyMimeHeaders(currentBodyPart, attachmentPart); 1496 addAttachmentPart(attachmentPart); 1497 } 1498 1499 private void setMimeHeaders(SOAPPart soapPart, 1500 MimeBodyPart soapMessagePart) throws Exception { 1501 1502 // first remove the existing content-type 1503 soapPart.removeAllMimeHeaders(); 1504 // add everything present in soapMessagePart 1505 List headers = soapMessagePart.getAllHeaders(); 1506 int sz = headers.size(); 1507 for( int i=0; i<sz; i++ ) { 1508 Header h = (Header) headers.get(i); 1509 soapPart.addMimeHeader(h.getName(), h.getValue()); 1510 } 1511 } 1512 1513 private void initCharsetProperty(ContentType contentType) { 1514 String charset = contentType.getParameter("charset"); 1515 if (charset != null) { 1516 ((SOAPPartImpl) getSOAPPart()).setSourceCharsetEncoding(charset); 1517 if(!charset.equalsIgnoreCase("utf-8")) 1518 setProperty(CHARACTER_SET_ENCODING, charset); 1519 } 1520 } 1521 1522 public void setLazyAttachments(boolean flag) { 1523 lazyAttachments = flag; 1524 } 1525 1526 }