src/share/jaxws_classes/com/sun/xml/internal/ws/encoding/MimeMultipartParser.java

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

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

merge

     1 /*
     2  * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     8  * particular file as subject to the "Classpath" exception as provided
     9  * by Oracle in the LICENSE file that accompanied this code.
    10  *
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    14  * version 2 for more details (a copy is included in the LICENSE file that
    15  * accompanied this code).
    16  *
    17  * You should have received a copy of the GNU General Public License version
    18  * 2 along with this work; if not, write to the Free Software Foundation,
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    20  *
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    22  * or visit www.oracle.com if you need additional information or have any
    23  * questions.
    24  */
    26 package com.sun.xml.internal.ws.encoding;
    28 import com.sun.istack.internal.NotNull;
    29 import com.sun.istack.internal.Nullable;
    30 import com.sun.xml.internal.ws.api.message.Attachment;
    31 import com.sun.xml.internal.ws.api.message.AttachmentEx;
    32 import com.sun.xml.internal.ws.developer.StreamingAttachmentFeature;
    33 import com.sun.xml.internal.ws.developer.StreamingDataHandler;
    34 import com.sun.xml.internal.ws.util.ByteArrayBuffer;
    35 import com.sun.xml.internal.ws.util.ByteArrayDataSource;
    37 import com.sun.xml.internal.org.jvnet.mimepull.Header;
    38 import com.sun.xml.internal.org.jvnet.mimepull.MIMEMessage;
    39 import com.sun.xml.internal.org.jvnet.mimepull.MIMEPart;
    41 import javax.activation.DataHandler;
    42 import javax.xml.soap.SOAPException;
    43 import javax.xml.soap.SOAPMessage;
    44 import javax.xml.transform.Source;
    45 import javax.xml.transform.stream.StreamSource;
    46 import javax.xml.ws.WebServiceException;
    47 import java.io.ByteArrayInputStream;
    48 import java.io.IOException;
    49 import java.io.InputStream;
    50 import java.io.OutputStream;
    51 import java.util.HashMap;
    52 import java.util.Iterator;
    53 import java.util.List;
    54 import java.util.Map;
    55 import java.util.logging.Level;
    56 import java.util.logging.Logger;
    58 /**
    59  * Parses Mime multipart message into primary part and attachment parts. It
    60  * parses the stream lazily as and when required.
    61  *
    62  * @author Vivek Pandey
    63  * @author Jitendra Kotamraju
    64  */
    65 public final class MimeMultipartParser {
    67     private final String start;
    68     private final MIMEMessage message;
    69     private Attachment root;
    70     private ContentTypeImpl contentType;
    72     // Attachments without root part
    73     private final Map<String, Attachment> attachments = new HashMap<String, Attachment>();
    75     private boolean gotAll;
    77     public MimeMultipartParser(InputStream in, String cType, StreamingAttachmentFeature feature) {
    78         this.contentType = new ContentTypeImpl(cType);
    79 //        ContentType ct = new ContentType(cType);
    80 //        String boundary = ct.getParameter("boundary");
    81         String boundary = contentType.getBoundary();
    82         if (boundary == null || boundary.equals("")) {
    83             throw new WebServiceException("MIME boundary parameter not found" + contentType);
    84         }
    85         message = (feature != null)
    86                 ? new MIMEMessage(in, boundary, feature.getConfig())
    87                 : new MIMEMessage(in, boundary);
    88         // Strip <...> from root part's Content-ID
    89 //        String st = ct.getParameter("start");
    90         String st = contentType.getRootId();
    91         if (st != null && st.length() > 2 && st.charAt(0) == '<' && st.charAt(st.length()-1) == '>') {
    92             st = st.substring(1, st.length()-1);
    93         }
    94         start = st;
    95     }
    97     /**
    98      * Parses the stream and returns the root part. If start parameter is
    99      * present in Content-Type, it is used to determine the root part, otherwise
   100      * root part is the first part.
   101      *
   102      * @return StreamAttachment for root part
   103      *         null if root part cannot be found
   104      *
   105      */
   106     public @Nullable Attachment getRootPart() {
   107         if (root == null) {
   108             root = new PartAttachment((start != null) ? message.getPart(start) : message.getPart(0));
   109         }
   110         return root;
   111     }
   113     /**
   114      * Parses the entire stream and returns all MIME parts except root MIME part.
   115      *
   116      * @return Map<String, StreamAttachment> for all attachment parts
   117      */
   118     public @NotNull Map<String, Attachment> getAttachmentParts() {
   119         if (!gotAll) {
   120             MIMEPart rootPart = (start != null) ? message.getPart(start) : message.getPart(0);
   121             List<MIMEPart> parts = message.getAttachments();
   122             for(MIMEPart part : parts) {
   123                 if (part != rootPart) {
   124                     String cid = part.getContentId();
   125                     if (!attachments.containsKey(cid)) {
   126                         PartAttachment attach = new PartAttachment(part);
   127                         attachments.put(attach.getContentId(), attach);
   128                     }
   129                 }
   130             }
   131             gotAll = true;
   132         }
   133         return attachments;
   134     }
   136     /**
   137      * This method can be called to get a matching MIME attachment part for the
   138      * given contentId. It parses the stream until it finds a matching part.
   139      *
   140      * @return StreamAttachment attachment for contentId
   141      *         null if there is no attachment for contentId
   142      */
   143     public @Nullable Attachment getAttachmentPart(String contentId) throws IOException {
   144         //first see if this attachment is already parsed, if so return it
   145         Attachment attach = attachments.get(contentId);
   146         if (attach == null) {
   147             MIMEPart part = message.getPart(contentId);
   148             attach = new PartAttachment(part);
   149             attachments.put(contentId, attach);
   150         }
   151         return attach;
   152     }
   154     static class PartAttachment implements AttachmentEx {
   156         final MIMEPart part;
   157         byte[] buf;
   158         private StreamingDataHandler streamingDataHandler;
   160         PartAttachment(MIMEPart part) {
   161             this.part = part;
   162         }
   164         public @NotNull @Override String getContentId() {
   165             return part.getContentId();
   166         }
   168         public @NotNull @Override String getContentType() {
   169             return part.getContentType();
   170         }
   172         @Override
   173         public byte[] asByteArray() {
   174             if (buf == null) {
   175                 ByteArrayBuffer baf = new ByteArrayBuffer();
   176                 try {
   177                     baf.write(part.readOnce());
   178                 } catch(IOException ioe) {
   179                     throw new WebServiceException(ioe);
   180                 } finally {
   181                     if (baf != null) {
   182                         try {
   183                             baf.close();
   184                         } catch (IOException ex) {
   185                             Logger.getLogger(MimeMultipartParser.class.getName()).log(Level.FINE, null, ex);
   186                         }
   187                     }
   188                 }
   189                 buf = baf.toByteArray();
   190             }
   191             return buf;
   192         }
   194         @Override
   195         public DataHandler asDataHandler() {
   196             if (streamingDataHandler == null) {
   197                 streamingDataHandler = (buf != null)
   198                     ? new DataSourceStreamingDataHandler(new ByteArrayDataSource(buf,getContentType()))
   199                     : new MIMEPartStreamingDataHandler(part);
   200             }
   201             return streamingDataHandler;
   202         }
   204         @Override
   205         public Source asSource() {
   206             return (buf != null)
   207                 ? new StreamSource(new ByteArrayInputStream(buf))
   208                 : new StreamSource(part.read());
   209         }
   211         @Override
   212         public InputStream asInputStream() {
   213             return (buf != null)
   214                 ? new ByteArrayInputStream(buf) : part.read();
   215         }
   217         @Override
   218         public void writeTo(OutputStream os) throws IOException {
   219             if (buf != null) {
   220                 os.write(buf);
   221             } else {
   222                 InputStream in = part.read();
   223                 byte[] temp = new byte[8192];
   224                 int len;
   225                 while((len=in.read(temp)) != -1) {
   226                     os.write(temp, 0, len);
   227                 }
   228                 in.close();
   229             }
   230         }
   232         @Override
   233         public void writeTo(SOAPMessage saaj) throws SOAPException {
   234             saaj.createAttachmentPart().setDataHandler(asDataHandler());
   235         }
   237         // AttachmentEx methods begin here
   238         @Override
   239         public Iterator<MimeHeader> getMimeHeaders() {
   240             final Iterator<? extends Header> ih = part.getAllHeaders()
   241                     .iterator();
   242             return new Iterator<MimeHeader>() {
   243                 @Override
   244                 public boolean hasNext() {
   245                     return ih.hasNext();
   246                 }
   248                 @Override
   249                 public MimeHeader next() {
   250                     final Header hdr = ih.next();
   251                     return new AttachmentEx.MimeHeader() {
   252                         @Override
   253                         public String getValue() {
   254                             return hdr.getValue();
   255                         }
   256                         @Override
   257                         public String getName() {
   258                             return hdr.getName();
   259                         }
   260                     };
   261                 }
   263                 @Override
   264                 public void remove() {
   265                     throw new UnsupportedOperationException();
   266                 }
   267             };
   268         }
   269     }
   271     public ContentTypeImpl getContentType() {
   272         return contentType;
   273     }
   275 }

mercurial