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

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

mercurial