src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/soap/MessageImpl.java

Thu, 31 Aug 2017 15:18:52 +0800

author
aoqi
date
Thu, 31 Aug 2017 15:18:52 +0800
changeset 637
9c07ef4934dd
parent 368
0989ad8c0860
parent 0
373ffda63c9a
permissions
-rw-r--r--

merge

     1 /*
     2  * Copyright (c) 1997, 2012, 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  */
    26 package com.sun.xml.internal.messaging.saaj.soap;
    28 import java.io.*;
    29 import java.util.*;
    30 import java.util.logging.Level;
    31 import java.util.logging.Logger;
    33 import javax.activation.DataHandler;
    34 import javax.activation.DataSource;
    35 import javax.xml.soap.*;
    36 import javax.xml.transform.Source;
    37 import javax.xml.transform.stream.StreamSource;
    39 import com.sun.xml.internal.messaging.saaj.packaging.mime.Header;
    40 import com.sun.xml.internal.messaging.saaj.packaging.mime.internet.*;
    41 import com.sun.xml.internal.messaging.saaj.packaging.mime.util.*;
    42 import com.sun.xml.internal.messaging.saaj.packaging.mime.MessagingException;
    44 import com.sun.xml.internal.messaging.saaj.SOAPExceptionImpl;
    45 import com.sun.xml.internal.messaging.saaj.soap.impl.EnvelopeImpl;
    46 import com.sun.xml.internal.messaging.saaj.util.*;
    47 import com.sun.xml.internal.org.jvnet.mimepull.MIMEPart;
    49 /**
    50  * The message implementation for SOAP messages with
    51  * attachments. Messages for specific profiles will likely extend this
    52  * MessageImpl class and add more value for that particular profile.
    53  *
    54  * @author Anil Vijendran (akv@eng.sun.com)
    55  * @author Rajiv Mordani (rajiv.mordani@sun.com)
    56  * @author Manveen Kaur (manveen.kaur@sun.com)
    57  */
    59 public abstract class MessageImpl
    60     extends SOAPMessage
    61     implements SOAPConstants {
    64     public static final String CONTENT_ID             = "Content-ID";
    65     public static final String CONTENT_LOCATION       = "Content-Location";
    67     protected static final Logger log =
    68         Logger.getLogger(LogDomainConstants.SOAP_DOMAIN,
    69                          "com.sun.xml.internal.messaging.saaj.soap.LocalStrings");
    71     protected static final int PLAIN_XML_FLAG      = 1;      // 00001
    72     protected static final int MIME_MULTIPART_FLAG = 2;      // 00010
    73     protected static final int SOAP1_1_FLAG = 4;             // 00100
    74     protected static final int SOAP1_2_FLAG = 8;             // 01000
    75     //protected static final int MIME_MULTIPART_XOP_FLAG = 14; // 01110
    76     protected static final int MIME_MULTIPART_XOP_SOAP1_1_FLAG = 6;  // 00110
    77     protected static final int MIME_MULTIPART_XOP_SOAP1_2_FLAG = 10; // 01010
    78     protected static final int XOP_FLAG = 13;                // 01101
    79     protected static final int FI_ENCODED_FLAG     = 16;     // 10000
    81     protected MimeHeaders headers;
    82     protected ContentType contentType;
    83     protected SOAPPartImpl soapPartImpl;
    84     protected FinalArrayList attachments;
    85     protected boolean saved = false;
    86     protected byte[] messageBytes;
    87     protected int messageByteCount;
    88     protected HashMap properties = new HashMap();
    90     // used for lazy attachment initialization
    91     protected MimeMultipart multiPart = null;
    92     protected boolean attachmentsInitialized = false;
    94     /**
    95      * True if this part is encoded using Fast Infoset.
    96      * MIME -> application/fastinfoset
    97      */
    98     protected boolean isFastInfoset = false;
   100     /**
   101      * True if the Accept header of this message includes
   102      * application/fastinfoset
   103      */
   104     protected boolean acceptFastInfoset = false;
   106     protected MimeMultipart mmp = null;
   108     // if attachments are present, don't read the entire message in byte stream in saveTo()
   109     private boolean optimizeAttachmentProcessing = true;
   111     private InputStream inputStreamAfterSaveChanges = null;
   113     // switch back to old MimeMultipart incase of problem
   114     private static boolean switchOffBM = false;
   115     private static boolean switchOffLazyAttachment = false;
   116     private static boolean useMimePull = false;
   118     static {
   119             String s = SAAJUtil.getSystemProperty("saaj.mime.optimization");
   120             if ((s != null) && s.equals("false")) {
   121                 switchOffBM = true;
   122             }
   123             s = SAAJUtil.getSystemProperty("saaj.lazy.mime.optimization");
   124             if ((s != null) && s.equals("false")) {
   125                 switchOffLazyAttachment = true;
   126             }
   127             useMimePull = SAAJUtil.getSystemBoolean("saaj.use.mimepull");
   129     }
   131     //property to indicate optimized serialization for lazy attachments
   132     private boolean lazyAttachments = false;
   134     // most of the times, Content-Types are already all lower cased.
   135     // String.toLowerCase() works faster in this case, so even if you
   136     // are only doing one comparison, it pays off to use String.toLowerCase()
   137     // than String.equalsIgnoreCase(). When you do more than one comparison,
   138     // the benefits of String.toLowerCase() dominates.
   139     //
   140     //
   141     // for FI,
   142     //   use application/fastinfoset for SOAP 1.1
   143     //   use application/soap+fastinfoset for SOAP 1.2
   144     // to speed up comparisons, test methods always use lower cases.
   146     /**
   147      * @param primary
   148      *      must be all lower case
   149      * @param sub
   150      *      must be all lower case
   151      */
   152     private static boolean isSoap1_1Type(String primary, String sub) {
   153         return primary.equalsIgnoreCase("text") && sub.equalsIgnoreCase("xml")
   154             || primary.equalsIgnoreCase("text") && sub.equalsIgnoreCase("xml-soap")
   155             || primary.equals("application")
   156                && sub.equals("fastinfoset");
   157     }
   159     /**
   160      * @param type
   161      *      must be all lower case
   162      */
   163     private static boolean isEqualToSoap1_1Type(String type) {
   164         return type.startsWith("text/xml") ||
   165                type.startsWith("application/fastinfoset");
   166     }
   168     /**
   169      * @param primary
   170      *      must be all lower case
   171      * @param sub
   172      *      must be all lower case
   173      */
   174     private static boolean isSoap1_2Type(String primary, String sub) {
   175         return primary.equals("application")
   176                && (sub.equals("soap+xml")
   177                    || sub.equals("soap+fastinfoset"));
   178     }
   180     /**
   181      * @param type
   182      *      must be all lower case
   183      */
   184     private static boolean isEqualToSoap1_2Type(String type) {
   185         return type.startsWith("application/soap+xml") ||
   186                type.startsWith("application/soap+fastinfoset");
   187     }
   189     /**
   190       * Construct a new message. This will be invoked before message
   191       * sends.
   192       */
   193     protected MessageImpl() {
   194         this(false, false);
   195         attachmentsInitialized = true;
   196     }
   198     /**
   199       * Construct a new message. This will be invoked before message
   200       * sends.
   201       */
   202     protected MessageImpl(boolean isFastInfoset, boolean acceptFastInfoset) {
   203         this.isFastInfoset = isFastInfoset;
   204         this.acceptFastInfoset = acceptFastInfoset;
   206         headers = new MimeHeaders();
   207         headers.setHeader("Accept", getExpectedAcceptHeader());
   208         contentType = new ContentType();
   209     }
   211     /**
   212      * Shallow copy.
   213      */
   214     protected MessageImpl(SOAPMessage msg) {
   215         if (!(msg instanceof MessageImpl)) {
   216             // don't know how to handle this.
   217         }
   218         MessageImpl src = (MessageImpl) msg;
   219         this.headers = src.headers;
   220         this.soapPartImpl = src.soapPartImpl;
   221         this.attachments = src.attachments;
   222         this.saved = src.saved;
   223         this.messageBytes = src.messageBytes;
   224         this.messageByteCount = src.messageByteCount;
   225         this.properties = src.properties;
   226         this.contentType = src.contentType;
   227     }
   229     /**
   230      * @param stat
   231      *      the mask value obtained from {@link #identifyContentType(ContentType)}
   232      */
   233     protected static boolean isSoap1_1Content(int stat) {
   234         return (stat & SOAP1_1_FLAG) != 0;
   235     }
   237     /**
   238      * @param stat
   239      *      the mask value obtained from {@link #identifyContentType(ContentType)}
   240      */
   241     protected static boolean isSoap1_2Content(int stat) {
   242         return (stat & SOAP1_2_FLAG) != 0;
   243     }
   245      private static boolean isMimeMultipartXOPSoap1_2Package(ContentType contentType) {
   246         String type = contentType.getParameter("type");
   247         if (type == null) {
   248             return false;
   249         }
   250         type = type.toLowerCase();
   251         if (!type.startsWith("application/xop+xml")) {
   252             return false;
   253         }
   254         String startinfo = contentType.getParameter("start-info");
   255         if (startinfo == null) {
   256             return false;
   257         }
   258         startinfo = startinfo.toLowerCase();
   259         return isEqualToSoap1_2Type(startinfo);
   260     }
   263      //private static boolean isMimeMultipartXOPPackage(ContentType contentType) {
   264      private static boolean isMimeMultipartXOPSoap1_1Package(ContentType contentType) {
   265         String type = contentType.getParameter("type");
   266         if(type==null)
   267             return false;
   269         type = type.toLowerCase();
   270         if(!type.startsWith("application/xop+xml"))
   271             return false;
   273         String startinfo = contentType.getParameter("start-info");
   274         if(startinfo == null)
   275             return false;
   276         startinfo = startinfo.toLowerCase();
   277         return isEqualToSoap1_1Type(startinfo);
   278     }
   280     private static boolean isSOAPBodyXOPPackage(ContentType contentType){
   281         String primary = contentType.getPrimaryType();
   282         String sub = contentType.getSubType();
   284         if (primary.equalsIgnoreCase("application")) {
   285             if (sub.equalsIgnoreCase("xop+xml")) {
   286                 String type = getTypeParameter(contentType);
   287                 return isEqualToSoap1_2Type(type) || isEqualToSoap1_1Type(type);
   288             }
   289         }
   290         return false;
   291     }
   293     /**
   294      * Construct a message from an input stream. When messages are
   295      * received, there's two parts -- the transport headers and the
   296      * message content in a transport specific stream.
   297      */
   298     protected MessageImpl(MimeHeaders headers, final InputStream in)
   299         throws SOAPExceptionImpl {
   300         contentType = parseContentType(headers);
   301         init(headers,identifyContentType(contentType),contentType,in);
   302     }
   304     private static ContentType parseContentType(MimeHeaders headers) throws SOAPExceptionImpl {
   305         final String ct;
   306         if (headers != null)
   307             ct = getContentType(headers);
   308         else {
   309             log.severe("SAAJ0550.soap.null.headers");
   310             throw new SOAPExceptionImpl("Cannot create message: " +
   311                                         "Headers can't be null");
   312         }
   314         if (ct == null) {
   315             log.severe("SAAJ0532.soap.no.Content-Type");
   316             throw new SOAPExceptionImpl("Absent Content-Type");
   317         }
   318         try {
   319             return new ContentType(ct);
   320         } catch (Throwable ex) {
   321             log.severe("SAAJ0535.soap.cannot.internalize.message");
   322             throw new SOAPExceptionImpl("Unable to internalize message", ex);
   323         }
   324     }
   326     /**
   327      * Construct a message from an input stream. When messages are
   328      * received, there's two parts -- the transport headers and the
   329      * message content in a transport specific stream.
   330      *
   331      * @param contentType
   332      *      The parsed content type header from the headers variable.
   333      *      This is redundant parameter, but it avoids reparsing this header again.
   334      * @param stat
   335      *      The result of {@link #identifyContentType(ContentType)} over
   336      *      the contentType parameter. This redundant parameter, but it avoids
   337      *      recomputing this information again.
   338      */
   339     protected MessageImpl(MimeHeaders headers, final ContentType contentType, int stat, final InputStream in) throws SOAPExceptionImpl {
   340         init(headers, stat, contentType, in);
   342     }
   344     private void init(MimeHeaders headers, int stat, final ContentType contentType, final InputStream in) throws SOAPExceptionImpl {
   345         this.headers = headers;
   347         try {
   349             // Set isFastInfoset/acceptFastInfoset flag based on MIME type
   350             if ((stat & FI_ENCODED_FLAG) > 0) {
   351                 isFastInfoset = acceptFastInfoset = true;
   352             }
   354             // If necessary, inspect Accept header to set acceptFastInfoset
   355             if (!isFastInfoset) {
   356                 String[] values = headers.getHeader("Accept");
   357                 if (values != null) {
   358                     for (int i = 0; i < values.length; i++) {
   359                         StringTokenizer st = new StringTokenizer(values[i], ",");
   360                         while (st.hasMoreTokens()) {
   361                             final String token = st.nextToken().trim();
   362                             if (token.equalsIgnoreCase("application/fastinfoset") ||
   363                                 token.equalsIgnoreCase("application/soap+fastinfoset")) {
   364                                 acceptFastInfoset = true;
   365                                 break;
   366                             }
   367                         }
   368                     }
   369                 }
   370             }
   372             if (!isCorrectSoapVersion(stat)) {
   373                 log.log(
   374                     Level.SEVERE,
   375                     "SAAJ0533.soap.incorrect.Content-Type",
   376                     new String[] {
   377                         contentType.toString(),
   378                         getExpectedContentType()});
   379                 throw new SOAPVersionMismatchException(
   380                     "Cannot create message: incorrect content-type for SOAP version. Got: "
   381                         + contentType
   382                         + " Expected: "
   383                         + getExpectedContentType());
   384             }
   386             if ((stat & PLAIN_XML_FLAG) != 0) {
   387                 if (isFastInfoset) {
   388                     getSOAPPart().setContent(
   389                         FastInfosetReflection.FastInfosetSource_new(in));
   390                 } else {
   391                     initCharsetProperty(contentType);
   392                     getSOAPPart().setContent(new StreamSource(in));
   393                 }
   394             }
   395             else if ((stat & MIME_MULTIPART_FLAG) != 0) {
   396                 DataSource ds = new DataSource() {
   397                     public InputStream getInputStream() {
   398                         return in;
   399                     }
   401                     public OutputStream getOutputStream() {
   402                         return null;
   403                     }
   405                     public String getContentType() {
   406                         return contentType.toString();
   407                     }
   409                     public String getName() {
   410                         return "";
   411                     }
   412                 };
   414                 multiPart = null;
   415                 if (useMimePull) {
   416                     multiPart = new MimePullMultipart(ds,contentType);
   417                 } else if (switchOffBM) {
   418                     multiPart = new MimeMultipart(ds,contentType);
   419                 } else {
   420                     multiPart = new BMMimeMultipart(ds,contentType);
   421                 }
   423                 String startParam = contentType.getParameter("start");
   424                 MimeBodyPart soapMessagePart = null;
   425                 InputStream soapPartInputStream = null;
   426                 String contentID = null;
   427                 String contentIDNoAngle = null;
   428                 if (switchOffBM || switchOffLazyAttachment) {
   429                     if(startParam == null) {
   430                         soapMessagePart = multiPart.getBodyPart(0);
   431                         for (int i = 1; i < multiPart.getCount(); i++) {
   432                             initializeAttachment(multiPart, i);
   433                         }
   434                     } else {
   435                         soapMessagePart = multiPart.getBodyPart(startParam);
   436                         for (int i = 0; i < multiPart.getCount(); i++) {
   437                             contentID = multiPart.getBodyPart(i).getContentID();
   438                             // Old versions of AXIS2 put angle brackets around the content
   439                             // id but not the start param
   440                             contentIDNoAngle = (contentID != null) ?
   441                                 contentID.replaceFirst("^<", "").replaceFirst(">$", "") : null;
   442                             if(!startParam.equals(contentID) && !startParam.equals(contentIDNoAngle))
   443                                 initializeAttachment(multiPart, i);
   444                         }
   445                     }
   446                 } else {
   447                     if (useMimePull) {
   448                         MimePullMultipart mpMultipart = (MimePullMultipart)multiPart;
   449                         MIMEPart sp = mpMultipart.readAndReturnSOAPPart();
   450                         soapMessagePart = new MimeBodyPart(sp);
   451                         soapPartInputStream = sp.readOnce();
   452                     } else {
   453                         BMMimeMultipart bmMultipart =
   454                                 (BMMimeMultipart) multiPart;
   455                         InputStream stream = bmMultipart.initStream();
   457                         SharedInputStream sin = null;
   458                         if (stream instanceof SharedInputStream) {
   459                             sin = (SharedInputStream) stream;
   460                         }
   462                         String boundary = "--" +
   463                                 contentType.getParameter("boundary");
   464                         byte[] bndbytes = ASCIIUtility.getBytes(boundary);
   465                         if (startParam == null) {
   466                             soapMessagePart =
   467                                     bmMultipart.getNextPart(stream, bndbytes, sin);
   468                             bmMultipart.removeBodyPart(soapMessagePart);
   469                         } else {
   470                             MimeBodyPart bp = null;
   471                             try {
   472                                while (!startParam.equals(contentID) && !startParam.equals(contentIDNoAngle)) {
   473                                     bp = bmMultipart.getNextPart(
   474                                             stream, bndbytes, sin);
   475                                     contentID = bp.getContentID();
   476                                     // Old versions of AXIS2 put angle brackets around the content
   477                                     // id but not the start param
   478                                     contentIDNoAngle = (contentID != null) ?
   479                                         contentID.replaceFirst("^<", "").replaceFirst(">$", "") : null;
   480                                 }
   481                                 soapMessagePart = bp;
   482                                 bmMultipart.removeBodyPart(bp);
   483                             } catch (Exception e) {
   484                                 throw new SOAPExceptionImpl(e);
   485                             }
   486                         }
   487                     }
   488                 }
   490                 if (soapPartInputStream == null && soapMessagePart != null) {
   491                     soapPartInputStream = soapMessagePart.getInputStream();
   492                 }
   494                 ContentType soapPartCType = new ContentType(
   495                                             soapMessagePart.getContentType());
   496                 initCharsetProperty(soapPartCType);
   497                 String baseType = soapPartCType.getBaseType().toLowerCase();
   498                 if(!(isEqualToSoap1_1Type(baseType)
   499                   || isEqualToSoap1_2Type(baseType)
   500                   || isSOAPBodyXOPPackage(soapPartCType))) {
   501                     log.log(Level.SEVERE,
   502                             "SAAJ0549.soap.part.invalid.Content-Type",
   503                             new Object[] {baseType});
   504                     throw new SOAPExceptionImpl(
   505                             "Bad Content-Type for SOAP Part : " +
   506                             baseType);
   507                 }
   509                 SOAPPart soapPart = getSOAPPart();
   510                 setMimeHeaders(soapPart, soapMessagePart);
   511                 soapPart.setContent(isFastInfoset ?
   512                      (Source) FastInfosetReflection.FastInfosetSource_new(
   513                          soapPartInputStream) :
   514                      (Source) new StreamSource(soapPartInputStream));
   515             } else {
   516                 log.severe("SAAJ0534.soap.unknown.Content-Type");
   517                 throw new SOAPExceptionImpl("Unrecognized Content-Type");
   518             }
   519         } catch (Throwable ex) {
   520             log.severe("SAAJ0535.soap.cannot.internalize.message");
   521             throw new SOAPExceptionImpl("Unable to internalize message", ex);
   522         }
   523         needsSave();
   524     }
   526     public boolean isFastInfoset() {
   527         return isFastInfoset;
   528     }
   530     public boolean acceptFastInfoset() {
   531         return acceptFastInfoset;
   532     }
   534     public void setIsFastInfoset(boolean value) {
   535         if (value != isFastInfoset) {
   536             isFastInfoset = value;
   537             if (isFastInfoset) {
   538                 acceptFastInfoset = true;
   539             }
   540             saved = false;      // ensure transcoding if necessary
   541         }
   542     }
   544     public Object getProperty(String property) {
   545         return (String) properties.get(property);
   546     }
   548     public void setProperty(String property, Object value) {
   549         verify(property, value);
   550         properties.put(property, value);
   551     }
   553     private void verify(String property, Object value) {
   554         if (property.equalsIgnoreCase(SOAPMessage.WRITE_XML_DECLARATION)) {
   555             if (!("true".equals(value) || "false".equals(value)))
   556                 throw new RuntimeException(
   557                     property + " must have value false or true");
   559             try {
   560                 EnvelopeImpl env = (EnvelopeImpl) getSOAPPart().getEnvelope();
   561                 if ("true".equalsIgnoreCase((String)value)) {
   562                     env.setOmitXmlDecl("no");
   563                 } else if ("false".equalsIgnoreCase((String)value)) {
   564                     env.setOmitXmlDecl("yes");
   565                 }
   566             } catch (Exception e) {
   567                 log.log(Level.SEVERE, "SAAJ0591.soap.exception.in.set.property",
   568                     new Object[] {e.getMessage(), "javax.xml.soap.write-xml-declaration"});
   569                 throw new RuntimeException(e);
   570             }
   571             return;
   572         }
   574         if (property.equalsIgnoreCase(SOAPMessage.CHARACTER_SET_ENCODING)) {
   575             try {
   576                 ((EnvelopeImpl) getSOAPPart().getEnvelope()).setCharsetEncoding((String)value);
   577             } catch (Exception e) {
   578                 log.log(Level.SEVERE, "SAAJ0591.soap.exception.in.set.property",
   579                     new Object[] {e.getMessage(), "javax.xml.soap.character-set-encoding"});
   580                 throw new RuntimeException(e);
   581             }
   582         }
   583     }
   585     protected abstract boolean isCorrectSoapVersion(int contentTypeId);
   587     protected abstract String getExpectedContentType();
   588     protected abstract String getExpectedAcceptHeader();
   590     /**
   591      * Sniffs the Content-Type header so that we can determine how to process.
   592      *
   593      * <p>
   594      * In the absence of type attribute we assume it to be text/xml.
   595      * That would mean we're easy on accepting the message and
   596      * generate the correct thing (as the SWA spec also specifies
   597      * that the type parameter should always be text/xml)
   598      *
   599      * @return
   600      *      combination of flags, such as PLAIN_XML_CODE and MIME_MULTIPART_CODE.
   601      */
   602     // SOAP1.2 allow SOAP1.2 content type
   603     static int identifyContentType(ContentType ct)
   604         throws SOAPExceptionImpl {
   605         // TBD
   606         //    Is there anything else we need to verify here?
   608         String primary = ct.getPrimaryType().toLowerCase();
   609         String sub = ct.getSubType().toLowerCase();
   611         if (primary.equals("multipart")) {
   612             if (sub.equals("related")) {
   613                 String type = getTypeParameter(ct);
   614                 if (isEqualToSoap1_1Type(type)) {
   615                     return (type.equals("application/fastinfoset") ?
   616                            FI_ENCODED_FLAG : 0) | MIME_MULTIPART_FLAG | SOAP1_1_FLAG;
   617                 }
   618                 else if (isEqualToSoap1_2Type(type)) {
   619                     return (type.equals("application/soap+fastinfoset") ?
   620                            FI_ENCODED_FLAG : 0) | MIME_MULTIPART_FLAG | SOAP1_2_FLAG;
   621                 /*} else if (isMimeMultipartXOPPackage(ct)) {
   622                     return MIME_MULTIPART_XOP_FLAG;*/
   623                 } else if (isMimeMultipartXOPSoap1_1Package(ct)) {
   624                     return MIME_MULTIPART_XOP_SOAP1_1_FLAG;
   625                 } else if (isMimeMultipartXOPSoap1_2Package(ct)) {
   626                     return MIME_MULTIPART_XOP_SOAP1_2_FLAG;
   627                 } else {
   628                     log.severe("SAAJ0536.soap.content-type.mustbe.multipart");
   629                     throw new SOAPExceptionImpl(
   630                         "Content-Type needs to be Multipart/Related "
   631                             + "and with \"type=text/xml\" "
   632                             + "or \"type=application/soap+xml\"");
   633                 }
   634             } else {
   635                 log.severe("SAAJ0537.soap.invalid.content-type");
   636                 throw new SOAPExceptionImpl(
   637                     "Invalid Content-Type: " + primary + '/' + sub);
   638             }
   639         }
   640         else if (isSoap1_1Type(primary, sub)) {
   641             return (primary.equalsIgnoreCase("application")
   642                     && sub.equalsIgnoreCase("fastinfoset") ?
   643                         FI_ENCODED_FLAG : 0)
   644                    | PLAIN_XML_FLAG | SOAP1_1_FLAG;
   645         }
   646         else if (isSoap1_2Type(primary, sub)) {
   647             return (primary.equalsIgnoreCase("application")
   648                     && sub.equalsIgnoreCase("soap+fastinfoset") ?
   649                         FI_ENCODED_FLAG : 0)
   650                    | PLAIN_XML_FLAG | SOAP1_2_FLAG;
   651         } else if(isSOAPBodyXOPPackage(ct)){
   652             return XOP_FLAG;
   653         } else {
   654             log.severe("SAAJ0537.soap.invalid.content-type");
   655             throw new SOAPExceptionImpl(
   656                 "Invalid Content-Type:"
   657                     + primary
   658                     + '/'
   659                     + sub
   660                     + ". Is this an error message instead of a SOAP response?");
   661         }
   662     }
   664     /**
   665      * Obtains the type parameter of the Content-Type header. Defaults to "text/xml".
   666      */
   667     private static String getTypeParameter(ContentType contentType) {
   668         String p = contentType.getParameter("type");
   669         if(p!=null)
   670             return p.toLowerCase();
   671         else
   672             return "text/xml";
   673     }
   675     public MimeHeaders getMimeHeaders() {
   676         return this.headers;
   677     }
   679     final static String getContentType(MimeHeaders headers) {
   680         String[] values = headers.getHeader("Content-Type");
   681         if (values == null)
   682             return null;
   683         else
   684             return values[0];
   685     }
   687     /*
   688      * Get the complete ContentType value along with optional parameters.
   689      */
   690     public String getContentType() {
   691         return getContentType(this.headers);
   692     }
   694     public void setContentType(String type) {
   695         headers.setHeader("Content-Type", type);
   696         needsSave();
   697     }
   699     private ContentType contentType() {
   700         ContentType ct = null;
   701         try {
   702             String currentContent = getContentType();
   703             if (currentContent == null) {
   704                 return this.contentType;
   705             }
   706             ct = new ContentType(currentContent);
   707         } catch (Exception e) {
   708             // what to do here?
   709         }
   710         return ct;
   711     }
   713     /*
   714      * Return the MIME type string, without the parameters.
   715      */
   716     public String getBaseType() {
   717         return contentType().getBaseType();
   718     }
   720     public void setBaseType(String type) {
   721         ContentType ct = contentType();
   722         ct.setParameter("type", type);
   723         headers.setHeader("Content-Type", ct.toString());
   724         needsSave();
   725     }
   727     public String getAction() {
   728         return contentType().getParameter("action");
   729     }
   731     public void setAction(String action) {
   732         ContentType ct = contentType();
   733         ct.setParameter("action", action);
   734         headers.setHeader("Content-Type", ct.toString());
   735         needsSave();
   736     }
   738     public String getCharset() {
   739         return contentType().getParameter("charset");
   740     }
   742     public void setCharset(String charset) {
   743         ContentType ct = contentType();
   744         ct.setParameter("charset", charset);
   745         headers.setHeader("Content-Type", ct.toString());
   746         needsSave();
   747     }
   749     /**
   750      * All write methods (i.e setters) should call this method in
   751      * order to make sure that a save is necessary since the state
   752      * has been modified.
   753      */
   754     private final void needsSave() {
   755         saved = false;
   756     }
   758     public  boolean saveRequired() {
   759         return saved != true;
   760     }
   762     public String getContentDescription() {
   763         String[] values = headers.getHeader("Content-Description");
   764         if (values != null && values.length > 0)
   765             return values[0];
   766         return null;
   767     }
   769     public void setContentDescription(String description) {
   770         headers.setHeader("Content-Description", description);
   771         needsSave();
   772     }
   774     public abstract SOAPPart getSOAPPart();
   776     public void removeAllAttachments() {
   777         try {
   778             initializeAllAttachments();
   779         } catch (Exception e) {
   780             throw new RuntimeException(e);
   781         }
   783         if (attachments != null) {
   784             attachments.clear();
   785             needsSave();
   786         }
   787     }
   789     public int countAttachments() {
   790         try {
   791             initializeAllAttachments();
   792         } catch (Exception e) {
   793             throw new RuntimeException(e);
   794         }
   795         if (attachments != null)
   796             return attachments.size();
   797         return 0;
   798     }
   800     public void addAttachmentPart(AttachmentPart attachment) {
   801         try {
   802             initializeAllAttachments();
   803             this.optimizeAttachmentProcessing = true;
   804         } catch (Exception e) {
   805             throw new RuntimeException(e);
   806         }
   807         if (attachments == null)
   808             attachments = new FinalArrayList();
   810         attachments.add(attachment);
   812         needsSave();
   813     }
   815     static private final Iterator nullIter = Collections.EMPTY_LIST.iterator();
   817     public Iterator getAttachments() {
   818         try {
   819             initializeAllAttachments();
   820         } catch (Exception e) {
   821             throw new RuntimeException(e);
   822         }
   823         if (attachments == null)
   824             return nullIter;
   825         return attachments.iterator();
   826     }
   828     private void setFinalContentType(String charset) {
   829         ContentType ct = contentType();
   830         if (ct == null) {
   831             ct = new ContentType();
   832         }
   833         String[] split = getExpectedContentType().split("/");
   834         ct.setPrimaryType(split[0]);
   835         ct.setSubType(split[1]);
   836         ct.setParameter("charset", charset);
   837         headers.setHeader("Content-Type", ct.toString());
   838     }
   840     private class MimeMatchingIterator implements Iterator {
   841         public MimeMatchingIterator(MimeHeaders headers) {
   842             this.headers = headers;
   843             this.iter = attachments.iterator();
   844         }
   846         private Iterator iter;
   847         private MimeHeaders headers;
   848         private Object nextAttachment;
   850         public boolean hasNext() {
   851             if (nextAttachment == null)
   852                 nextAttachment = nextMatch();
   853             return nextAttachment != null;
   854         }
   856         public Object next() {
   857             if (nextAttachment != null) {
   858                 Object ret = nextAttachment;
   859                 nextAttachment = null;
   860                 return ret;
   861             }
   863             if (hasNext())
   864                 return nextAttachment;
   866             return null;
   867         }
   869         Object nextMatch() {
   870             while (iter.hasNext()) {
   871                 AttachmentPartImpl ap = (AttachmentPartImpl) iter.next();
   872                 if (ap.hasAllHeaders(headers))
   873                     return ap;
   874             }
   875             return null;
   876         }
   878         public void remove() {
   879             iter.remove();
   880         }
   881     }
   883     public Iterator getAttachments(MimeHeaders headers) {
   884         try {
   885             initializeAllAttachments();
   886         } catch (Exception e) {
   887             throw new RuntimeException(e);
   888         }
   889         if (attachments == null)
   890             return nullIter;
   892         return new MimeMatchingIterator(headers);
   893     }
   895     public void removeAttachments(MimeHeaders headers) {
   896         try {
   897             initializeAllAttachments();
   898         } catch (Exception e) {
   899             throw new RuntimeException(e);
   900         }
   901         if (attachments == null)
   902             return ;
   904         Iterator it =  new MimeMatchingIterator(headers);
   905         while (it.hasNext()) {
   906             int index = attachments.indexOf(it.next());
   907             attachments.set(index, null);
   908         }
   909         FinalArrayList f = new FinalArrayList();
   910         for (int i = 0; i < attachments.size(); i++) {
   911             if (attachments.get(i) != null) {
   912                 f.add(attachments.get(i));
   913             }
   914         }
   915         attachments = f;
   916        // needsSave();
   917     }
   919     public AttachmentPart createAttachmentPart() {
   920         return new AttachmentPartImpl();
   921     }
   923     public  AttachmentPart getAttachment(SOAPElement element)
   924         throws SOAPException {
   925         try {
   926             initializeAllAttachments();
   927         } catch (Exception e) {
   928             throw new RuntimeException(e);
   929         }
   930         String uri;
   931         String hrefAttr = element.getAttribute("href");
   932         if ("".equals(hrefAttr)) {
   933             Node node = getValueNodeStrict(element);
   934             String swaRef = null;
   935             if (node != null) {
   936                 swaRef = node.getValue();
   937             }
   938             if (swaRef == null || "".equals(swaRef)) {
   939                 return null;
   940             } else {
   941                 uri = swaRef;
   942             }
   943         } else {
   944             uri = hrefAttr;
   945         }
   946         return getAttachmentPart(uri);
   947     }
   949     private Node getValueNodeStrict(SOAPElement element) {
   950         Node node = (Node)element.getFirstChild();
   951         if (node != null) {
   952             if (node.getNextSibling() == null
   953                 && node.getNodeType() == org.w3c.dom.Node.TEXT_NODE) {
   954                 return node;
   955             } else {
   956                 return null;
   957             }
   958         }
   959         return null;
   960     }
   963     private AttachmentPart getAttachmentPart(String uri) throws SOAPException {
   964         AttachmentPart _part;
   965         try {
   966             if (uri.startsWith("cid:")) {
   967                 // rfc2392
   968                 uri = '<'+uri.substring("cid:".length())+'>';
   970                 MimeHeaders headersToMatch = new MimeHeaders();
   971                 headersToMatch.addHeader(CONTENT_ID, uri);
   973                 Iterator i = this.getAttachments(headersToMatch);
   974                 _part = (i == null) ? null : (AttachmentPart)i.next();
   975             } else {
   976                 // try content-location
   977                 MimeHeaders headersToMatch = new MimeHeaders();
   978                 headersToMatch.addHeader(CONTENT_LOCATION, uri);
   980                 Iterator i = this.getAttachments(headersToMatch);
   981                 _part = (i == null) ? null : (AttachmentPart)i.next();
   982             }
   984             // try  auto-generated JAXRPC CID
   985             if (_part == null) {
   986                 Iterator j = this.getAttachments();
   988                 while (j.hasNext()) {
   989                     AttachmentPart p = (AttachmentPart)j.next();
   990                     String cl = p.getContentId();
   991                     if (cl != null) {
   992                         // obtain the partname
   993                         int eqIndex = cl.indexOf("=");
   994                         if (eqIndex > -1) {
   995                             cl = cl.substring(1, eqIndex);
   996                             if (cl.equalsIgnoreCase(uri)) {
   997                                 _part = p;
   998                                  break;
   999                             }
  1005         } catch (Exception se) {
  1006             log.log(Level.SEVERE, "SAAJ0590.soap.unable.to.locate.attachment", new Object[] {uri});
  1007             throw new SOAPExceptionImpl(se);
  1009         return _part;
  1012     private final InputStream getHeaderBytes()
  1013         throws IOException {
  1014         SOAPPartImpl sp = (SOAPPartImpl) getSOAPPart();
  1015         return sp.getContentAsStream();
  1018     private String convertToSingleLine(String contentType) {
  1019         StringBuffer buffer = new StringBuffer();
  1020         for (int i = 0; i < contentType.length(); i ++) {
  1021             char c = contentType.charAt(i);
  1022             if (c != '\r' && c != '\n' && c != '\t')
  1023                 buffer.append(c);
  1025         return buffer.toString();
  1028     private MimeMultipart getMimeMessage() throws SOAPException {
  1029         try {
  1030             SOAPPartImpl soapPart = (SOAPPartImpl) getSOAPPart();
  1031             MimeBodyPart mimeSoapPart = soapPart.getMimePart();
  1033             /*
  1034              * Get content type from this message instead of soapPart
  1035              * to ensure agreement if soapPart is transcoded (XML <-> FI)
  1036              */
  1037             ContentType soapPartCtype = new ContentType(getExpectedContentType());
  1039             if (!isFastInfoset) {
  1040                 soapPartCtype.setParameter("charset", initCharset());
  1042             mimeSoapPart.setHeader("Content-Type", soapPartCtype.toString());
  1044             MimeMultipart headerAndBody = null;
  1046             if (!switchOffBM && !switchOffLazyAttachment &&
  1047                    (multiPart != null) && !attachmentsInitialized) {
  1048                 headerAndBody = new BMMimeMultipart();
  1049                 headerAndBody.addBodyPart(mimeSoapPart);
  1050                 if (attachments != null) {
  1051                     for (Iterator eachAttachment = attachments.iterator();
  1052                          eachAttachment.hasNext();) {
  1053                         headerAndBody.addBodyPart(
  1054                             ((AttachmentPartImpl) eachAttachment.next())
  1055                                 .getMimePart());
  1058                 InputStream in = ((BMMimeMultipart)multiPart).getInputStream();
  1059                 if (!((BMMimeMultipart)multiPart).lastBodyPartFound() &&
  1060                     !((BMMimeMultipart)multiPart).isEndOfStream()) {
  1061                     ((BMMimeMultipart)headerAndBody).setInputStream(in);
  1062                     ((BMMimeMultipart)headerAndBody).setBoundary(
  1063                         ((BMMimeMultipart)multiPart).getBoundary());
  1064                     ((BMMimeMultipart)headerAndBody).
  1065                         setLazyAttachments(lazyAttachments);
  1068             } else {
  1069                 headerAndBody = new MimeMultipart();
  1070                 headerAndBody.addBodyPart(mimeSoapPart);
  1072                 for (Iterator eachAttachement = getAttachments();
  1073                     eachAttachement.hasNext();
  1074                     ) {
  1075                     headerAndBody.addBodyPart(
  1076                         ((AttachmentPartImpl) eachAttachement.next())
  1077                             .getMimePart());
  1081             ContentType contentType = headerAndBody.getContentType();
  1083             ParameterList l = contentType.getParameterList();
  1085             // set content type depending on SOAP version
  1086             l.set("type", getExpectedContentType());
  1087             l.set("boundary", contentType.getParameter("boundary"));
  1088             ContentType nct = new ContentType("multipart", "related", l);
  1090             headers.setHeader(
  1091                 "Content-Type",
  1092                 convertToSingleLine(nct.toString()));
  1093           // TBD
  1094           //    Set content length MIME header here.
  1096             return headerAndBody;
  1097         } catch (SOAPException ex) {
  1098             throw ex;
  1099         } catch (Throwable ex) {
  1100             log.severe("SAAJ0538.soap.cannot.convert.msg.to.multipart.obj");
  1101             throw new SOAPExceptionImpl(
  1102                 "Unable to convert SOAP message into "
  1103                     + "a MimeMultipart object",
  1104                 ex);
  1108     private String initCharset() {
  1110         String charset = null;
  1112         String[] cts = getMimeHeaders().getHeader("Content-Type");
  1113         if ((cts != null) && (cts[0] != null)) {
  1114             charset = getCharsetString(cts[0]);
  1117         if (charset == null) {
  1118             charset = (String) getProperty(CHARACTER_SET_ENCODING);
  1121         if (charset != null) {
  1122             return charset;
  1125         return "utf-8";
  1128     private String getCharsetString(String s) {
  1129         try {
  1130             int index = s.indexOf(";");
  1131             if(index < 0)
  1132                 return null;
  1133             ParameterList pl = new ParameterList(s.substring(index));
  1134             return pl.get("charset");
  1135         } catch(Exception e) {
  1136             return null;
  1140     public void saveChanges() throws SOAPException {
  1142         // suck in all the data from the attachments and have it
  1143         // ready for writing/sending etc.
  1145         String charset = initCharset();
  1147         /*if (countAttachments() == 0) {*/
  1148         int attachmentCount = (attachments == null) ? 0 : attachments.size();
  1149         if (attachmentCount == 0) {
  1150             if (!switchOffBM && !switchOffLazyAttachment &&
  1151                 !attachmentsInitialized && (multiPart != null)) {
  1152                 // so there might be attachments
  1153                 attachmentCount = 1;
  1157         try {
  1158             if ((attachmentCount == 0) && !hasXOPContent()) {
  1159                 InputStream in;
  1160                 try{
  1161                 /*
  1162                  * Not sure why this is called getHeaderBytes(), but it actually
  1163                  * returns the whole message as a byte stream. This stream could
  1164                  * be either XML of Fast depending on the mode.
  1165                  */
  1166                     in = getHeaderBytes();
  1167                     // no attachments, hence this property can be false
  1168                     this.optimizeAttachmentProcessing = false;
  1169                     if (SOAPPartImpl.lazyContentLength) {
  1170                         inputStreamAfterSaveChanges = in;
  1172                 } catch (IOException ex) {
  1173                     log.severe("SAAJ0539.soap.cannot.get.header.stream");
  1174                     throw new SOAPExceptionImpl(
  1175                             "Unable to get header stream in saveChanges: ",
  1176                             ex);
  1179                 if (in instanceof ByteInputStream) {
  1180                     ByteInputStream bIn = (ByteInputStream)in;
  1181                     messageBytes = bIn.getBytes();
  1182                     messageByteCount = bIn.getCount();
  1185                 setFinalContentType(charset);
  1186                 /*
  1187                 headers.setHeader(
  1188                         "Content-Type",
  1189                         getExpectedContentType() +
  1190                         (isFastInfoset ? "" : "; charset=" + charset));*/
  1191                 if (messageByteCount > 0) {
  1192                     headers.setHeader(
  1193                             "Content-Length",
  1194                             Integer.toString(messageByteCount));
  1196             } else {
  1197                 if(hasXOPContent())
  1198                     mmp = getXOPMessage();
  1199                 else
  1200                     mmp = getMimeMessage();
  1202         } catch (Throwable ex) {
  1203             log.severe("SAAJ0540.soap.err.saving.multipart.msg");
  1204             throw new SOAPExceptionImpl(
  1205                     "Error during saving a multipart message",
  1206                     ex);
  1209         // FIX ME -- SOAP Action replaced by Content-Type optional parameter action
  1210         /*
  1211         if(isCorrectSoapVersion(SOAP1_1_FLAG)) {
  1213             String[] soapAction = headers.getHeader("SOAPAction");
  1215             if (soapAction == null || soapAction.length == 0)
  1216                 headers.setHeader("SOAPAction", "\"\"");
  1219         */
  1221         saved = true;
  1224     private MimeMultipart getXOPMessage() throws SOAPException {
  1225         try {
  1226             MimeMultipart headerAndBody = new MimeMultipart();
  1227             SOAPPartImpl soapPart =  (SOAPPartImpl)getSOAPPart();
  1228             MimeBodyPart mimeSoapPart = soapPart.getMimePart();
  1229             ContentType soapPartCtype =
  1230                 new ContentType("application/xop+xml");
  1231             soapPartCtype.setParameter("type", getExpectedContentType());
  1232             String charset = initCharset();
  1233             soapPartCtype.setParameter("charset", charset);
  1234             mimeSoapPart.setHeader("Content-Type", soapPartCtype.toString());
  1235             headerAndBody.addBodyPart(mimeSoapPart);
  1237             for (Iterator eachAttachement = getAttachments();
  1238                 eachAttachement.hasNext();
  1239                 ) {
  1240                 headerAndBody.addBodyPart(
  1241                     ((AttachmentPartImpl) eachAttachement.next())
  1242                         .getMimePart());
  1245             ContentType contentType = headerAndBody.getContentType();
  1247             ParameterList l = contentType.getParameterList();
  1249             //lets not write start-info for now till we get servlet fix done
  1250             l.set("start-info", getExpectedContentType());//+";charset="+initCharset());
  1252             // set content type depending on SOAP version
  1253             l.set("type", "application/xop+xml");
  1255             if (isCorrectSoapVersion(SOAP1_2_FLAG)) {
  1256                  String action = getAction();
  1257                  if(action != null)
  1258                      l.set("action", action);
  1261             l.set("boundary", contentType.getParameter("boundary"));
  1262             ContentType nct = new ContentType("Multipart", "Related", l);
  1263             headers.setHeader(
  1264                 "Content-Type",
  1265                 convertToSingleLine(nct.toString()));
  1266             // TBD
  1267             //    Set content length MIME header here.
  1269             return headerAndBody;
  1270         } catch (SOAPException ex) {
  1271             throw ex;
  1272         } catch (Throwable ex) {
  1273             log.severe("SAAJ0538.soap.cannot.convert.msg.to.multipart.obj");
  1274             throw new SOAPExceptionImpl(
  1275                 "Unable to convert SOAP message into "
  1276                     + "a MimeMultipart object",
  1277                 ex);
  1282     private boolean hasXOPContent() throws ParseException {
  1283         String type = getContentType();
  1284         if(type == null)
  1285             return false;
  1286         ContentType ct = new ContentType(type);
  1287         //return isMimeMultipartXOPPackage(ct) || isSOAPBodyXOPPackage(ct);
  1288         return isMimeMultipartXOPSoap1_1Package(ct) ||
  1289             isMimeMultipartXOPSoap1_2Package(ct) || isSOAPBodyXOPPackage(ct);
  1293     public void writeTo(OutputStream out) throws SOAPException, IOException {
  1294         if (saveRequired()){
  1295             this.optimizeAttachmentProcessing = true;
  1296             saveChanges();
  1299         if(!optimizeAttachmentProcessing){
  1300             if (SOAPPartImpl.lazyContentLength && messageByteCount <= 0) {
  1301                 byte[] buf = new byte[1024];
  1303                 int length = 0;
  1304                 while( (length = inputStreamAfterSaveChanges.read(buf)) != -1) {
  1305                     out.write(buf,0, length);
  1306                     messageByteCount += length;
  1308                 if (messageByteCount > 0) {
  1309                     headers.setHeader(
  1310                             "Content-Length",
  1311                             Integer.toString(messageByteCount));
  1313             } else {
  1314                 out.write(messageBytes, 0, messageByteCount);
  1317         else{
  1318             try{
  1319                 if(hasXOPContent()){
  1320                     mmp.writeTo(out);
  1321                 }else{
  1322                     mmp.writeTo(out);
  1323                     if (!switchOffBM && !switchOffLazyAttachment &&
  1324                             (multiPart != null) && !attachmentsInitialized) {
  1325                         ((BMMimeMultipart)multiPart).setInputStream(
  1326                                 ((BMMimeMultipart)mmp).getInputStream());
  1329             } catch(Exception ex){
  1330                 log.severe("SAAJ0540.soap.err.saving.multipart.msg");
  1331                 throw new SOAPExceptionImpl(
  1332                         "Error during saving a multipart message",
  1333                         ex);
  1337         if(isCorrectSoapVersion(SOAP1_1_FLAG)) {
  1339             String[] soapAction = headers.getHeader("SOAPAction");
  1341             if (soapAction == null || soapAction.length == 0)
  1342                 headers.setHeader("SOAPAction", "\"\"");
  1346         messageBytes = null;
  1347         needsSave();
  1350     public SOAPBody getSOAPBody() throws SOAPException {
  1351         SOAPBody body = getSOAPPart().getEnvelope().getBody();
  1352         /*if (body == null) {
  1353              throw new SOAPException("No SOAP Body was found in the SOAP Message");
  1354         }*/
  1355         return body;
  1358     public SOAPHeader getSOAPHeader() throws SOAPException {
  1359         SOAPHeader hdr = getSOAPPart().getEnvelope().getHeader();
  1360         /*if (hdr == null) {
  1361             throw new SOAPException("No SOAP Header was found in the SOAP Message");
  1362         }*/
  1363         return hdr;
  1366     private void initializeAllAttachments ()
  1367         throws MessagingException, SOAPException {
  1368         if (switchOffBM || switchOffLazyAttachment) {
  1369             return;
  1372         if (attachmentsInitialized || (multiPart == null)) {
  1373             return;
  1376         if (attachments == null)
  1377             attachments = new FinalArrayList();
  1379         int count = multiPart.getCount();
  1380         for (int i=0; i < count; i++ ) {
  1381             initializeAttachment(multiPart.getBodyPart(i));
  1383         attachmentsInitialized = true;
  1384         //multiPart = null;
  1385         needsSave();
  1388     private void initializeAttachment(MimeBodyPart mbp) throws SOAPException {
  1389         AttachmentPartImpl attachmentPart = new AttachmentPartImpl();
  1390         DataHandler attachmentHandler = mbp.getDataHandler();
  1391         attachmentPart.setDataHandler(attachmentHandler);
  1393         AttachmentPartImpl.copyMimeHeaders(mbp, attachmentPart);
  1394         attachments.add(attachmentPart);
  1397     private void initializeAttachment(MimeMultipart multiPart, int i)
  1398         throws Exception {
  1399         MimeBodyPart currentBodyPart = multiPart.getBodyPart(i);
  1400         AttachmentPartImpl attachmentPart = new AttachmentPartImpl();
  1402         DataHandler attachmentHandler = currentBodyPart.getDataHandler();
  1403         attachmentPart.setDataHandler(attachmentHandler);
  1405         AttachmentPartImpl.copyMimeHeaders(currentBodyPart, attachmentPart);
  1406         addAttachmentPart(attachmentPart);
  1409     private void setMimeHeaders(SOAPPart soapPart,
  1410             MimeBodyPart soapMessagePart) throws Exception {
  1412         // first remove the existing content-type
  1413         soapPart.removeAllMimeHeaders();
  1414         // add everything present in soapMessagePart
  1415         List headers = soapMessagePart.getAllHeaders();
  1416         int sz = headers.size();
  1417         for( int i=0; i<sz; i++ ) {
  1418             Header h = (Header) headers.get(i);
  1419             soapPart.addMimeHeader(h.getName(), h.getValue());
  1423     private void initCharsetProperty(ContentType contentType) {
  1424         String charset = contentType.getParameter("charset");
  1425         if (charset != null) {
  1426             ((SOAPPartImpl) getSOAPPart()).setSourceCharsetEncoding(charset);
  1427             if(!charset.equalsIgnoreCase("utf-8"))
  1428                 setProperty(CHARACTER_SET_ENCODING, charset);
  1432     public void setLazyAttachments(boolean flag) {
  1433         lazyAttachments = flag;

mercurial