--- a/jaxws/src/java.xml.soap/share/classes/com/sun/xml/internal/messaging/saaj/soap/MessageImpl.java Mon Jan 12 11:46:43 2015 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1486 +0,0 @@
-/*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package com.sun.xml.internal.messaging.saaj.soap;
-
-import java.io.*;
-import java.util.*;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import javax.activation.DataHandler;
-import javax.activation.DataSource;
-import javax.xml.soap.*;
-import javax.xml.stream.XMLStreamReader;
-import javax.xml.transform.Source;
-import javax.xml.transform.stax.StAXSource;
-import javax.xml.transform.stream.StreamSource;
-
-import com.sun.xml.internal.messaging.saaj.packaging.mime.Header;
-import com.sun.xml.internal.messaging.saaj.packaging.mime.internet.*;
-import com.sun.xml.internal.messaging.saaj.packaging.mime.util.*;
-import com.sun.xml.internal.messaging.saaj.packaging.mime.MessagingException;
-
-import com.sun.xml.internal.messaging.saaj.SOAPExceptionImpl;
-import com.sun.xml.internal.messaging.saaj.soap.impl.EnvelopeImpl;
-import com.sun.xml.internal.messaging.saaj.util.*;
-import com.sun.xml.internal.org.jvnet.mimepull.MIMEPart;
-
-/**
- * The message implementation for SOAP messages with
- * attachments. Messages for specific profiles will likely extend this
- * MessageImpl class and add more value for that particular profile.
- *
- * @author Anil Vijendran (akv@eng.sun.com)
- * @author Rajiv Mordani (rajiv.mordani@sun.com)
- * @author Manveen Kaur (manveen.kaur@sun.com)
- */
-
-public abstract class MessageImpl
- extends SOAPMessage
- implements SOAPConstants {
-
-
- public static final String CONTENT_ID = "Content-ID";
- public static final String CONTENT_LOCATION = "Content-Location";
-
- protected static final Logger log =
- Logger.getLogger(LogDomainConstants.SOAP_DOMAIN,
- "com.sun.xml.internal.messaging.saaj.soap.LocalStrings");
-
- protected static final int PLAIN_XML_FLAG = 1; // 00001
- protected static final int MIME_MULTIPART_FLAG = 2; // 00010
- protected static final int SOAP1_1_FLAG = 4; // 00100
- protected static final int SOAP1_2_FLAG = 8; // 01000
- //protected static final int MIME_MULTIPART_XOP_FLAG = 14; // 01110
- protected static final int MIME_MULTIPART_XOP_SOAP1_1_FLAG = 6; // 00110
- protected static final int MIME_MULTIPART_XOP_SOAP1_2_FLAG = 10; // 01010
- protected static final int XOP_FLAG = 13; // 01101
- protected static final int FI_ENCODED_FLAG = 16; // 10000
-
- protected MimeHeaders headers;
- protected ContentType contentType;
- protected SOAPPartImpl soapPartImpl;
- protected FinalArrayList attachments;
- protected boolean saved = false;
- protected byte[] messageBytes;
- protected int messageByteCount;
- protected HashMap properties = new HashMap();
-
- // used for lazy attachment initialization
- protected MimeMultipart multiPart = null;
- protected boolean attachmentsInitialized = false;
-
- /**
- * True if this part is encoded using Fast Infoset.
- * MIME -> application/fastinfoset
- */
- protected boolean isFastInfoset = false;
-
- /**
- * True if the Accept header of this message includes
- * application/fastinfoset
- */
- protected boolean acceptFastInfoset = false;
-
- protected MimeMultipart mmp = null;
-
- // if attachments are present, don't read the entire message in byte stream in saveTo()
- private boolean optimizeAttachmentProcessing = true;
-
- private InputStream inputStreamAfterSaveChanges = null;
-
- public static final String LAZY_SOAP_BODY_PARSING = "saaj.lazy.soap.body";
-
- // switch back to old MimeMultipart incase of problem
- private static boolean switchOffBM = false;
- private static boolean switchOffLazyAttachment = false;
- private static boolean useMimePull = false;
-
- static {
- String s = SAAJUtil.getSystemProperty("saaj.mime.optimization");
- if ((s != null) && s.equals("false")) {
- switchOffBM = true;
- }
- s = SAAJUtil.getSystemProperty("saaj.lazy.mime.optimization");
- if ((s != null) && s.equals("false")) {
- switchOffLazyAttachment = true;
- }
- useMimePull = SAAJUtil.getSystemBoolean("saaj.use.mimepull");
-
- }
-
- //property to indicate optimized serialization for lazy attachments
- private boolean lazyAttachments = false;
-
- // most of the times, Content-Types are already all lower cased.
- // String.toLowerCase() works faster in this case, so even if you
- // are only doing one comparison, it pays off to use String.toLowerCase()
- // than String.equalsIgnoreCase(). When you do more than one comparison,
- // the benefits of String.toLowerCase() dominates.
- //
- //
- // for FI,
- // use application/fastinfoset for SOAP 1.1
- // use application/soap+fastinfoset for SOAP 1.2
- // to speed up comparisons, test methods always use lower cases.
-
- /**
- * @param primary
- * must be all lower case
- * @param sub
- * must be all lower case
- */
- private static boolean isSoap1_1Type(String primary, String sub) {
- return primary.equalsIgnoreCase("text") && sub.equalsIgnoreCase("xml")
- || primary.equalsIgnoreCase("text") && sub.equalsIgnoreCase("xml-soap")
- || primary.equals("application")
- && sub.equals("fastinfoset");
- }
-
- /**
- * @param type
- * must be all lower case
- */
- private static boolean isEqualToSoap1_1Type(String type) {
- return type.startsWith("text/xml") ||
- type.startsWith("application/fastinfoset");
- }
-
- /**
- * @param primary
- * must be all lower case
- * @param sub
- * must be all lower case
- */
- private static boolean isSoap1_2Type(String primary, String sub) {
- return primary.equals("application")
- && (sub.equals("soap+xml")
- || sub.equals("soap+fastinfoset"));
- }
-
- /**
- * @param type
- * must be all lower case
- */
- private static boolean isEqualToSoap1_2Type(String type) {
- return type.startsWith("application/soap+xml") ||
- type.startsWith("application/soap+fastinfoset");
- }
-
- /**
- * Construct a new message. This will be invoked before message
- * sends.
- */
- protected MessageImpl() {
- this(false, false);
- attachmentsInitialized = true;
- }
-
- /**
- * Construct a new message. This will be invoked before message
- * sends.
- */
- protected MessageImpl(boolean isFastInfoset, boolean acceptFastInfoset) {
- this.isFastInfoset = isFastInfoset;
- this.acceptFastInfoset = acceptFastInfoset;
-
- headers = new MimeHeaders();
- headers.setHeader("Accept", getExpectedAcceptHeader());
- contentType = new ContentType();
- }
-
- /**
- * Shallow copy.
- */
- protected MessageImpl(SOAPMessage msg) {
- if (!(msg instanceof MessageImpl)) {
- // don't know how to handle this.
- }
- MessageImpl src = (MessageImpl) msg;
- this.headers = src.headers;
- this.soapPartImpl = src.soapPartImpl;
- this.attachments = src.attachments;
- this.saved = src.saved;
- this.messageBytes = src.messageBytes;
- this.messageByteCount = src.messageByteCount;
- this.properties = src.properties;
- this.contentType = src.contentType;
- }
-
- /**
- * @param stat
- * the mask value obtained from {@link #identifyContentType(ContentType)}
- */
- protected static boolean isSoap1_1Content(int stat) {
- return (stat & SOAP1_1_FLAG) != 0;
- }
-
- /**
- * @param stat
- * the mask value obtained from {@link #identifyContentType(ContentType)}
- */
- protected static boolean isSoap1_2Content(int stat) {
- return (stat & SOAP1_2_FLAG) != 0;
- }
-
- private static boolean isMimeMultipartXOPSoap1_2Package(ContentType contentType) {
- String type = contentType.getParameter("type");
- if (type == null) {
- return false;
- }
- type = type.toLowerCase();
- if (!type.startsWith("application/xop+xml")) {
- return false;
- }
- String startinfo = contentType.getParameter("start-info");
- if (startinfo == null) {
- return false;
- }
- startinfo = startinfo.toLowerCase();
- return isEqualToSoap1_2Type(startinfo);
- }
-
-
- //private static boolean isMimeMultipartXOPPackage(ContentType contentType) {
- private static boolean isMimeMultipartXOPSoap1_1Package(ContentType contentType) {
- String type = contentType.getParameter("type");
- if(type==null)
- return false;
-
- type = type.toLowerCase();
- if(!type.startsWith("application/xop+xml"))
- return false;
-
- String startinfo = contentType.getParameter("start-info");
- if(startinfo == null)
- return false;
- startinfo = startinfo.toLowerCase();
- return isEqualToSoap1_1Type(startinfo);
- }
-
- private static boolean isSOAPBodyXOPPackage(ContentType contentType){
- String primary = contentType.getPrimaryType();
- String sub = contentType.getSubType();
-
- if (primary.equalsIgnoreCase("application")) {
- if (sub.equalsIgnoreCase("xop+xml")) {
- String type = getTypeParameter(contentType);
- return isEqualToSoap1_2Type(type) || isEqualToSoap1_1Type(type);
- }
- }
- return false;
- }
-
- /**
- * Construct a message from an input stream. When messages are
- * received, there's two parts -- the transport headers and the
- * message content in a transport specific stream.
- */
- protected MessageImpl(MimeHeaders headers, final InputStream in)
- throws SOAPExceptionImpl {
- contentType = parseContentType(headers);
- init(headers,identifyContentType(contentType),contentType,in);
- }
-
- private static ContentType parseContentType(MimeHeaders headers) throws SOAPExceptionImpl {
- final String ct;
- if (headers != null)
- ct = getContentType(headers);
- else {
- log.severe("SAAJ0550.soap.null.headers");
- throw new SOAPExceptionImpl("Cannot create message: " +
- "Headers can't be null");
- }
-
- if (ct == null) {
- log.severe("SAAJ0532.soap.no.Content-Type");
- throw new SOAPExceptionImpl("Absent Content-Type");
- }
- try {
- return new ContentType(ct);
- } catch (Throwable ex) {
- log.severe("SAAJ0535.soap.cannot.internalize.message");
- throw new SOAPExceptionImpl("Unable to internalize message", ex);
- }
- }
-
- /**
- * Construct a message from an input stream. When messages are
- * received, there's two parts -- the transport headers and the
- * message content in a transport specific stream.
- *
- * @param contentType
- * The parsed content type header from the headers variable.
- * This is redundant parameter, but it avoids reparsing this header again.
- * @param stat
- * The result of {@link #identifyContentType(ContentType)} over
- * the contentType parameter. This redundant parameter, but it avoids
- * recomputing this information again.
- */
- protected MessageImpl(MimeHeaders headers, final ContentType contentType, int stat, final InputStream in) throws SOAPExceptionImpl {
- init(headers, stat, contentType, in);
-
- }
-
- public MessageImpl(MimeHeaders headers, ContentType ct, int stat,
- XMLStreamReader reader) throws SOAPExceptionImpl {
- init(headers, stat, ct, reader);
- }
-
- private void init(MimeHeaders headers, int stat, final ContentType contentType, final Object input) throws SOAPExceptionImpl {
- this.headers = headers;
-
- try {
-
- // Set isFastInfoset/acceptFastInfoset flag based on MIME type
- if ((stat & FI_ENCODED_FLAG) > 0) {
- isFastInfoset = acceptFastInfoset = true;
- }
-
- // If necessary, inspect Accept header to set acceptFastInfoset
- if (!isFastInfoset) {
- String[] values = headers.getHeader("Accept");
- if (values != null) {
- for (int i = 0; i < values.length; i++) {
- StringTokenizer st = new StringTokenizer(values[i], ",");
- while (st.hasMoreTokens()) {
- final String token = st.nextToken().trim();
- if (token.equalsIgnoreCase("application/fastinfoset") ||
- token.equalsIgnoreCase("application/soap+fastinfoset")) {
- acceptFastInfoset = true;
- break;
- }
- }
- }
- }
- }
-
- if (!isCorrectSoapVersion(stat)) {
- log.log(
- Level.SEVERE,
- "SAAJ0533.soap.incorrect.Content-Type",
- new String[] {
- contentType.toString(),
- getExpectedContentType()});
- throw new SOAPVersionMismatchException(
- "Cannot create message: incorrect content-type for SOAP version. Got: "
- + contentType
- + " Expected: "
- + getExpectedContentType());
- }
- InputStream in = null;
- XMLStreamReader rdr = null;
- if (input instanceof InputStream) {
- in = (InputStream) input;
- } else {
- //is a StAX reader
- rdr = (XMLStreamReader) input;
- }
- if ((stat & PLAIN_XML_FLAG) != 0) {
- if (in != null) {
- if (isFastInfoset) {
- getSOAPPart().setContent(
- FastInfosetReflection.FastInfosetSource_new(in));
- } else {
- initCharsetProperty(contentType);
- getSOAPPart().setContent(new StreamSource(in));
- }
- } else {
- //is a StAX reader
- if (isFastInfoset) {
- //need to get FI stax reader
- } else {
- initCharsetProperty(contentType);
- getSOAPPart().setContent(new StAXSource(rdr));
- }
- }
- }
- else if ((stat & MIME_MULTIPART_FLAG) != 0 && in == null) {
- //only parse multipart in the inputstream case
- //in stax reader case, we would be given the attachments separately
- getSOAPPart().setContent(new StAXSource(rdr));
- } else if ((stat & MIME_MULTIPART_FLAG) != 0) {
- final InputStream finalIn = in;
- DataSource ds = new DataSource() {
- public InputStream getInputStream() {
- return finalIn;
- }
-
- public OutputStream getOutputStream() {
- return null;
- }
-
- public String getContentType() {
- return contentType.toString();
- }
-
- public String getName() {
- return "";
- }
- };
-
- multiPart = null;
- if (useMimePull) {
- multiPart = new MimePullMultipart(ds,contentType);
- } else if (switchOffBM) {
- multiPart = new MimeMultipart(ds,contentType);
- } else {
- multiPart = new BMMimeMultipart(ds,contentType);
- }
-
- String startParam = contentType.getParameter("start");
- MimeBodyPart soapMessagePart = null;
- InputStream soapPartInputStream = null;
- String contentID = null;
- String contentIDNoAngle = null;
- if (switchOffBM || switchOffLazyAttachment) {
- if(startParam == null) {
- soapMessagePart = multiPart.getBodyPart(0);
- for (int i = 1; i < multiPart.getCount(); i++) {
- initializeAttachment(multiPart, i);
- }
- } else {
- soapMessagePart = multiPart.getBodyPart(startParam);
- for (int i = 0; i < multiPart.getCount(); i++) {
- contentID = multiPart.getBodyPart(i).getContentID();
- // Old versions of AXIS2 put angle brackets around the content
- // id but not the start param
- contentIDNoAngle = (contentID != null) ?
- contentID.replaceFirst("^<", "").replaceFirst(">$", "") : null;
- if(!startParam.equals(contentID) && !startParam.equals(contentIDNoAngle))
- initializeAttachment(multiPart, i);
- }
- }
- } else {
- if (useMimePull) {
- MimePullMultipart mpMultipart = (MimePullMultipart)multiPart;
- MIMEPart sp = mpMultipart.readAndReturnSOAPPart();
- soapMessagePart = new MimeBodyPart(sp);
- soapPartInputStream = sp.readOnce();
- } else {
- BMMimeMultipart bmMultipart =
- (BMMimeMultipart) multiPart;
- InputStream stream = bmMultipart.initStream();
-
- SharedInputStream sin = null;
- if (stream instanceof SharedInputStream) {
- sin = (SharedInputStream) stream;
- }
-
- String boundary = "--" +
- contentType.getParameter("boundary");
- byte[] bndbytes = ASCIIUtility.getBytes(boundary);
- if (startParam == null) {
- soapMessagePart =
- bmMultipart.getNextPart(stream, bndbytes, sin);
- bmMultipart.removeBodyPart(soapMessagePart);
- } else {
- MimeBodyPart bp = null;
- try {
- while (!startParam.equals(contentID) && !startParam.equals(contentIDNoAngle)) {
- bp = bmMultipart.getNextPart(
- stream, bndbytes, sin);
- contentID = bp.getContentID();
- // Old versions of AXIS2 put angle brackets around the content
- // id but not the start param
- contentIDNoAngle = (contentID != null) ?
- contentID.replaceFirst("^<", "").replaceFirst(">$", "") : null;
- }
- soapMessagePart = bp;
- bmMultipart.removeBodyPart(bp);
- } catch (Exception e) {
- throw new SOAPExceptionImpl(e);
- }
- }
- }
- }
-
- // findbugs correctly points out that we'd NPE instantiating
- // the ContentType (just below here) if soapMessagePart were
- // null. Hence are better off throwing a controlled exception
- // at this point if it is null.
- if (soapMessagePart == null) {
- log.severe("SAAJ0510.soap.cannot.create.envelope");
- throw new SOAPExceptionImpl(
- "Unable to create envelope from given source: SOAP part not found");
- }
-
- if (soapPartInputStream == null) {
- soapPartInputStream = soapMessagePart.getInputStream();
- }
-
- ContentType soapPartCType = new ContentType(
- soapMessagePart.getContentType());
- initCharsetProperty(soapPartCType);
- String baseType = soapPartCType.getBaseType().toLowerCase();
- if(!(isEqualToSoap1_1Type(baseType)
- || isEqualToSoap1_2Type(baseType)
- || isSOAPBodyXOPPackage(soapPartCType))) {
- log.log(Level.SEVERE,
- "SAAJ0549.soap.part.invalid.Content-Type",
- new Object[] {baseType});
- throw new SOAPExceptionImpl(
- "Bad Content-Type for SOAP Part : " +
- baseType);
- }
-
- SOAPPart soapPart = getSOAPPart();
- setMimeHeaders(soapPart, soapMessagePart);
- soapPart.setContent(isFastInfoset ?
- (Source) FastInfosetReflection.FastInfosetSource_new(
- soapPartInputStream) :
- (Source) new StreamSource(soapPartInputStream));
- } else {
- log.severe("SAAJ0534.soap.unknown.Content-Type");
- throw new SOAPExceptionImpl("Unrecognized Content-Type");
- }
- } catch (Throwable ex) {
- log.severe("SAAJ0535.soap.cannot.internalize.message");
- throw new SOAPExceptionImpl("Unable to internalize message", ex);
- }
- needsSave();
- }
-
- public boolean isFastInfoset() {
- return isFastInfoset;
- }
-
- public boolean acceptFastInfoset() {
- return acceptFastInfoset;
- }
-
- public void setIsFastInfoset(boolean value) {
- if (value != isFastInfoset) {
- isFastInfoset = value;
- if (isFastInfoset) {
- acceptFastInfoset = true;
- }
- saved = false; // ensure transcoding if necessary
- }
- }
-
- public boolean isLazySoapBodyParsing() {
- Object lazyParsingProp = getProperty(LAZY_SOAP_BODY_PARSING);
- if (lazyParsingProp == null) return false;
- if (lazyParsingProp instanceof Boolean) {
- return ((Boolean) lazyParsingProp).booleanValue();
- } else {
- return Boolean.valueOf(lazyParsingProp.toString());
- }
- }
- public Object getProperty(String property) {
- return (String) properties.get(property);
- }
-
- public void setProperty(String property, Object value) {
- verify(property, value);
- properties.put(property, value);
- }
-
- private void verify(String property, Object value) {
- if (property.equalsIgnoreCase(SOAPMessage.WRITE_XML_DECLARATION)) {
- if (!("true".equals(value) || "false".equals(value)))
- throw new RuntimeException(
- property + " must have value false or true");
-
- try {
- EnvelopeImpl env = (EnvelopeImpl) getSOAPPart().getEnvelope();
- if ("true".equalsIgnoreCase((String)value)) {
- env.setOmitXmlDecl("no");
- } else if ("false".equalsIgnoreCase((String)value)) {
- env.setOmitXmlDecl("yes");
- }
- } catch (Exception e) {
- log.log(Level.SEVERE, "SAAJ0591.soap.exception.in.set.property",
- new Object[] {e.getMessage(), "javax.xml.soap.write-xml-declaration"});
- throw new RuntimeException(e);
- }
- return;
- }
-
- if (property.equalsIgnoreCase(SOAPMessage.CHARACTER_SET_ENCODING)) {
- try {
- ((EnvelopeImpl) getSOAPPart().getEnvelope()).setCharsetEncoding((String)value);
- } catch (Exception e) {
- log.log(Level.SEVERE, "SAAJ0591.soap.exception.in.set.property",
- new Object[] {e.getMessage(), "javax.xml.soap.character-set-encoding"});
- throw new RuntimeException(e);
- }
- }
- }
-
- protected abstract boolean isCorrectSoapVersion(int contentTypeId);
-
- protected abstract String getExpectedContentType();
- protected abstract String getExpectedAcceptHeader();
-
- /**
- * Sniffs the Content-Type header so that we can determine how to process.
- *
- * <p>
- * In the absence of type attribute we assume it to be text/xml.
- * That would mean we're easy on accepting the message and
- * generate the correct thing (as the SWA spec also specifies
- * that the type parameter should always be text/xml)
- *
- * @return
- * combination of flags, such as PLAIN_XML_CODE and MIME_MULTIPART_CODE.
- */
- // SOAP1.2 allow SOAP1.2 content type
- static int identifyContentType(ContentType ct)
- throws SOAPExceptionImpl {
- // TBD
- // Is there anything else we need to verify here?
-
- String primary = ct.getPrimaryType().toLowerCase();
- String sub = ct.getSubType().toLowerCase();
-
- if (primary.equals("multipart")) {
- if (sub.equals("related")) {
- String type = getTypeParameter(ct);
- if (isEqualToSoap1_1Type(type)) {
- return (type.equals("application/fastinfoset") ?
- FI_ENCODED_FLAG : 0) | MIME_MULTIPART_FLAG | SOAP1_1_FLAG;
- }
- else if (isEqualToSoap1_2Type(type)) {
- return (type.equals("application/soap+fastinfoset") ?
- FI_ENCODED_FLAG : 0) | MIME_MULTIPART_FLAG | SOAP1_2_FLAG;
- /*} else if (isMimeMultipartXOPPackage(ct)) {
- return MIME_MULTIPART_XOP_FLAG;*/
- } else if (isMimeMultipartXOPSoap1_1Package(ct)) {
- return MIME_MULTIPART_XOP_SOAP1_1_FLAG;
- } else if (isMimeMultipartXOPSoap1_2Package(ct)) {
- return MIME_MULTIPART_XOP_SOAP1_2_FLAG;
- } else {
- log.severe("SAAJ0536.soap.content-type.mustbe.multipart");
- throw new SOAPExceptionImpl(
- "Content-Type needs to be Multipart/Related "
- + "and with \"type=text/xml\" "
- + "or \"type=application/soap+xml\"");
- }
- } else {
- log.severe("SAAJ0537.soap.invalid.content-type");
- throw new SOAPExceptionImpl(
- "Invalid Content-Type: " + primary + '/' + sub);
- }
- }
- else if (isSoap1_1Type(primary, sub)) {
- return (primary.equalsIgnoreCase("application")
- && sub.equalsIgnoreCase("fastinfoset") ?
- FI_ENCODED_FLAG : 0)
- | PLAIN_XML_FLAG | SOAP1_1_FLAG;
- }
- else if (isSoap1_2Type(primary, sub)) {
- return (primary.equalsIgnoreCase("application")
- && sub.equalsIgnoreCase("soap+fastinfoset") ?
- FI_ENCODED_FLAG : 0)
- | PLAIN_XML_FLAG | SOAP1_2_FLAG;
- } else if(isSOAPBodyXOPPackage(ct)){
- return XOP_FLAG;
- } else {
- log.severe("SAAJ0537.soap.invalid.content-type");
- throw new SOAPExceptionImpl(
- "Invalid Content-Type:"
- + primary
- + '/'
- + sub
- + ". Is this an error message instead of a SOAP response?");
- }
- }
-
- /**
- * Obtains the type parameter of the Content-Type header. Defaults to "text/xml".
- */
- private static String getTypeParameter(ContentType contentType) {
- String p = contentType.getParameter("type");
- if(p!=null)
- return p.toLowerCase();
- else
- return "text/xml";
- }
-
- public MimeHeaders getMimeHeaders() {
- return this.headers;
- }
-
- final static String getContentType(MimeHeaders headers) {
- String[] values = headers.getHeader("Content-Type");
- if (values == null)
- return null;
- else
- return values[0];
- }
-
- /*
- * Get the complete ContentType value along with optional parameters.
- */
- public String getContentType() {
- return getContentType(this.headers);
- }
-
- public void setContentType(String type) {
- headers.setHeader("Content-Type", type);
- needsSave();
- }
-
- private ContentType contentType() {
- ContentType ct = null;
- try {
- String currentContent = getContentType();
- if (currentContent == null) {
- return this.contentType;
- }
- ct = new ContentType(currentContent);
- } catch (Exception e) {
- // what to do here?
- }
- return ct;
- }
-
- /*
- * Return the MIME type string, without the parameters.
- */
- public String getBaseType() {
- return contentType().getBaseType();
- }
-
- public void setBaseType(String type) {
- ContentType ct = contentType();
- ct.setParameter("type", type);
- headers.setHeader("Content-Type", ct.toString());
- needsSave();
- }
-
- public String getAction() {
- return contentType().getParameter("action");
- }
-
- public void setAction(String action) {
- ContentType ct = contentType();
- ct.setParameter("action", action);
- headers.setHeader("Content-Type", ct.toString());
- needsSave();
- }
-
- public String getCharset() {
- return contentType().getParameter("charset");
- }
-
- public void setCharset(String charset) {
- ContentType ct = contentType();
- ct.setParameter("charset", charset);
- headers.setHeader("Content-Type", ct.toString());
- needsSave();
- }
-
- /**
- * All write methods (i.e setters) should call this method in
- * order to make sure that a save is necessary since the state
- * has been modified.
- */
- private final void needsSave() {
- saved = false;
- }
-
- public boolean saveRequired() {
- return saved != true;
- }
-
- public String getContentDescription() {
- String[] values = headers.getHeader("Content-Description");
- if (values != null && values.length > 0)
- return values[0];
- return null;
- }
-
- public void setContentDescription(String description) {
- headers.setHeader("Content-Description", description);
- needsSave();
- }
-
- public abstract SOAPPart getSOAPPart();
-
- public void removeAllAttachments() {
- try {
- initializeAllAttachments();
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
-
- if (attachments != null) {
- attachments.clear();
- needsSave();
- }
- }
-
- public int countAttachments() {
- try {
- initializeAllAttachments();
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- if (attachments != null)
- return attachments.size();
- return 0;
- }
-
- public void addAttachmentPart(AttachmentPart attachment) {
- try {
- initializeAllAttachments();
- this.optimizeAttachmentProcessing = true;
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- if (attachments == null)
- attachments = new FinalArrayList();
-
- attachments.add(attachment);
-
- needsSave();
- }
-
- static private final Iterator nullIter = Collections.EMPTY_LIST.iterator();
-
- public Iterator getAttachments() {
- try {
- initializeAllAttachments();
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- if (attachments == null)
- return nullIter;
- return attachments.iterator();
- }
-
- private void setFinalContentType(String charset) {
- ContentType ct = contentType();
- if (ct == null) {
- ct = new ContentType();
- }
- String[] split = getExpectedContentType().split("/");
- ct.setPrimaryType(split[0]);
- ct.setSubType(split[1]);
- ct.setParameter("charset", charset);
- headers.setHeader("Content-Type", ct.toString());
- }
-
- private class MimeMatchingIterator implements Iterator {
- public MimeMatchingIterator(MimeHeaders headers) {
- this.headers = headers;
- this.iter = attachments.iterator();
- }
-
- private Iterator iter;
- private MimeHeaders headers;
- private Object nextAttachment;
-
- public boolean hasNext() {
- if (nextAttachment == null)
- nextAttachment = nextMatch();
- return nextAttachment != null;
- }
-
- public Object next() {
- if (nextAttachment != null) {
- Object ret = nextAttachment;
- nextAttachment = null;
- return ret;
- }
-
- if (hasNext())
- return nextAttachment;
-
- return null;
- }
-
- Object nextMatch() {
- while (iter.hasNext()) {
- AttachmentPartImpl ap = (AttachmentPartImpl) iter.next();
- if (ap.hasAllHeaders(headers))
- return ap;
- }
- return null;
- }
-
- public void remove() {
- iter.remove();
- }
- }
-
- public Iterator getAttachments(MimeHeaders headers) {
- try {
- initializeAllAttachments();
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- if (attachments == null)
- return nullIter;
-
- return new MimeMatchingIterator(headers);
- }
-
- public void removeAttachments(MimeHeaders headers) {
- try {
- initializeAllAttachments();
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- if (attachments == null)
- return ;
-
- Iterator it = new MimeMatchingIterator(headers);
- while (it.hasNext()) {
- int index = attachments.indexOf(it.next());
- attachments.set(index, null);
- }
- FinalArrayList f = new FinalArrayList();
- for (int i = 0; i < attachments.size(); i++) {
- if (attachments.get(i) != null) {
- f.add(attachments.get(i));
- }
- }
- attachments = f;
- // needsSave();
- }
-
- public AttachmentPart createAttachmentPart() {
- return new AttachmentPartImpl();
- }
-
- public AttachmentPart getAttachment(SOAPElement element)
- throws SOAPException {
- try {
- initializeAllAttachments();
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- String uri;
- String hrefAttr = element.getAttribute("href");
- if ("".equals(hrefAttr)) {
- Node node = getValueNodeStrict(element);
- String swaRef = null;
- if (node != null) {
- swaRef = node.getValue();
- }
- if (swaRef == null || "".equals(swaRef)) {
- return null;
- } else {
- uri = swaRef;
- }
- } else {
- uri = hrefAttr;
- }
- return getAttachmentPart(uri);
- }
-
- private Node getValueNodeStrict(SOAPElement element) {
- Node node = (Node)element.getFirstChild();
- if (node != null) {
- if (node.getNextSibling() == null
- && node.getNodeType() == org.w3c.dom.Node.TEXT_NODE) {
- return node;
- } else {
- return null;
- }
- }
- return null;
- }
-
-
- private AttachmentPart getAttachmentPart(String uri) throws SOAPException {
- AttachmentPart _part;
- try {
- if (uri.startsWith("cid:")) {
- // rfc2392
- uri = '<'+uri.substring("cid:".length())+'>';
-
- MimeHeaders headersToMatch = new MimeHeaders();
- headersToMatch.addHeader(CONTENT_ID, uri);
-
- Iterator i = this.getAttachments(headersToMatch);
- _part = (i == null) ? null : (AttachmentPart)i.next();
- } else {
- // try content-location
- MimeHeaders headersToMatch = new MimeHeaders();
- headersToMatch.addHeader(CONTENT_LOCATION, uri);
-
- Iterator i = this.getAttachments(headersToMatch);
- _part = (i == null) ? null : (AttachmentPart)i.next();
- }
-
- // try auto-generated JAXRPC CID
- if (_part == null) {
- Iterator j = this.getAttachments();
-
- while (j.hasNext()) {
- AttachmentPart p = (AttachmentPart)j.next();
- String cl = p.getContentId();
- if (cl != null) {
- // obtain the partname
- int eqIndex = cl.indexOf("=");
- if (eqIndex > -1) {
- cl = cl.substring(1, eqIndex);
- if (cl.equalsIgnoreCase(uri)) {
- _part = p;
- break;
- }
- }
- }
- }
- }
-
- } catch (Exception se) {
- log.log(Level.SEVERE, "SAAJ0590.soap.unable.to.locate.attachment", new Object[] {uri});
- throw new SOAPExceptionImpl(se);
- }
- return _part;
- }
-
- private final InputStream getHeaderBytes()
- throws IOException {
- SOAPPartImpl sp = (SOAPPartImpl) getSOAPPart();
- return sp.getContentAsStream();
- }
-
- private String convertToSingleLine(String contentType) {
- StringBuffer buffer = new StringBuffer();
- for (int i = 0; i < contentType.length(); i ++) {
- char c = contentType.charAt(i);
- if (c != '\r' && c != '\n' && c != '\t')
- buffer.append(c);
- }
- return buffer.toString();
- }
-
- private MimeMultipart getMimeMessage() throws SOAPException {
- try {
- SOAPPartImpl soapPart = (SOAPPartImpl) getSOAPPart();
- MimeBodyPart mimeSoapPart = soapPart.getMimePart();
-
- /*
- * Get content type from this message instead of soapPart
- * to ensure agreement if soapPart is transcoded (XML <-> FI)
- */
- ContentType soapPartCtype = new ContentType(getExpectedContentType());
-
- if (!isFastInfoset) {
- soapPartCtype.setParameter("charset", initCharset());
- }
- mimeSoapPart.setHeader("Content-Type", soapPartCtype.toString());
-
- MimeMultipart headerAndBody = null;
-
- if (!switchOffBM && !switchOffLazyAttachment &&
- (multiPart != null) && !attachmentsInitialized) {
- headerAndBody = new BMMimeMultipart();
- headerAndBody.addBodyPart(mimeSoapPart);
- if (attachments != null) {
- for (Iterator eachAttachment = attachments.iterator();
- eachAttachment.hasNext();) {
- headerAndBody.addBodyPart(
- ((AttachmentPartImpl) eachAttachment.next())
- .getMimePart());
- }
- }
- InputStream in = ((BMMimeMultipart)multiPart).getInputStream();
- if (!((BMMimeMultipart)multiPart).lastBodyPartFound() &&
- !((BMMimeMultipart)multiPart).isEndOfStream()) {
- ((BMMimeMultipart)headerAndBody).setInputStream(in);
- ((BMMimeMultipart)headerAndBody).setBoundary(
- ((BMMimeMultipart)multiPart).getBoundary());
- ((BMMimeMultipart)headerAndBody).
- setLazyAttachments(lazyAttachments);
- }
-
- } else {
- headerAndBody = new MimeMultipart();
- headerAndBody.addBodyPart(mimeSoapPart);
-
- for (Iterator eachAttachement = getAttachments();
- eachAttachement.hasNext();
- ) {
- headerAndBody.addBodyPart(
- ((AttachmentPartImpl) eachAttachement.next())
- .getMimePart());
- }
- }
-
- ContentType contentType = headerAndBody.getContentType();
-
- ParameterList l = contentType.getParameterList();
-
- // set content type depending on SOAP version
- l.set("type", getExpectedContentType());
- l.set("boundary", contentType.getParameter("boundary"));
- ContentType nct = new ContentType("multipart", "related", l);
-
- headers.setHeader(
- "Content-Type",
- convertToSingleLine(nct.toString()));
- // TBD
- // Set content length MIME header here.
-
- return headerAndBody;
- } catch (SOAPException ex) {
- throw ex;
- } catch (Throwable ex) {
- log.severe("SAAJ0538.soap.cannot.convert.msg.to.multipart.obj");
- throw new SOAPExceptionImpl(
- "Unable to convert SOAP message into "
- + "a MimeMultipart object",
- ex);
- }
- }
-
- private String initCharset() {
-
- String charset = null;
-
- String[] cts = getMimeHeaders().getHeader("Content-Type");
- if ((cts != null) && (cts[0] != null)) {
- charset = getCharsetString(cts[0]);
- }
-
- if (charset == null) {
- charset = (String) getProperty(CHARACTER_SET_ENCODING);
- }
-
- if (charset != null) {
- return charset;
- }
-
- return "utf-8";
- }
-
- private String getCharsetString(String s) {
- try {
- int index = s.indexOf(";");
- if(index < 0)
- return null;
- ParameterList pl = new ParameterList(s.substring(index));
- return pl.get("charset");
- } catch(Exception e) {
- return null;
- }
- }
-
- public void saveChanges() throws SOAPException {
-
- // suck in all the data from the attachments and have it
- // ready for writing/sending etc.
-
- String charset = initCharset();
-
- /*if (countAttachments() == 0) {*/
- int attachmentCount = (attachments == null) ? 0 : attachments.size();
- if (attachmentCount == 0) {
- if (!switchOffBM && !switchOffLazyAttachment &&
- !attachmentsInitialized && (multiPart != null)) {
- // so there might be attachments
- attachmentCount = 1;
- }
- }
-
- try {
- if ((attachmentCount == 0) && !hasXOPContent()) {
- InputStream in;
- try{
- /*
- * Not sure why this is called getHeaderBytes(), but it actually
- * returns the whole message as a byte stream. This stream could
- * be either XML of Fast depending on the mode.
- */
- in = getHeaderBytes();
- // no attachments, hence this property can be false
- this.optimizeAttachmentProcessing = false;
- if (SOAPPartImpl.lazyContentLength) {
- inputStreamAfterSaveChanges = in;
- }
- } catch (IOException ex) {
- log.severe("SAAJ0539.soap.cannot.get.header.stream");
- throw new SOAPExceptionImpl(
- "Unable to get header stream in saveChanges: ",
- ex);
- }
-
- if (in instanceof ByteInputStream) {
- ByteInputStream bIn = (ByteInputStream)in;
- messageBytes = bIn.getBytes();
- messageByteCount = bIn.getCount();
- }
-
- setFinalContentType(charset);
- /*
- headers.setHeader(
- "Content-Type",
- getExpectedContentType() +
- (isFastInfoset ? "" : "; charset=" + charset));*/
- if (messageByteCount > 0) {
- headers.setHeader(
- "Content-Length",
- Integer.toString(messageByteCount));
- }
- } else {
- if(hasXOPContent())
- mmp = getXOPMessage();
- else
- mmp = getMimeMessage();
- }
- } catch (Throwable ex) {
- log.severe("SAAJ0540.soap.err.saving.multipart.msg");
- throw new SOAPExceptionImpl(
- "Error during saving a multipart message",
- ex);
- }
-
- // FIX ME -- SOAP Action replaced by Content-Type optional parameter action
- /*
- if(isCorrectSoapVersion(SOAP1_1_FLAG)) {
-
- String[] soapAction = headers.getHeader("SOAPAction");
-
- if (soapAction == null || soapAction.length == 0)
- headers.setHeader("SOAPAction", "\"\"");
-
- }
- */
-
- saved = true;
- }
-
- private MimeMultipart getXOPMessage() throws SOAPException {
- try {
- MimeMultipart headerAndBody = new MimeMultipart();
- SOAPPartImpl soapPart = (SOAPPartImpl)getSOAPPart();
- MimeBodyPart mimeSoapPart = soapPart.getMimePart();
- ContentType soapPartCtype =
- new ContentType("application/xop+xml");
- soapPartCtype.setParameter("type", getExpectedContentType());
- String charset = initCharset();
- soapPartCtype.setParameter("charset", charset);
- mimeSoapPart.setHeader("Content-Type", soapPartCtype.toString());
- headerAndBody.addBodyPart(mimeSoapPart);
-
- for (Iterator eachAttachement = getAttachments();
- eachAttachement.hasNext();
- ) {
- headerAndBody.addBodyPart(
- ((AttachmentPartImpl) eachAttachement.next())
- .getMimePart());
- }
-
- ContentType contentType = headerAndBody.getContentType();
-
- ParameterList l = contentType.getParameterList();
-
- //lets not write start-info for now till we get servlet fix done
- l.set("start-info", getExpectedContentType());//+";charset="+initCharset());
-
- // set content type depending on SOAP version
- l.set("type", "application/xop+xml");
-
- if (isCorrectSoapVersion(SOAP1_2_FLAG)) {
- String action = getAction();
- if(action != null)
- l.set("action", action);
- }
-
- l.set("boundary", contentType.getParameter("boundary"));
- ContentType nct = new ContentType("Multipart", "Related", l);
- headers.setHeader(
- "Content-Type",
- convertToSingleLine(nct.toString()));
- // TBD
- // Set content length MIME header here.
-
- return headerAndBody;
- } catch (SOAPException ex) {
- throw ex;
- } catch (Throwable ex) {
- log.severe("SAAJ0538.soap.cannot.convert.msg.to.multipart.obj");
- throw new SOAPExceptionImpl(
- "Unable to convert SOAP message into "
- + "a MimeMultipart object",
- ex);
- }
-
- }
-
- private boolean hasXOPContent() throws ParseException {
- String type = getContentType();
- if(type == null)
- return false;
- ContentType ct = new ContentType(type);
- //return isMimeMultipartXOPPackage(ct) || isSOAPBodyXOPPackage(ct);
- return isMimeMultipartXOPSoap1_1Package(ct) ||
- isMimeMultipartXOPSoap1_2Package(ct) || isSOAPBodyXOPPackage(ct);
-
- }
-
- public void writeTo(OutputStream out) throws SOAPException, IOException {
- if (saveRequired()){
- this.optimizeAttachmentProcessing = true;
- saveChanges();
- }
-
- if(!optimizeAttachmentProcessing){
- if (SOAPPartImpl.lazyContentLength && messageByteCount <= 0) {
- byte[] buf = new byte[1024];
-
- int length = 0;
- while( (length = inputStreamAfterSaveChanges.read(buf)) != -1) {
- out.write(buf,0, length);
- messageByteCount += length;
- }
- if (messageByteCount > 0) {
- headers.setHeader(
- "Content-Length",
- Integer.toString(messageByteCount));
- }
- } else {
- out.write(messageBytes, 0, messageByteCount);
- }
- }
- else{
- try{
- if(hasXOPContent()){
- mmp.writeTo(out);
- }else{
- mmp.writeTo(out);
- if (!switchOffBM && !switchOffLazyAttachment &&
- (multiPart != null) && !attachmentsInitialized) {
- ((BMMimeMultipart)multiPart).setInputStream(
- ((BMMimeMultipart)mmp).getInputStream());
- }
- }
- } catch(Exception ex){
- log.severe("SAAJ0540.soap.err.saving.multipart.msg");
- throw new SOAPExceptionImpl(
- "Error during saving a multipart message",
- ex);
- }
- }
-
- if(isCorrectSoapVersion(SOAP1_1_FLAG)) {
-
- String[] soapAction = headers.getHeader("SOAPAction");
-
- if (soapAction == null || soapAction.length == 0)
- headers.setHeader("SOAPAction", "\"\"");
-
- }
-
- messageBytes = null;
- needsSave();
- }
-
- public SOAPBody getSOAPBody() throws SOAPException {
- SOAPBody body = getSOAPPart().getEnvelope().getBody();
- /*if (body == null) {
- throw new SOAPException("No SOAP Body was found in the SOAP Message");
- }*/
- return body;
- }
-
- public SOAPHeader getSOAPHeader() throws SOAPException {
- SOAPHeader hdr = getSOAPPart().getEnvelope().getHeader();
- /*if (hdr == null) {
- throw new SOAPException("No SOAP Header was found in the SOAP Message");
- }*/
- return hdr;
- }
-
- private void initializeAllAttachments ()
- throws MessagingException, SOAPException {
- if (switchOffBM || switchOffLazyAttachment) {
- return;
- }
-
- if (attachmentsInitialized || (multiPart == null)) {
- return;
- }
-
- if (attachments == null)
- attachments = new FinalArrayList();
-
- int count = multiPart.getCount();
- for (int i=0; i < count; i++ ) {
- initializeAttachment(multiPart.getBodyPart(i));
- }
- attachmentsInitialized = true;
- //multiPart = null;
- needsSave();
- }
-
- private void initializeAttachment(MimeBodyPart mbp) throws SOAPException {
- AttachmentPartImpl attachmentPart = new AttachmentPartImpl();
- DataHandler attachmentHandler = mbp.getDataHandler();
- attachmentPart.setDataHandler(attachmentHandler);
-
- AttachmentPartImpl.copyMimeHeaders(mbp, attachmentPart);
- attachments.add(attachmentPart);
- }
-
- private void initializeAttachment(MimeMultipart multiPart, int i)
- throws Exception {
- MimeBodyPart currentBodyPart = multiPart.getBodyPart(i);
- AttachmentPartImpl attachmentPart = new AttachmentPartImpl();
-
- DataHandler attachmentHandler = currentBodyPart.getDataHandler();
- attachmentPart.setDataHandler(attachmentHandler);
-
- AttachmentPartImpl.copyMimeHeaders(currentBodyPart, attachmentPart);
- addAttachmentPart(attachmentPart);
- }
-
- private void setMimeHeaders(SOAPPart soapPart,
- MimeBodyPart soapMessagePart) throws Exception {
-
- // first remove the existing content-type
- soapPart.removeAllMimeHeaders();
- // add everything present in soapMessagePart
- List headers = soapMessagePart.getAllHeaders();
- int sz = headers.size();
- for( int i=0; i<sz; i++ ) {
- Header h = (Header) headers.get(i);
- soapPart.addMimeHeader(h.getName(), h.getValue());
- }
- }
-
- private void initCharsetProperty(ContentType contentType) {
- String charset = contentType.getParameter("charset");
- if (charset != null) {
- ((SOAPPartImpl) getSOAPPart()).setSourceCharsetEncoding(charset);
- if(!charset.equalsIgnoreCase("utf-8"))
- setProperty(CHARACTER_SET_ENCODING, charset);
- }
- }
-
- public void setLazyAttachments(boolean flag) {
- lazyAttachments = flag;
- }
-
-}