Tue, 06 Mar 2012 16:09:35 -0800
7150322: Stop using drop source bundles in jaxws
Reviewed-by: darcy, ohrstrom
1 /*
2 * Copyright (c) 1997, 2010, 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.fastinfoset;
28 import com.sun.xml.internal.fastinfoset.stax.StAXDocumentSerializer;
29 import com.sun.xml.internal.fastinfoset.stax.StAXDocumentParser;
30 import com.sun.xml.internal.fastinfoset.vocab.ParserVocabulary;
31 import com.sun.xml.internal.fastinfoset.vocab.SerializerVocabulary;
32 import com.sun.xml.internal.ws.api.SOAPVersion;
33 import com.sun.xml.internal.ws.api.message.Message;
34 import com.sun.xml.internal.ws.api.message.Messages;
35 import com.sun.xml.internal.ws.api.pipe.Codec;
36 import com.sun.xml.internal.ws.api.pipe.ContentType;
37 import com.sun.xml.internal.ws.api.message.Packet;
38 import com.sun.xml.internal.ws.encoding.ContentTypeImpl;
39 import java.io.BufferedInputStream;
41 import javax.xml.stream.XMLStreamException;
42 import javax.xml.stream.XMLStreamWriter;
43 import javax.xml.stream.XMLStreamReader;
44 import javax.xml.ws.WebServiceException;
45 import java.io.OutputStream;
46 import java.io.InputStream;
47 import java.io.IOException;
48 import java.nio.channels.WritableByteChannel;
49 import java.nio.channels.ReadableByteChannel;
50 import com.sun.xml.internal.org.jvnet.fastinfoset.FastInfosetSource;
52 /**
53 * A codec for encoding/decoding XML infosets to/from fast
54 * infoset documents.
55 *
56 * @author Paul Sandoz
57 */
58 public class FastInfosetCodec implements Codec {
59 private static final int DEFAULT_INDEXED_STRING_SIZE_LIMIT = 32;
60 private static final int DEFAULT_INDEXED_STRING_MEMORY_LIMIT = 4 * 1024 * 1024; //4M limit
62 private StAXDocumentParser _parser;
64 private StAXDocumentSerializer _serializer;
66 private final boolean _retainState;
68 private final ContentType _contentType;
70 /* package */ FastInfosetCodec(boolean retainState) {
71 _retainState = retainState;
72 _contentType = (retainState) ? new ContentTypeImpl(FastInfosetMIMETypes.STATEFUL_INFOSET) :
73 new ContentTypeImpl(FastInfosetMIMETypes.INFOSET);
74 }
76 public String getMimeType() {
77 return _contentType.getContentType();
78 }
80 public Codec copy() {
81 return new FastInfosetCodec(_retainState);
82 }
84 public ContentType getStaticContentType(Packet packet) {
85 return _contentType;
86 }
88 public ContentType encode(Packet packet, OutputStream out) {
89 Message message = packet.getMessage();
90 if (message != null && message.hasPayload()) {
91 final XMLStreamWriter writer = getXMLStreamWriter(out);
92 try {
93 writer.writeStartDocument();
94 packet.getMessage().writePayloadTo(writer);
95 writer.writeEndDocument();
96 writer.flush();
97 } catch (XMLStreamException e) {
98 throw new WebServiceException(e);
99 }
100 }
102 return _contentType;
103 }
105 public ContentType encode(Packet packet, WritableByteChannel buffer) {
106 //TODO: not yet implemented
107 throw new UnsupportedOperationException();
108 }
110 public void decode(InputStream in, String contentType, Packet packet) throws IOException {
111 /* Implements similar logic as the XMLMessage.create(String, InputStream).
112 * But it's faster, as we know the InputStream has FastInfoset content*/
113 Message message = null;
114 in = hasSomeData(in);
115 if (in != null) {
116 message = Messages.createUsingPayload(new FastInfosetSource(in),
117 SOAPVersion.SOAP_11);
118 } else {
119 message = Messages.createEmpty(SOAPVersion.SOAP_11);
120 }
122 packet.setMessage(message);
123 }
125 public void decode(ReadableByteChannel in, String contentType, Packet response) {
126 throw new UnsupportedOperationException();
127 }
129 private XMLStreamWriter getXMLStreamWriter(OutputStream out) {
130 if (_serializer != null) {
131 _serializer.setOutputStream(out);
132 return _serializer;
133 } else {
134 return _serializer = createNewStreamWriter(out, _retainState);
135 }
136 }
138 private XMLStreamReader getXMLStreamReader(InputStream in) {
139 if (_parser != null) {
140 _parser.setInputStream(in);
141 return _parser;
142 } else {
143 return _parser = createNewStreamReader(in, _retainState);
144 }
145 }
147 /**
148 * Creates a new {@link FastInfosetCodec} instance.
149 *
150 * @return a new {@link FastInfosetCodec} instance.
151 */
152 public static FastInfosetCodec create() {
153 return create(false);
154 }
156 /**
157 * Creates a new {@link FastInfosetCodec} instance.
158 *
159 * @param retainState if true the Codec should retain the state of
160 * vocabulary tables for multiple encode/decode invocations.
161 * @return a new {@link FastInfosetCodec} instance.
162 */
163 public static FastInfosetCodec create(boolean retainState) {
164 return new FastInfosetCodec(retainState);
165 }
167 /**
168 * Create a new (@link StAXDocumentSerializer} instance.
169 *
170 * @param in the OutputStream to serialize to.
171 * @param retainState if true the serializer should retain the state of
172 * vocabulary tables for multiple serializations.
173 * @return a new {@link StAXDocumentSerializer} instance.
174 */
175 /* package */ static StAXDocumentSerializer createNewStreamWriter(OutputStream out, boolean retainState) {
176 return createNewStreamWriter(out, retainState, DEFAULT_INDEXED_STRING_SIZE_LIMIT, DEFAULT_INDEXED_STRING_MEMORY_LIMIT);
177 }
179 /**
180 * Create a new (@link StAXDocumentSerializer} instance.
181 *
182 * @param in the OutputStream to serialize to.
183 * @param retainState if true the serializer should retain the state of
184 * vocabulary tables for multiple serializations.
185 * @return a new {@link StAXDocumentSerializer} instance.
186 */
187 /* package */ static StAXDocumentSerializer createNewStreamWriter(OutputStream out,
188 boolean retainState, int indexedStringSizeLimit, int stringsMemoryLimit) {
189 StAXDocumentSerializer serializer = new StAXDocumentSerializer(out);
190 if (retainState) {
191 /**
192 * Create a serializer vocabulary external to the serializer.
193 * This will ensure that the vocabulary will never be cleared
194 * for each serialization and will be retained (and will grow)
195 * for each serialization
196 */
197 SerializerVocabulary vocabulary = new SerializerVocabulary();
198 serializer.setVocabulary(vocabulary);
199 serializer.setMinAttributeValueSize(0);
200 serializer.setMaxAttributeValueSize(indexedStringSizeLimit);
201 serializer.setMinCharacterContentChunkSize(0);
202 serializer.setMaxCharacterContentChunkSize(indexedStringSizeLimit);
203 serializer.setAttributeValueMapMemoryLimit(stringsMemoryLimit);
204 serializer.setCharacterContentChunkMapMemoryLimit(stringsMemoryLimit);
205 }
206 return serializer;
207 }
209 /**
210 * Create a new (@link StAXDocumentParser} instance.
211 *
212 * @param in the InputStream to parse from.
213 * @param retainState if true the parser should retain the state of
214 * vocabulary tables for multiple parses.
215 * @return a new {@link StAXDocumentParser} instance.
216 */
217 /* package */ static StAXDocumentParser createNewStreamReader(InputStream in, boolean retainState) {
218 StAXDocumentParser parser = new StAXDocumentParser(in);
219 parser.setStringInterning(true);
220 if (retainState) {
221 /**
222 * Create a parser vocabulary external to the parser.
223 * This will ensure that the vocabulary will never be cleared
224 * for each parse and will be retained (and will grow)
225 * for each parse.
226 */
227 ParserVocabulary vocabulary = new ParserVocabulary();
228 parser.setVocabulary(vocabulary);
229 }
230 return parser;
231 }
233 /**
234 * Create a new (@link StAXDocumentParser} recyclable instance.
235 *
236 * @param in the InputStream to parse from.
237 * @param retainState if true the parser should retain the state of
238 * vocabulary tables for multiple parses.
239 * @return a new recyclable {@link StAXDocumentParser} instance.
240 */
241 /* package */ static StAXDocumentParser createNewStreamReaderRecyclable(InputStream in, boolean retainState) {
242 StAXDocumentParser parser = new FastInfosetStreamReaderRecyclable(in);
243 parser.setStringInterning(true);
244 parser.setForceStreamClose(true);
245 if (retainState) {
246 /**
247 * Create a parser vocabulary external to the parser.
248 * This will ensure that the vocabulary will never be cleared
249 * for each parse and will be retained (and will grow)
250 * for each parse.
251 */
252 ParserVocabulary vocabulary = new ParserVocabulary();
253 parser.setVocabulary(vocabulary);
254 }
255 return parser;
256 }
258 /**
259 * Method is copied from com.sun.xml.internal.ws.encoding.xml.XMLMessage
260 * @TODO method should be public in some util package?
261 *
262 * Finds if the stream has some content or not
263 *
264 * @return null if there is no data
265 * else stream to be used
266 */
267 private static InputStream hasSomeData(InputStream in) throws IOException {
268 if (in != null) {
269 if (in.available() < 1) {
270 if (!in.markSupported()) {
271 in = new BufferedInputStream(in);
272 }
273 in.mark(1);
274 if (in.read() != -1) {
275 in.reset();
276 } else {
277 in = null; // No data
278 }
279 }
280 }
281 return in;
282 }
283 }