FileDocCategorySizeDatePackage
MultiPartRelatedInputStream.javaAPI DocApache Axis 1.425238Sat Apr 22 18:57:28 BST 2006org.apache.axis.attachments

MultiPartRelatedInputStream

public class MultiPartRelatedInputStream extends MultiPartInputStream
This simulates the multipart stream.
author
Rick Rineholt

Fields Summary
protected static Log
log
Field log
public static final String
MIME_MULTIPART_RELATED
Field MIME_MULTIPART_RELATED
protected HashMap
parts
Field parts
protected LinkedList
orderedParts
Field orderedParts
protected int
rootPartLength
Field rootPartLength
protected boolean
closed
Field closed
protected boolean
eos
Field eos
protected org.apache.axis.attachments.BoundaryDelimitedStream
boundaryDelimitedStream
Field boundaryDelimitedStream
protected InputStream
soapStream
Field soapStream
protected InputStream
soapStreamBDS
Field soapStreamBDS
protected byte[]
boundary
Field boundary
protected ByteArrayInputStream
cachedSOAPEnvelope
Field cachedSOAPEnvelope
protected String
contentLocation
Field contentLocation
protected String
contentId
Field contentId
private static final int
MAX_CACHED
Field MAX_CACHED
protected static final String[]
READ_ALL
Field READ_ALL
Constructors Summary
public MultiPartRelatedInputStream(String contentType, InputStream stream)
Create a new Multipart stream.

param
contentType the string that holds the contentType
param
stream the true input stream from where the source
throws
org.apache.axis.AxisFault if the stream could not be created


                                                
     
               
              

        super(null);    // don't cache this stream.

        if(!(stream instanceof BufferedInputStream)) {
            stream = new BufferedInputStream(stream);
        }
        
        try {

            // First find the start and boundary parameters. There are real weird rules regard what
            // can be in real headers what needs to be escaped etc  let mail parse it.
            javax.mail.internet.ContentType ct =
                    new javax.mail.internet.ContentType(contentType);
            String rootPartContentId =
                    ct.getParameter("start");       // Get the root part content.

            if (rootPartContentId != null) {
                rootPartContentId = rootPartContentId.trim();

                if (rootPartContentId.startsWith("<")) {
                    rootPartContentId = rootPartContentId.substring(1);
                }

                if (rootPartContentId.endsWith(">")) {
                    rootPartContentId = rootPartContentId.substring(0,
                            rootPartContentId.length() - 1);
                }

            }

            if(ct.getParameter("boundary") != null) {
                String boundaryStr =
                        "--"
                        + ct.getParameter(
                                "boundary");    // The boundary with -- add as always the case.


                // if start is null then the first attachment is the rootpart
                // First read the start boundary -- this is done with brute force since the servlet may swallow the crlf between headers.
                // after this we use the more efficient boundarydelimeted stream.  There should never be any data here anyway.
                byte[][] boundaryMarker = new byte[2][boundaryStr.length() + 2];

                IOUtils.readFully(stream, boundaryMarker[0]);

                boundary = (boundaryStr + "\r\n").getBytes("US-ASCII");

                int current = 0;

                // This just goes brute force one byte at a time to find the first boundary.
                // in most cases this just a crlf.
                for (boolean found = false; !found; ++current) {
                    if (!(found =
                            java.util.Arrays.equals(boundaryMarker[current & 0x1],
                                    boundary))) {
                        System.arraycopy(boundaryMarker[current & 0x1], 1,
                                boundaryMarker[(current + 1) & 0x1], 0,
                                boundaryMarker[0].length - 1);

                        if (stream.read(
                                boundaryMarker[(current + 1) & 0x1],
                                boundaryMarker[0].length - 1, 1) < 1) {
                            throw new org.apache.axis.AxisFault(
                                    Messages.getMessage(
                                            "mimeErrorNoBoundary", new String(boundary)));
                        }
                    }
                }

                // after the first boundary each boundary will have a cr lf at the beginning since after the data in any part there
                // is a cr lf added to put the boundary at the begining of a line.
                boundaryStr = "\r\n" + boundaryStr;
                boundary = boundaryStr.getBytes("US-ASCII");
            } else {
                // Since boundary is not specified, we try to find one.
                for (boolean found = false; !found;) {
                    boundary= readLine(stream);
                    if( boundary == null)
                        throw new org.apache.axis.AxisFault(
                                Messages.getMessage(
                                        "mimeErrorNoBoundary", "--"));
                     found = boundary.length >4  && boundary[2] == '-" &&  boundary[3]== '-";
                }
              }

            // create the boundary delmited stream.
            boundaryDelimitedStream =
                    new org.apache.axis.attachments.BoundaryDelimitedStream(stream,
                            boundary, 1024);

            // Now read through all potential streams until we have found the root part.
            String contentTransferEncoding = null;

            do {
                contentId = null;
                contentLocation = null;
                contentTransferEncoding = null;

                // Read this attachments headers from the stream.
                javax.mail.internet.InternetHeaders headers =
                        new javax.mail.internet.InternetHeaders(
                                boundaryDelimitedStream);

                // Use java mail utility to read through the headers.
                contentId = headers.getHeader(HTTPConstants.HEADER_CONTENT_ID,
                        null);

                // Clean up the headers and remove any < >
                if (contentId != null) {
                    contentId = contentId.trim();

                    if (contentId.startsWith("<")) {
                        contentId = contentId.substring(1);
                    }

                    if (contentId.endsWith(">")) {
                        contentId = contentId.substring(0, contentId.length()
                                - 1);
                    }

                    contentId = contentId.trim();

                  //  if (!contentId.startsWith("cid:")) {
                  //      contentId =
                  //              "cid:"
                  //              + contentId;        // make sure its identified as cid
                  //  }
                }

                contentLocation =
                        headers.getHeader(HTTPConstants.HEADER_CONTENT_LOCATION,
                                null);

                if (contentLocation != null) {
                    contentLocation = contentLocation.trim();

                    if (contentLocation.startsWith("<")) {
                        contentLocation = contentLocation.substring(1);
                    }

                    if (contentLocation.endsWith(">")) {
                        contentLocation = contentLocation.substring(
                                0, contentLocation.length() - 1);
                    }

                    contentLocation = contentLocation.trim();
                }

                contentType =
                        headers.getHeader(HTTPConstants.HEADER_CONTENT_TYPE, null);

                if (contentType != null) {
                    contentType = contentType.trim();
                }

                contentTransferEncoding = headers.getHeader(
                        HTTPConstants.HEADER_CONTENT_TRANSFER_ENCODING, null);

                if (contentTransferEncoding != null) {
                    contentTransferEncoding = contentTransferEncoding.trim();
                }

                java.io.InputStream decodedStream = boundaryDelimitedStream;

                if ((contentTransferEncoding != null)
                        && (0 != contentTransferEncoding.length())) {
                    decodedStream = MimeUtility.decode(decodedStream,
                            contentTransferEncoding);
                }

                if ((rootPartContentId != null) && !rootPartContentId.equals(
                        contentId)) {    // This is a part that has come in prior to the root part. Need to buffer it up.
                    javax.activation.DataHandler dh =
                            new javax.activation.DataHandler(
                                    new org.apache.axis.attachments.ManagedMemoryDataSource(
                                            decodedStream, MAX_CACHED, contentType, true));
                    AttachmentPart ap = new AttachmentPart(dh);

                    if (contentId != null) {
                        ap.setMimeHeader(HTTPConstants.HEADER_CONTENT_ID,
                                contentId);
                    }

                    if (contentLocation != null) {
                        ap.setMimeHeader(HTTPConstants.HEADER_CONTENT_LOCATION,
                                contentLocation);
                    }

                    for (java.util.Enumeration en =
                            headers.getNonMatchingHeaders(new String[]{
                                HTTPConstants.HEADER_CONTENT_ID,
                                HTTPConstants.HEADER_CONTENT_LOCATION,
                                HTTPConstants.HEADER_CONTENT_TYPE}); en.hasMoreElements();) {
                        javax.mail.Header header =
                                (javax.mail.Header) en.nextElement();
                        String name = header.getName();
                        String value = header.getValue();

                        if ((name != null) && (value != null)) {
                            name = name.trim();

                            if (name.length() != 0) {
                                ap.addMimeHeader(name, value);
                            }
                        }
                    }

                    addPart(contentId, contentLocation, ap);

                    boundaryDelimitedStream =
                            boundaryDelimitedStream.getNextStream();    // Gets the next stream.
                }
            } while ((null != boundaryDelimitedStream)
                    && (rootPartContentId != null)
                    && !rootPartContentId.equals(contentId));

            if (boundaryDelimitedStream == null) {
                throw new org.apache.axis.AxisFault(
                        Messages.getMessage("noRoot", rootPartContentId));
            }

            soapStreamBDS = boundaryDelimitedStream;

            if ((contentTransferEncoding != null)
                    && (0 != contentTransferEncoding.length())) {
                soapStream = MimeUtility.decode(boundaryDelimitedStream,
                        contentTransferEncoding);
            } else {
                soapStream =
                        boundaryDelimitedStream;    // This should be the SOAP part
            }

            // Read from the input stream all attachments prior to the root part.
        } catch (javax.mail.internet.ParseException e) {
            throw new org.apache.axis.AxisFault(
                    Messages.getMessage("mimeErrorParsing", e.getMessage()));
        } catch (java.io.IOException e) {
            throw new org.apache.axis.AxisFault(
                    Messages.getMessage("readError", e.getMessage()));
        } catch (javax.mail.MessagingException e) {
            throw new org.apache.axis.AxisFault(
                    Messages.getMessage("readError", e.getMessage()));
        }
    
Methods Summary
protected voidaddPart(java.lang.String contentId, java.lang.String locationId, AttachmentPart ap)
Add an AttachmentPart together with its content and location IDs.

param
contentId the content ID
param
locationId the location ID
param
ap the AttachmentPart


        if ((contentId != null) && (contentId.trim().length() != 0)) {
            parts.put(contentId, ap);
        }

        if ((locationId != null) && (locationId.trim().length() != 0)) {
            parts.put(locationId, ap);
        }

        orderedParts.add(ap);
    
public intavailable()

        return (closed || eos) ? 0 : soapStream.available();
    
public voidclose()


        closed = true;

        soapStream.close();
    
public org.apache.axis.PartgetAttachmentByReference(java.lang.String[] id)


        // First see if we have read it in yet.
        Part ret = null;

        for (int i = id.length - 1; (ret == null) && (i > -1); --i) {
            ret = (AttachmentPart) parts.get(id[i]);
        }

        if (null == ret) {
            ret = readTillFound(id);
        }

        log.debug(Messages.getMessage("return02",
                "getAttachmentByReference(\"" + id
                + "\"", ((ret == null)
                ? "null"
                : ret.toString())));

        return ret;
    
public java.util.CollectiongetAttachments()


        readAll();

        return orderedParts;
    
public java.lang.StringgetContentId()

        return contentId;
    
public java.lang.StringgetContentLocation()

        return contentLocation;
    
public intread(byte[] b, int off, int len)


        if (closed) {
            throw new java.io.IOException(Messages.getMessage("streamClosed"));
        }

        if (eos) {
            return -1;
        }

        int read = soapStream.read(b, off, len);

        if (read < 0) {
            eos = true;
        }

        return read;
    
public intread(byte[] b)

        return read(b, 0, b.length);
    
public intread()


        if (closed) {
            throw new java.io.IOException(Messages.getMessage("streamClosed"));
        }

        if (eos) {
            return -1;
        }

        int ret = soapStream.read();

        if (ret < 0) {
            eos = true;
        }

        return ret;
    
protected voidreadAll()
Read all data.

throws
org.apache.axis.AxisFault if there was a problem reading all the data

    // Shouldn't never match

                                    
         
        readTillFound(READ_ALL);
    
private final byte[]readLine(java.io.InputStream is)


        java.io.ByteArrayOutputStream input = new java.io.ByteArrayOutputStream(1024);
        int c = 0;
        input.write('\r");
        input.write('\n");

        int next = -1;
        for (;c != -1;) {
            c = -1 != next ? next :  is.read();
            next = -1;
            switch (c) {
                case -1:
                break;
                case '\r":
                    next = is.read();
                    if(next == '\n")  //found a line.
                        return input.toByteArray();
                    if(next == -1)  return null;
                    //fall through
                default:
                    input.write((byte)c);
                break;
            }
        }
        //even if there is stuff in buffer if EOF then this can't be a boundary.
        return null;
    
protected org.apache.axis.PartreadTillFound(java.lang.String[] id)
This will read streams in till the one that is needed is found.

param
id id is the stream being sought.
return
the part for the id
throws
org.apache.axis.AxisFault


        if (boundaryDelimitedStream == null) {
            return null;    // The whole stream has been consumed already
        }

        Part ret = null;

        try {
            if (soapStreamBDS
                    == boundaryDelimitedStream) {    // Still on the SOAP stream.
                if (!eos) {    // The SOAP packet has not been fully read yet. Need to store it away.
                    java.io.ByteArrayOutputStream soapdata =
                            new java.io.ByteArrayOutputStream(1024 * 8);
                    byte[] buf =
                            new byte[1024 * 16];
                    int byteread = 0;

                    do {
                        byteread = soapStream.read(buf);

                        if (byteread > 0) {
                            soapdata.write(buf, 0, byteread);
                        }
                    } while (byteread > -1);

                    soapdata.close();

                    soapStream = new java.io.ByteArrayInputStream(
                            soapdata.toByteArray());
                }

                boundaryDelimitedStream =
                        boundaryDelimitedStream.getNextStream();
            }

            // Now start searching for the data.
            if (null != boundaryDelimitedStream) {
                do {
                    String contentType = null;
                    String contentId = null;
                    String contentTransferEncoding = null;
                    String contentLocation = null;

                    // Read this attachments headers from the stream.
                    javax.mail.internet.InternetHeaders headers =
                            new javax.mail.internet.InternetHeaders(
                                    boundaryDelimitedStream);

                    contentId = headers.getHeader("Content-Id", null);

                    if (contentId != null) {
                        contentId = contentId.trim();

                        if (contentId.startsWith("<")) {
                            contentId = contentId.substring(1);
                        }

                        if (contentId.endsWith(">")) {
                            contentId =
                                    contentId.substring(0, contentId.length() - 1);
                        }

                     //   if (!contentId.startsWith("cid:")) {
                     //       contentId = "cid:" + contentId;
                     //   }

                        contentId = contentId.trim();
                    }

                    contentType =
                            headers.getHeader(HTTPConstants.HEADER_CONTENT_TYPE,
                                    null);

                    if (contentType != null) {
                        contentType = contentType.trim();
                    }

                    contentLocation =
                            headers.getHeader(HTTPConstants.HEADER_CONTENT_LOCATION,
                                    null);

                    if (contentLocation != null) {
                        contentLocation = contentLocation.trim();
                    }

                    contentTransferEncoding = headers.getHeader(
                            HTTPConstants.HEADER_CONTENT_TRANSFER_ENCODING, null);

                    if (contentTransferEncoding != null) {
                        contentTransferEncoding =
                                contentTransferEncoding.trim();
                    }

                    java.io.InputStream decodedStream = boundaryDelimitedStream;

                    if ((contentTransferEncoding != null)
                            && (0 != contentTransferEncoding.length())) {
                        decodedStream =
                                MimeUtility.decode(decodedStream,
                                        contentTransferEncoding);
                    }

                    ManagedMemoryDataSource source = new ManagedMemoryDataSource(
                                                        decodedStream, ManagedMemoryDataSource.MAX_MEMORY_DISK_CACHED, contentType, true);
                    DataHandler dh = new DataHandler(source);
                    AttachmentPart ap = new AttachmentPart(dh);

                    if (contentId != null) {
                        ap.setMimeHeader(HTTPConstants.HEADER_CONTENT_ID,
                                contentId);
                    }

                    if (contentLocation != null) {
                        ap.setMimeHeader(HTTPConstants.HEADER_CONTENT_LOCATION,
                                contentLocation);
                    }

                    for (java.util.Enumeration en =
                            headers.getNonMatchingHeaders(new String[]{
                                HTTPConstants.HEADER_CONTENT_ID,
                                HTTPConstants.HEADER_CONTENT_LOCATION,
                                HTTPConstants.HEADER_CONTENT_TYPE}); en.hasMoreElements();) {
                        javax.mail.Header header =
                                (javax.mail.Header) en.nextElement();
                        String name = header.getName();
                        String value = header.getValue();

                        if ((name != null) && (value != null)) {
                            name = name.trim();

                            if (name.length() != 0) {
                                ap.addMimeHeader(name, value);
                            }
                        }
                    }

                    addPart(contentId, contentLocation, ap);

                    for (int i = id.length - 1; (ret == null) && (i > -1);
                         --i) {
                        if ((contentId != null) && id[i].equals(
                                contentId)) {    // This is the part being sought
                            ret = ap;
                        } else if ((contentLocation != null)
                                && id[i].equals(contentLocation)) {
                            ret = ap;
                        }
                    }

                    boundaryDelimitedStream =
                            boundaryDelimitedStream.getNextStream();
                } while ((null == ret) && (null != boundaryDelimitedStream));
            }
        } catch (Exception e) {
            throw org.apache.axis.AxisFault.makeFault(e);
        }

        return ret;