src/share/jaxws_classes/com/sun/xml/internal/ws/encoding/fastinfoset/FastInfosetCodec.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

aoqi@0 1 /*
aoqi@0 2 * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
aoqi@0 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
aoqi@0 4 *
aoqi@0 5 * This code is free software; you can redistribute it and/or modify it
aoqi@0 6 * under the terms of the GNU General Public License version 2 only, as
aoqi@0 7 * published by the Free Software Foundation. Oracle designates this
aoqi@0 8 * particular file as subject to the "Classpath" exception as provided
aoqi@0 9 * by Oracle in the LICENSE file that accompanied this code.
aoqi@0 10 *
aoqi@0 11 * This code is distributed in the hope that it will be useful, but WITHOUT
aoqi@0 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
aoqi@0 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
aoqi@0 14 * version 2 for more details (a copy is included in the LICENSE file that
aoqi@0 15 * accompanied this code).
aoqi@0 16 *
aoqi@0 17 * You should have received a copy of the GNU General Public License version
aoqi@0 18 * 2 along with this work; if not, write to the Free Software Foundation,
aoqi@0 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
aoqi@0 20 *
aoqi@0 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
aoqi@0 22 * or visit www.oracle.com if you need additional information or have any
aoqi@0 23 * questions.
aoqi@0 24 */
aoqi@0 25
aoqi@0 26 package com.sun.xml.internal.ws.encoding.fastinfoset;
aoqi@0 27
aoqi@0 28 import com.sun.xml.internal.fastinfoset.stax.StAXDocumentSerializer;
aoqi@0 29 import com.sun.xml.internal.fastinfoset.stax.StAXDocumentParser;
aoqi@0 30 import com.sun.xml.internal.fastinfoset.vocab.ParserVocabulary;
aoqi@0 31 import com.sun.xml.internal.fastinfoset.vocab.SerializerVocabulary;
aoqi@0 32 import com.sun.xml.internal.ws.api.SOAPVersion;
aoqi@0 33 import com.sun.xml.internal.ws.api.message.Message;
aoqi@0 34 import com.sun.xml.internal.ws.api.message.Messages;
aoqi@0 35 import com.sun.xml.internal.ws.api.pipe.Codec;
aoqi@0 36 import com.sun.xml.internal.ws.api.pipe.ContentType;
aoqi@0 37 import com.sun.xml.internal.ws.api.message.Packet;
aoqi@0 38 import com.sun.xml.internal.ws.encoding.ContentTypeImpl;
aoqi@0 39 import java.io.BufferedInputStream;
aoqi@0 40
aoqi@0 41 import javax.xml.stream.XMLStreamException;
aoqi@0 42 import javax.xml.stream.XMLStreamWriter;
aoqi@0 43 import javax.xml.ws.WebServiceException;
aoqi@0 44 import java.io.OutputStream;
aoqi@0 45 import java.io.InputStream;
aoqi@0 46 import java.io.IOException;
aoqi@0 47 import java.nio.channels.WritableByteChannel;
aoqi@0 48 import java.nio.channels.ReadableByteChannel;
aoqi@0 49 import com.sun.xml.internal.org.jvnet.fastinfoset.FastInfosetSource;
aoqi@0 50
aoqi@0 51 /**
aoqi@0 52 * A codec for encoding/decoding XML infosets to/from fast
aoqi@0 53 * infoset documents.
aoqi@0 54 *
aoqi@0 55 * @author Paul Sandoz
aoqi@0 56 */
aoqi@0 57 public class FastInfosetCodec implements Codec {
aoqi@0 58 private static final int DEFAULT_INDEXED_STRING_SIZE_LIMIT = 32;
aoqi@0 59 private static final int DEFAULT_INDEXED_STRING_MEMORY_LIMIT = 4 * 1024 * 1024; //4M limit
aoqi@0 60
aoqi@0 61 private StAXDocumentParser _parser;
aoqi@0 62
aoqi@0 63 private StAXDocumentSerializer _serializer;
aoqi@0 64
aoqi@0 65 private final boolean _retainState;
aoqi@0 66
aoqi@0 67 private final ContentType _contentType;
aoqi@0 68
aoqi@0 69 /* package */ FastInfosetCodec(boolean retainState) {
aoqi@0 70 _retainState = retainState;
aoqi@0 71 _contentType = (retainState) ? new ContentTypeImpl(FastInfosetMIMETypes.STATEFUL_INFOSET) :
aoqi@0 72 new ContentTypeImpl(FastInfosetMIMETypes.INFOSET);
aoqi@0 73 }
aoqi@0 74
aoqi@0 75 public String getMimeType() {
aoqi@0 76 return _contentType.getContentType();
aoqi@0 77 }
aoqi@0 78
aoqi@0 79 public Codec copy() {
aoqi@0 80 return new FastInfosetCodec(_retainState);
aoqi@0 81 }
aoqi@0 82
aoqi@0 83 public ContentType getStaticContentType(Packet packet) {
aoqi@0 84 return _contentType;
aoqi@0 85 }
aoqi@0 86
aoqi@0 87 public ContentType encode(Packet packet, OutputStream out) {
aoqi@0 88 Message message = packet.getMessage();
aoqi@0 89 if (message != null && message.hasPayload()) {
aoqi@0 90 final XMLStreamWriter writer = getXMLStreamWriter(out);
aoqi@0 91 try {
aoqi@0 92 writer.writeStartDocument();
aoqi@0 93 packet.getMessage().writePayloadTo(writer);
aoqi@0 94 writer.writeEndDocument();
aoqi@0 95 writer.flush();
aoqi@0 96 } catch (XMLStreamException e) {
aoqi@0 97 throw new WebServiceException(e);
aoqi@0 98 }
aoqi@0 99 }
aoqi@0 100
aoqi@0 101 return _contentType;
aoqi@0 102 }
aoqi@0 103
aoqi@0 104 public ContentType encode(Packet packet, WritableByteChannel buffer) {
aoqi@0 105 //TODO: not yet implemented
aoqi@0 106 throw new UnsupportedOperationException();
aoqi@0 107 }
aoqi@0 108
aoqi@0 109 public void decode(InputStream in, String contentType, Packet packet) throws IOException {
aoqi@0 110 /* Implements similar logic as the XMLMessage.create(String, InputStream).
aoqi@0 111 * But it's faster, as we know the InputStream has FastInfoset content*/
aoqi@0 112 Message message;
aoqi@0 113 in = hasSomeData(in);
aoqi@0 114 if (in != null) {
aoqi@0 115 message = Messages.createUsingPayload(new FastInfosetSource(in),
aoqi@0 116 SOAPVersion.SOAP_11);
aoqi@0 117 } else {
aoqi@0 118 message = Messages.createEmpty(SOAPVersion.SOAP_11);
aoqi@0 119 }
aoqi@0 120
aoqi@0 121 packet.setMessage(message);
aoqi@0 122 }
aoqi@0 123
aoqi@0 124 public void decode(ReadableByteChannel in, String contentType, Packet response) {
aoqi@0 125 throw new UnsupportedOperationException();
aoqi@0 126 }
aoqi@0 127
aoqi@0 128 private XMLStreamWriter getXMLStreamWriter(OutputStream out) {
aoqi@0 129 if (_serializer != null) {
aoqi@0 130 _serializer.setOutputStream(out);
aoqi@0 131 return _serializer;
aoqi@0 132 } else {
aoqi@0 133 return _serializer = createNewStreamWriter(out, _retainState);
aoqi@0 134 }
aoqi@0 135 }
aoqi@0 136
aoqi@0 137 /**
aoqi@0 138 * Creates a new {@link FastInfosetCodec} instance.
aoqi@0 139 *
aoqi@0 140 * @return a new {@link FastInfosetCodec} instance.
aoqi@0 141 */
aoqi@0 142 public static FastInfosetCodec create() {
aoqi@0 143 return create(false);
aoqi@0 144 }
aoqi@0 145
aoqi@0 146 /**
aoqi@0 147 * Creates a new {@link FastInfosetCodec} instance.
aoqi@0 148 *
aoqi@0 149 * @param retainState if true the Codec should retain the state of
aoqi@0 150 * vocabulary tables for multiple encode/decode invocations.
aoqi@0 151 * @return a new {@link FastInfosetCodec} instance.
aoqi@0 152 */
aoqi@0 153 public static FastInfosetCodec create(boolean retainState) {
aoqi@0 154 return new FastInfosetCodec(retainState);
aoqi@0 155 }
aoqi@0 156
aoqi@0 157 /**
aoqi@0 158 * Create a new (@link StAXDocumentSerializer} instance.
aoqi@0 159 *
aoqi@0 160 * @param in the OutputStream to serialize to.
aoqi@0 161 * @param retainState if true the serializer should retain the state of
aoqi@0 162 * vocabulary tables for multiple serializations.
aoqi@0 163 * @return a new {@link StAXDocumentSerializer} instance.
aoqi@0 164 */
aoqi@0 165 /* package */ static StAXDocumentSerializer createNewStreamWriter(OutputStream out, boolean retainState) {
aoqi@0 166 return createNewStreamWriter(out, retainState, DEFAULT_INDEXED_STRING_SIZE_LIMIT, DEFAULT_INDEXED_STRING_MEMORY_LIMIT);
aoqi@0 167 }
aoqi@0 168
aoqi@0 169 /**
aoqi@0 170 * Create a new (@link StAXDocumentSerializer} instance.
aoqi@0 171 *
aoqi@0 172 * @param in the OutputStream to serialize to.
aoqi@0 173 * @param retainState if true the serializer should retain the state of
aoqi@0 174 * vocabulary tables for multiple serializations.
aoqi@0 175 * @return a new {@link StAXDocumentSerializer} instance.
aoqi@0 176 */
aoqi@0 177 /* package */ static StAXDocumentSerializer createNewStreamWriter(OutputStream out,
aoqi@0 178 boolean retainState, int indexedStringSizeLimit, int stringsMemoryLimit) {
aoqi@0 179 StAXDocumentSerializer serializer = new StAXDocumentSerializer(out);
aoqi@0 180 if (retainState) {
aoqi@0 181 /**
aoqi@0 182 * Create a serializer vocabulary external to the serializer.
aoqi@0 183 * This will ensure that the vocabulary will never be cleared
aoqi@0 184 * for each serialization and will be retained (and will grow)
aoqi@0 185 * for each serialization
aoqi@0 186 */
aoqi@0 187 SerializerVocabulary vocabulary = new SerializerVocabulary();
aoqi@0 188 serializer.setVocabulary(vocabulary);
aoqi@0 189 serializer.setMinAttributeValueSize(0);
aoqi@0 190 serializer.setMaxAttributeValueSize(indexedStringSizeLimit);
aoqi@0 191 serializer.setMinCharacterContentChunkSize(0);
aoqi@0 192 serializer.setMaxCharacterContentChunkSize(indexedStringSizeLimit);
aoqi@0 193 serializer.setAttributeValueMapMemoryLimit(stringsMemoryLimit);
aoqi@0 194 serializer.setCharacterContentChunkMapMemoryLimit(stringsMemoryLimit);
aoqi@0 195 }
aoqi@0 196 return serializer;
aoqi@0 197 }
aoqi@0 198
aoqi@0 199 /**
aoqi@0 200 * Create a new (@link StAXDocumentParser} instance.
aoqi@0 201 *
aoqi@0 202 * @param in the InputStream to parse from.
aoqi@0 203 * @param retainState if true the parser should retain the state of
aoqi@0 204 * vocabulary tables for multiple parses.
aoqi@0 205 * @return a new {@link StAXDocumentParser} instance.
aoqi@0 206 */
aoqi@0 207 /* package */ static StAXDocumentParser createNewStreamReader(InputStream in, boolean retainState) {
aoqi@0 208 StAXDocumentParser parser = new StAXDocumentParser(in);
aoqi@0 209 parser.setStringInterning(true);
aoqi@0 210 if (retainState) {
aoqi@0 211 /**
aoqi@0 212 * Create a parser vocabulary external to the parser.
aoqi@0 213 * This will ensure that the vocabulary will never be cleared
aoqi@0 214 * for each parse and will be retained (and will grow)
aoqi@0 215 * for each parse.
aoqi@0 216 */
aoqi@0 217 ParserVocabulary vocabulary = new ParserVocabulary();
aoqi@0 218 parser.setVocabulary(vocabulary);
aoqi@0 219 }
aoqi@0 220 return parser;
aoqi@0 221 }
aoqi@0 222
aoqi@0 223 /**
aoqi@0 224 * Create a new (@link StAXDocumentParser} recyclable instance.
aoqi@0 225 *
aoqi@0 226 * @param in the InputStream to parse from.
aoqi@0 227 * @param retainState if true the parser should retain the state of
aoqi@0 228 * vocabulary tables for multiple parses.
aoqi@0 229 * @return a new recyclable {@link StAXDocumentParser} instance.
aoqi@0 230 */
aoqi@0 231 /* package */ static StAXDocumentParser createNewStreamReaderRecyclable(InputStream in, boolean retainState) {
aoqi@0 232 StAXDocumentParser parser = new FastInfosetStreamReaderRecyclable(in);
aoqi@0 233 parser.setStringInterning(true);
aoqi@0 234 parser.setForceStreamClose(true);
aoqi@0 235 if (retainState) {
aoqi@0 236 /**
aoqi@0 237 * Create a parser vocabulary external to the parser.
aoqi@0 238 * This will ensure that the vocabulary will never be cleared
aoqi@0 239 * for each parse and will be retained (and will grow)
aoqi@0 240 * for each parse.
aoqi@0 241 */
aoqi@0 242 ParserVocabulary vocabulary = new ParserVocabulary();
aoqi@0 243 parser.setVocabulary(vocabulary);
aoqi@0 244 }
aoqi@0 245 return parser;
aoqi@0 246 }
aoqi@0 247
aoqi@0 248 /**
aoqi@0 249 * Method is copied from com.sun.xml.internal.ws.encoding.xml.XMLMessage
aoqi@0 250 * @TODO method should be public in some util package?
aoqi@0 251 *
aoqi@0 252 * Finds if the stream has some content or not
aoqi@0 253 *
aoqi@0 254 * @return null if there is no data
aoqi@0 255 * else stream to be used
aoqi@0 256 */
aoqi@0 257 private static InputStream hasSomeData(InputStream in) throws IOException {
aoqi@0 258 if (in != null) {
aoqi@0 259 if (in.available() < 1) {
aoqi@0 260 if (!in.markSupported()) {
aoqi@0 261 in = new BufferedInputStream(in);
aoqi@0 262 }
aoqi@0 263 in.mark(1);
aoqi@0 264 if (in.read() != -1) {
aoqi@0 265 in.reset();
aoqi@0 266 } else {
aoqi@0 267 in = null; // No data
aoqi@0 268 }
aoqi@0 269 }
aoqi@0 270 }
aoqi@0 271 return in;
aoqi@0 272 }
aoqi@0 273 }

mercurial