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

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

author
aoqi
date
Thu, 31 Aug 2017 15:18:52 +0800
changeset 637
9c07ef4934dd
parent 494
2fcd3ddb57a6
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.xml.internal.ws.api.SOAPVersion;
    29 import com.sun.xml.internal.ws.api.WSFeatureList;
    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.api.message.Message;
    33 import com.sun.xml.internal.ws.api.message.Packet;
    34 import com.sun.xml.internal.ws.api.pipe.Codec;
    35 import com.sun.xml.internal.ws.api.pipe.ContentType;
    36 import com.sun.xml.internal.ws.developer.StreamingAttachmentFeature;
    38 import java.io.IOException;
    39 import java.io.InputStream;
    40 import java.io.OutputStream;
    41 import java.nio.channels.ReadableByteChannel;
    42 import java.util.Iterator;
    43 import java.util.UUID;
    45 /**
    46  * {@link Codec}s that uses the MIME multipart as the underlying format.
    47  *
    48  * <p>
    49  * When the runtime needs to dynamically choose a {@link Codec}, and
    50  * when there are more than one {@link Codec}s that use MIME multipart,
    51  * it is often impossible to determine the right {@link Codec} unless
    52  * you parse the multipart message to some extent.
    53  *
    54  * <p>
    55  * By having all such {@link Codec}s extending from this class,
    56  * the "sniffer" can decode a multipart message partially, and then
    57  * pass the partial parse result to the ultimately-responsible {@link Codec}.
    58  * This improves the performance.
    59  *
    60  * @author Kohsuke Kawaguchi
    61  */
    62 abstract class MimeCodec implements Codec {
    64     public static final String MULTIPART_RELATED_MIME_TYPE = "multipart/related";
    66     protected Codec mimeRootCodec;
    67     protected final SOAPVersion version;
    68     protected final WSFeatureList features;
    70     protected MimeCodec(SOAPVersion version, WSFeatureList f) {
    71         this.version = version;
    72         this.features = f;
    73     }
    75     public String getMimeType() {
    76         return MULTIPART_RELATED_MIME_TYPE;
    77     }
    79     protected Codec getMimeRootCodec(Packet packet) {
    80         return mimeRootCodec;
    81     }
    83     // TODO: preencode String literals to byte[] so that they don't have to
    84     // go through char[]->byte[] conversion at runtime.
    85     public ContentType encode(Packet packet, OutputStream out) throws IOException {
    86         Message msg = packet.getMessage();
    87         if (msg == null) {
    88             return null;
    89         }
    90         ContentTypeImpl ctImpl = (ContentTypeImpl)getStaticContentType(packet);
    91         String boundary = ctImpl.getBoundary();
    92         boolean hasAttachments = (boundary != null);
    93         Codec rootCodec = getMimeRootCodec(packet);
    94         if (hasAttachments) {
    95             writeln("--"+boundary, out);
    96             ContentType ct = rootCodec.getStaticContentType(packet);
    97             String ctStr = (ct != null) ? ct.getContentType() : rootCodec.getMimeType();
    98             writeln("Content-Type: " + ctStr, out);
    99             writeln(out);
   100         }
   101         ContentType primaryCt = rootCodec.encode(packet, out);
   103         if (hasAttachments) {
   104             writeln(out);
   105             // Encode all the attchments
   106             for (Attachment att : msg.getAttachments()) {
   107                 writeln("--"+boundary, out);
   108                 //SAAJ's AttachmentPart.getContentId() returns content id already enclosed with
   109                 //angle brackets. For now put angle bracket only if its not there
   110                 String cid = att.getContentId();
   111                 if(cid != null && cid.length() >0 && cid.charAt(0) != '<')
   112                     cid = '<' + cid + '>';
   113                 writeln("Content-Id:" + cid, out);
   114                 writeln("Content-Type: " + att.getContentType(), out);
   115                 writeCustomMimeHeaders(att, out);
   116                 writeln("Content-Transfer-Encoding: binary", out);
   117                 writeln(out);                    // write \r\n
   118                 att.writeTo(out);
   119                 writeln(out);                    // write \r\n
   120             }
   121             writeAsAscii("--"+boundary, out);
   122             writeAsAscii("--", out);
   123         }
   124         // TODO not returing correct multipart/related type(no boundary)
   125         return hasAttachments ? ctImpl : primaryCt;
   126     }
   128     private void writeCustomMimeHeaders(Attachment att, OutputStream out) throws IOException {
   129         if (att instanceof AttachmentEx) {
   130             Iterator<AttachmentEx.MimeHeader> allMimeHeaders = ((AttachmentEx) att).getMimeHeaders();
   131             while (allMimeHeaders.hasNext()) {
   132                 AttachmentEx.MimeHeader mh = allMimeHeaders.next();
   133                 String name = mh.getName();
   135                 if (!"Content-Type".equalsIgnoreCase(name) && !"Content-Id".equalsIgnoreCase(name)) {
   136                     writeln(name +": " + mh.getValue(), out);
   137                 }
   138             }
   139         }
   140     }
   142     public ContentType getStaticContentType(Packet packet) {
   143         ContentType ct = (ContentType) packet.getInternalContentType();
   144         if ( ct != null ) return ct;
   145         Message msg = packet.getMessage();
   146         boolean hasAttachments = !msg.getAttachments().isEmpty();
   147         Codec rootCodec = getMimeRootCodec(packet);
   149         if (hasAttachments) {
   150             String boundary = "uuid:" + UUID.randomUUID().toString();
   151             String boundaryParameter = "boundary=\"" + boundary + "\"";
   152             // TODO use primaryEncoder to get type
   153             String messageContentType =  MULTIPART_RELATED_MIME_TYPE +
   154                     "; type=\"" + rootCodec.getMimeType() + "\"; " +
   155                     boundaryParameter;
   156             ContentTypeImpl impl = new ContentTypeImpl(messageContentType, packet.soapAction, null);
   157             impl.setBoundary(boundary);
   158             impl.setBoundaryParameter(boundaryParameter);
   159             packet.setContentType(impl);
   160             return impl;
   161         } else {
   162             ct = rootCodec.getStaticContentType(packet);
   163             packet.setContentType(ct);
   164             return ct;
   165         }
   166     }
   168     /**
   169      * Copy constructor.
   170      */
   171     protected MimeCodec(MimeCodec that) {
   172         this.version = that.version;
   173         this.features = that.features;
   174     }
   176     public void decode(InputStream in, String contentType, Packet packet) throws IOException {
   177         MimeMultipartParser parser = new MimeMultipartParser(in, contentType, features.get(StreamingAttachmentFeature.class));
   178         decode(parser,packet);
   179     }
   181     public void decode(ReadableByteChannel in, String contentType, Packet packet) {
   182         throw new UnsupportedOperationException();
   183     }
   185     /**
   186      * Parses a {@link Packet} from a {@link MimeMultipartParser}.
   187      */
   188     protected abstract void decode(MimeMultipartParser mpp, Packet packet) throws IOException;
   190     public abstract MimeCodec copy();
   193     public static void writeln(String s,OutputStream out) throws IOException {
   194         writeAsAscii(s,out);
   195         writeln(out);
   196     }
   198     /**
   199      * Writes a string as ASCII string.
   200      */
   201     public static void writeAsAscii(String s,OutputStream out) throws IOException {
   202         int len = s.length();
   203         for( int i=0; i<len; i++ )
   204             out.write((byte)s.charAt(i));
   205     }
   207     public static void writeln(OutputStream out) throws IOException {
   208         out.write('\r');
   209         out.write('\n');
   210     }
   211 }

mercurial