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

Sun, 15 Dec 2013 23:35:45 +0100

author
mkos
date
Sun, 15 Dec 2013 23:35:45 +0100
changeset 494
2fcd3ddb57a6
parent 368
0989ad8c0860
child 637
9c07ef4934dd
permissions
-rw-r--r--

8025152: Enhance activation set up
8028388: 9 jaxws tests failed in nightly build with java.lang.ClassCastException
Summary: fix also reviewed by Bill Shannon, Alexander Fomin
Reviewed-by: dfuchs, hawtin, mgrebac
Contributed-by: bill.shannon@oracle.com

ohair@286 1 /*
alanb@368 2 * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
ohair@286 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
ohair@286 4 *
ohair@286 5 * This code is free software; you can redistribute it and/or modify it
ohair@286 6 * under the terms of the GNU General Public License version 2 only, as
ohair@286 7 * published by the Free Software Foundation. Oracle designates this
ohair@286 8 * particular file as subject to the "Classpath" exception as provided
ohair@286 9 * by Oracle in the LICENSE file that accompanied this code.
ohair@286 10 *
ohair@286 11 * This code is distributed in the hope that it will be useful, but WITHOUT
ohair@286 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
ohair@286 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
ohair@286 14 * version 2 for more details (a copy is included in the LICENSE file that
ohair@286 15 * accompanied this code).
ohair@286 16 *
ohair@286 17 * You should have received a copy of the GNU General Public License version
ohair@286 18 * 2 along with this work; if not, write to the Free Software Foundation,
ohair@286 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
ohair@286 20 *
ohair@286 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
ohair@286 22 * or visit www.oracle.com if you need additional information or have any
ohair@286 23 * questions.
ohair@286 24 */
ohair@286 25
ohair@286 26 package com.sun.xml.internal.ws.encoding;
ohair@286 27
ohair@286 28 import com.sun.xml.internal.ws.api.SOAPVersion;
ohair@286 29 import com.sun.xml.internal.ws.api.WSFeatureList;
ohair@286 30 import com.sun.xml.internal.ws.api.message.Attachment;
ohair@286 31 import com.sun.xml.internal.ws.api.message.AttachmentEx;
ohair@286 32 import com.sun.xml.internal.ws.api.message.Message;
ohair@286 33 import com.sun.xml.internal.ws.api.message.Packet;
ohair@286 34 import com.sun.xml.internal.ws.api.pipe.Codec;
ohair@286 35 import com.sun.xml.internal.ws.api.pipe.ContentType;
ohair@286 36 import com.sun.xml.internal.ws.developer.StreamingAttachmentFeature;
ohair@286 37
ohair@286 38 import java.io.IOException;
ohair@286 39 import java.io.InputStream;
ohair@286 40 import java.io.OutputStream;
ohair@286 41 import java.nio.channels.ReadableByteChannel;
ohair@286 42 import java.util.Iterator;
ohair@286 43 import java.util.UUID;
ohair@286 44
ohair@286 45 /**
ohair@286 46 * {@link Codec}s that uses the MIME multipart as the underlying format.
ohair@286 47 *
ohair@286 48 * <p>
ohair@286 49 * When the runtime needs to dynamically choose a {@link Codec}, and
ohair@286 50 * when there are more than one {@link Codec}s that use MIME multipart,
ohair@286 51 * it is often impossible to determine the right {@link Codec} unless
ohair@286 52 * you parse the multipart message to some extent.
ohair@286 53 *
ohair@286 54 * <p>
ohair@286 55 * By having all such {@link Codec}s extending from this class,
ohair@286 56 * the "sniffer" can decode a multipart message partially, and then
ohair@286 57 * pass the partial parse result to the ultimately-responsible {@link Codec}.
ohair@286 58 * This improves the performance.
ohair@286 59 *
ohair@286 60 * @author Kohsuke Kawaguchi
ohair@286 61 */
ohair@286 62 abstract class MimeCodec implements Codec {
ohair@286 63
ohair@286 64 public static final String MULTIPART_RELATED_MIME_TYPE = "multipart/related";
ohair@286 65
alanb@368 66 protected Codec mimeRootCodec;
ohair@286 67 protected final SOAPVersion version;
ohair@286 68 protected final WSFeatureList features;
ohair@286 69
ohair@286 70 protected MimeCodec(SOAPVersion version, WSFeatureList f) {
ohair@286 71 this.version = version;
ohair@286 72 this.features = f;
ohair@286 73 }
ohair@286 74
ohair@286 75 public String getMimeType() {
ohair@286 76 return MULTIPART_RELATED_MIME_TYPE;
ohair@286 77 }
ohair@286 78
alanb@368 79 protected Codec getMimeRootCodec(Packet packet) {
alanb@368 80 return mimeRootCodec;
alanb@368 81 }
alanb@368 82
ohair@286 83 // TODO: preencode String literals to byte[] so that they don't have to
ohair@286 84 // go through char[]->byte[] conversion at runtime.
ohair@286 85 public ContentType encode(Packet packet, OutputStream out) throws IOException {
ohair@286 86 Message msg = packet.getMessage();
ohair@286 87 if (msg == null) {
ohair@286 88 return null;
ohair@286 89 }
alanb@368 90 ContentTypeImpl ctImpl = (ContentTypeImpl)getStaticContentType(packet);
alanb@368 91 String boundary = ctImpl.getBoundary();
alanb@368 92 boolean hasAttachments = (boundary != null);
alanb@368 93 Codec rootCodec = getMimeRootCodec(packet);
ohair@286 94 if (hasAttachments) {
ohair@286 95 writeln("--"+boundary, out);
ohair@286 96 ContentType ct = rootCodec.getStaticContentType(packet);
ohair@286 97 String ctStr = (ct != null) ? ct.getContentType() : rootCodec.getMimeType();
ohair@286 98 writeln("Content-Type: " + ctStr, out);
ohair@286 99 writeln(out);
ohair@286 100 }
ohair@286 101 ContentType primaryCt = rootCodec.encode(packet, out);
ohair@286 102
ohair@286 103 if (hasAttachments) {
ohair@286 104 writeln(out);
ohair@286 105 // Encode all the attchments
ohair@286 106 for (Attachment att : msg.getAttachments()) {
ohair@286 107 writeln("--"+boundary, out);
ohair@286 108 //SAAJ's AttachmentPart.getContentId() returns content id already enclosed with
ohair@286 109 //angle brackets. For now put angle bracket only if its not there
ohair@286 110 String cid = att.getContentId();
ohair@286 111 if(cid != null && cid.length() >0 && cid.charAt(0) != '<')
ohair@286 112 cid = '<' + cid + '>';
ohair@286 113 writeln("Content-Id:" + cid, out);
ohair@286 114 writeln("Content-Type: " + att.getContentType(), out);
ohair@286 115 writeCustomMimeHeaders(att, out);
ohair@286 116 writeln("Content-Transfer-Encoding: binary", out);
ohair@286 117 writeln(out); // write \r\n
ohair@286 118 att.writeTo(out);
ohair@286 119 writeln(out); // write \r\n
ohair@286 120 }
ohair@286 121 writeAsAscii("--"+boundary, out);
ohair@286 122 writeAsAscii("--", out);
ohair@286 123 }
ohair@286 124 // TODO not returing correct multipart/related type(no boundary)
alanb@368 125 return hasAttachments ? ctImpl : primaryCt;
ohair@286 126 }
ohair@286 127
ohair@286 128 private void writeCustomMimeHeaders(Attachment att, OutputStream out) throws IOException {
ohair@286 129 if (att instanceof AttachmentEx) {
ohair@286 130 Iterator<AttachmentEx.MimeHeader> allMimeHeaders = ((AttachmentEx) att).getMimeHeaders();
ohair@286 131 while (allMimeHeaders.hasNext()) {
ohair@286 132 AttachmentEx.MimeHeader mh = allMimeHeaders.next();
ohair@286 133 String name = mh.getName();
ohair@286 134
ohair@286 135 if (!"Content-Type".equalsIgnoreCase(name) && !"Content-Id".equalsIgnoreCase(name)) {
ohair@286 136 writeln(name +": " + mh.getValue(), out);
ohair@286 137 }
ohair@286 138 }
ohair@286 139 }
ohair@286 140 }
ohair@286 141
ohair@286 142 public ContentType getStaticContentType(Packet packet) {
alanb@368 143 ContentType ct = (ContentType) packet.getInternalContentType();
alanb@368 144 if ( ct != null ) return ct;
ohair@286 145 Message msg = packet.getMessage();
alanb@368 146 boolean hasAttachments = !msg.getAttachments().isEmpty();
alanb@368 147 Codec rootCodec = getMimeRootCodec(packet);
ohair@286 148
ohair@286 149 if (hasAttachments) {
alanb@368 150 String boundary = "uuid:" + UUID.randomUUID().toString();
ohair@286 151 String boundaryParameter = "boundary=\"" + boundary + "\"";
ohair@286 152 // TODO use primaryEncoder to get type
alanb@368 153 String messageContentType = MULTIPART_RELATED_MIME_TYPE +
ohair@286 154 "; type=\"" + rootCodec.getMimeType() + "\"; " +
ohair@286 155 boundaryParameter;
alanb@368 156 ContentTypeImpl impl = new ContentTypeImpl(messageContentType, packet.soapAction, null);
alanb@368 157 impl.setBoundary(boundary);
alanb@368 158 impl.setBoundaryParameter(boundaryParameter);
alanb@368 159 packet.setContentType(impl);
alanb@368 160 return impl;
ohair@286 161 } else {
alanb@368 162 ct = rootCodec.getStaticContentType(packet);
alanb@368 163 packet.setContentType(ct);
alanb@368 164 return ct;
ohair@286 165 }
ohair@286 166 }
ohair@286 167
ohair@286 168 /**
ohair@286 169 * Copy constructor.
ohair@286 170 */
ohair@286 171 protected MimeCodec(MimeCodec that) {
ohair@286 172 this.version = that.version;
ohair@286 173 this.features = that.features;
ohair@286 174 }
ohair@286 175
ohair@286 176 public void decode(InputStream in, String contentType, Packet packet) throws IOException {
ohair@286 177 MimeMultipartParser parser = new MimeMultipartParser(in, contentType, features.get(StreamingAttachmentFeature.class));
ohair@286 178 decode(parser,packet);
ohair@286 179 }
ohair@286 180
ohair@286 181 public void decode(ReadableByteChannel in, String contentType, Packet packet) {
ohair@286 182 throw new UnsupportedOperationException();
ohair@286 183 }
ohair@286 184
ohair@286 185 /**
ohair@286 186 * Parses a {@link Packet} from a {@link MimeMultipartParser}.
ohair@286 187 */
ohair@286 188 protected abstract void decode(MimeMultipartParser mpp, Packet packet) throws IOException;
ohair@286 189
ohair@286 190 public abstract MimeCodec copy();
ohair@286 191
ohair@286 192
ohair@286 193 public static void writeln(String s,OutputStream out) throws IOException {
ohair@286 194 writeAsAscii(s,out);
ohair@286 195 writeln(out);
ohair@286 196 }
ohair@286 197
ohair@286 198 /**
ohair@286 199 * Writes a string as ASCII string.
ohair@286 200 */
ohair@286 201 public static void writeAsAscii(String s,OutputStream out) throws IOException {
ohair@286 202 int len = s.length();
ohair@286 203 for( int i=0; i<len; i++ )
ohair@286 204 out.write((byte)s.charAt(i));
ohair@286 205 }
ohair@286 206
ohair@286 207 public static void writeln(OutputStream out) throws IOException {
ohair@286 208 out.write('\r');
ohair@286 209 out.write('\n');
ohair@286 210 }
ohair@286 211 }

mercurial