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