alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Java example source code file (MessageImpl.java)

This example Java source code file (MessageImpl.java) is included in the alvinalexander.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Learn more about this Java project at its project page.

Java - Java tags/keywords

attachmentpartimpl, content-type, contenttype, inputstream, iterator, log, logging, messageimpl, mimebodypart, mimeheaders, mimemultipart, object, runtimeexception, soapexceptionimpl, soappartimpl, string, util

The MessageImpl.java Java example source code

/*
 * Copyright (c) 1997, 2012, 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.transform.Source;
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;

    // 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);

    }

    private void init(MimeHeaders headers, int stat, final ContentType contentType, final InputStream in) 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());
            }

            if ((stat & PLAIN_XML_FLAG) != 0) {
                if (isFastInfoset) {
                    getSOAPPart().setContent(
                        FastInfosetReflection.FastInfosetSource_new(in));
                } else {
                    initCharsetProperty(contentType);
                    getSOAPPart().setContent(new StreamSource(in));
                }
            }
            else if ((stat & MIME_MULTIPART_FLAG) != 0) {
                DataSource ds = new DataSource() {
                    public InputStream getInputStream() {
                        return in;
                    }

                    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);
                            }
                        }
                    }
                }

                if (soapPartInputStream == null && soapMessagePart != 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 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;
    }

}

Other Java examples (source code examples)

Here is a short list of links related to this Java MessageImpl.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.