Wed, 27 Apr 2016 01:27:09 +0800
Initial load
http://hg.openjdk.java.net/jdk8u/jdk8u/jaxws/
changeset: 657:d47a47f961ee
tag: jdk8u25-b17
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 static com.sun.xml.internal.ws.binding.WebServiceFeatureList.getSoapVersion;
30 import com.oracle.webservices.internal.impl.encoding.StreamDecoderImpl;
31 import com.oracle.webservices.internal.impl.internalspi.encoding.StreamDecoder;
32 import com.sun.istack.internal.NotNull;
33 import com.sun.istack.internal.Nullable;
34 import com.sun.xml.internal.stream.buffer.MutableXMLStreamBuffer;
35 import com.sun.xml.internal.stream.buffer.XMLStreamBuffer;
36 import com.sun.xml.internal.stream.buffer.XMLStreamBufferMark;
37 import com.sun.xml.internal.stream.buffer.stax.StreamReaderBufferCreator;
38 import com.sun.xml.internal.ws.api.SOAPVersion;
39 import com.sun.xml.internal.ws.api.WSBinding;
40 import com.sun.xml.internal.ws.api.WSFeatureList;
41 import com.sun.xml.internal.ws.api.message.AttachmentSet;
42 import com.sun.xml.internal.ws.api.message.Header;
43 import com.sun.xml.internal.ws.api.message.HeaderList;
44 import com.sun.xml.internal.ws.api.message.Message;
45 import com.sun.xml.internal.ws.api.message.Packet;
46 import com.sun.xml.internal.ws.api.pipe.ContentType;
47 import com.sun.xml.internal.ws.api.streaming.XMLStreamWriterFactory;
48 import com.sun.xml.internal.ws.developer.SerializationFeature;
49 import com.sun.xml.internal.ws.message.AttachmentSetImpl;
50 import com.sun.xml.internal.ws.message.stream.StreamMessage;
51 import com.sun.xml.internal.ws.protocol.soap.VersionMismatchException;
52 import com.sun.xml.internal.ws.server.UnsupportedMediaException;
53 import com.sun.xml.internal.ws.streaming.XMLStreamReaderUtil;
54 import com.sun.xml.internal.ws.util.ServiceFinder;
56 import javax.xml.stream.XMLStreamConstants;
57 import javax.xml.stream.XMLStreamException;
58 import javax.xml.stream.XMLStreamReader;
59 import javax.xml.stream.XMLStreamWriter;
60 import javax.xml.ws.WebServiceException;
61 import java.io.IOException;
62 import java.io.InputStream;
63 import java.io.OutputStream;
64 import java.nio.channels.ReadableByteChannel;
65 import java.nio.channels.WritableByteChannel;
66 import java.nio.charset.Charset;
67 import java.util.HashMap;
68 import java.util.List;
69 import java.util.Map;
71 /**
72 * A stream SOAP codec.
73 *
74 * @author Paul Sandoz
75 */
76 @SuppressWarnings({"StringEquality"})
77 public abstract class StreamSOAPCodec implements com.sun.xml.internal.ws.api.pipe.StreamSOAPCodec, RootOnlyCodec {
79 private static final String SOAP_ENVELOPE = "Envelope";
80 private static final String SOAP_HEADER = "Header";
81 private static final String SOAP_BODY = "Body";
83 private final SOAPVersion soapVersion;
84 protected final SerializationFeature serializationFeature;
86 private final StreamDecoder streamDecoder;
88 // charset of last decoded message. Will be used for encoding server's
89 // response messages with the request message's encoding
90 // it will stored in the packet.invocationProperties
91 private final static String DECODED_MESSAGE_CHARSET = "decodedMessageCharset";
93 /*package*/ StreamSOAPCodec(SOAPVersion soapVersion) {
94 this(soapVersion, null);
95 }
97 /*package*/ StreamSOAPCodec(WSBinding binding) {
98 this(binding.getSOAPVersion(), binding.getFeature(SerializationFeature.class));
99 }
101 StreamSOAPCodec(WSFeatureList features) {
102 this(getSoapVersion(features), features.get(SerializationFeature.class));
103 }
105 private StreamSOAPCodec(SOAPVersion soapVersion, @Nullable SerializationFeature sf) {
106 this.soapVersion = soapVersion;
107 this.serializationFeature = sf;
108 this.streamDecoder = selectStreamDecoder();
109 }
111 private StreamDecoder selectStreamDecoder() {
112 for (StreamDecoder sd : ServiceFinder.find(StreamDecoder.class)) {
113 return sd;
114 }
116 return new StreamDecoderImpl();
117 }
119 public ContentType getStaticContentType(Packet packet) {
120 return getContentType(packet);
121 }
123 public ContentType encode(Packet packet, OutputStream out) {
124 if (packet.getMessage() != null) {
125 String encoding = getPacketEncoding(packet);
126 packet.invocationProperties.remove(DECODED_MESSAGE_CHARSET);
127 XMLStreamWriter writer = XMLStreamWriterFactory.create(out, encoding);
128 try {
129 packet.getMessage().writeTo(writer);
130 writer.flush();
131 } catch (XMLStreamException e) {
132 throw new WebServiceException(e);
133 }
134 XMLStreamWriterFactory.recycle(writer);
135 }
136 return getContentType(packet);
137 }
139 protected abstract ContentType getContentType(Packet packet);
141 protected abstract String getDefaultContentType();
143 public ContentType encode(Packet packet, WritableByteChannel buffer) {
144 //TODO: not yet implemented
145 throw new UnsupportedOperationException();
146 }
148 protected abstract List<String> getExpectedContentTypes();
150 public void decode(InputStream in, String contentType, Packet packet) throws IOException {
151 decode(in, contentType, packet, new AttachmentSetImpl());
152 }
154 /*
155 * Checks against expected Content-Type headers that is handled by a codec
156 *
157 * @param ct the Content-Type of the request
158 * @param expected expected Content-Types for a codec
159 * @return true if the codec supports this Content-Type
160 * false otherwise
161 */
162 private static boolean isContentTypeSupported(String ct, List<String> expected) {
163 for(String contentType : expected) {
164 if (ct.contains(contentType)) {
165 return true;
166 }
167 }
168 return false;
169 }
171 /**
172 * Decodes a message from {@link XMLStreamReader} that points to
173 * the beginning of a SOAP infoset.
174 *
175 * @param reader
176 * can point to the start document or the start element.
177 */
178 public final @NotNull Message decode(@NotNull XMLStreamReader reader) {
179 return decode(reader,new AttachmentSetImpl());
180 }
182 /**
183 * Decodes a message from {@link XMLStreamReader} that points to
184 * the beginning of a SOAP infoset.
185 *
186 * @param reader
187 * can point to the start document or the start element.
188 * @param attachmentSet
189 * {@link StreamSOAPCodec} can take attachments parsed outside,
190 * so that this codec can be used as a part of a biggre codec
191 * (like MIME multipart codec.)
192 */
193 public final Message decode(XMLStreamReader reader, @NotNull AttachmentSet attachmentSet) {
194 return decode(soapVersion, reader, attachmentSet);
195 }
197 public static final Message decode(SOAPVersion soapVersion, XMLStreamReader reader, @NotNull AttachmentSet attachmentSet) {
198 // Move to soap:Envelope and verify
199 if(reader.getEventType()!=XMLStreamConstants.START_ELEMENT)
200 XMLStreamReaderUtil.nextElementContent(reader);
201 XMLStreamReaderUtil.verifyReaderState(reader,XMLStreamConstants.START_ELEMENT);
202 if (SOAP_ENVELOPE.equals(reader.getLocalName()) && !soapVersion.nsUri.equals(reader.getNamespaceURI())) {
203 throw new VersionMismatchException(soapVersion, soapVersion.nsUri, reader.getNamespaceURI());
204 }
205 XMLStreamReaderUtil.verifyTag(reader, soapVersion.nsUri, SOAP_ENVELOPE);
206 return new StreamMessage(soapVersion, reader, attachmentSet);
207 }
209 public void decode(ReadableByteChannel in, String contentType, Packet packet ) {
210 throw new UnsupportedOperationException();
211 }
213 public final StreamSOAPCodec copy() {
214 return this;
215 }
217 public void decode(InputStream in, String contentType, Packet packet, AttachmentSet att ) throws IOException {
218 List<String> expectedContentTypes = getExpectedContentTypes();
219 if (contentType != null && !isContentTypeSupported(contentType,expectedContentTypes)) {
220 throw new UnsupportedMediaException(contentType, expectedContentTypes);
221 }
222 com.oracle.webservices.internal.api.message.ContentType pct = packet.getInternalContentType();
223 ContentTypeImpl cti = (pct != null && pct instanceof ContentTypeImpl) ?
224 (ContentTypeImpl)pct : new ContentTypeImpl(contentType);
225 String charset = cti.getCharSet();
226 if (charset != null && !Charset.isSupported(charset)) {
227 throw new UnsupportedMediaException(charset);
228 }
229 if (charset != null) {
230 packet.invocationProperties.put(DECODED_MESSAGE_CHARSET, charset);
231 } else {
232 packet.invocationProperties.remove(DECODED_MESSAGE_CHARSET);
233 }
234 packet.setMessage(streamDecoder.decode(in, charset, att, soapVersion));
235 }
237 public void decode(ReadableByteChannel in, String contentType, Packet response, AttachmentSet att ) {
238 throw new UnsupportedOperationException();
239 }
241 /*
242 * Creates a new {@link StreamSOAPCodec} instance.
243 */
244 public static StreamSOAPCodec create(SOAPVersion version) {
245 if(version==null)
246 // this decoder is for SOAP, not for XML/HTTP
247 throw new IllegalArgumentException();
248 switch(version) {
249 case SOAP_11:
250 return new StreamSOAP11Codec();
251 case SOAP_12:
252 return new StreamSOAP12Codec();
253 default:
254 throw new AssertionError();
255 }
256 }
258 /*
259 * Creates a new {@link StreamSOAPCodec} instance using binding
260 */
261 public static StreamSOAPCodec create(WSFeatureList features) {
262 SOAPVersion version = getSoapVersion(features);
263 if(version==null)
264 // this decoder is for SOAP, not for XML/HTTP
265 throw new IllegalArgumentException();
266 switch(version) {
267 case SOAP_11:
268 return new StreamSOAP11Codec(features);
269 case SOAP_12:
270 return new StreamSOAP12Codec(features);
271 default:
272 throw new AssertionError();
273 }
274 }
276 /**
277 * Creates a new {@link StreamSOAPCodec} instance using binding
278 *
279 * @deprecated use {@link #create(WSFeatureList)}
280 */
281 public static StreamSOAPCodec create(WSBinding binding) {
282 SOAPVersion version = binding.getSOAPVersion();
283 if(version==null)
284 // this decoder is for SOAP, not for XML/HTTP
285 throw new IllegalArgumentException();
286 switch(version) {
287 case SOAP_11:
288 return new StreamSOAP11Codec(binding);
289 case SOAP_12:
290 return new StreamSOAP12Codec(binding);
291 default:
292 throw new AssertionError();
293 }
294 }
296 private String getPacketEncoding(Packet packet) {
297 // If SerializationFeature is set, just use that encoding
298 if (serializationFeature != null && serializationFeature.getEncoding() != null) {
299 return serializationFeature.getEncoding().equals("")
300 ? SOAPBindingCodec.DEFAULT_ENCODING : serializationFeature.getEncoding();
301 }
303 if (packet != null && packet.endpoint != null) {
304 // Use request message's encoding for Server-side response messages
305 String charset = (String)packet.invocationProperties.get(DECODED_MESSAGE_CHARSET);
306 return charset == null
307 ? SOAPBindingCodec.DEFAULT_ENCODING : charset;
308 }
310 // Use default encoding for client-side request messages
311 return SOAPBindingCodec.DEFAULT_ENCODING;
312 }
314 protected ContentTypeImpl.Builder getContenTypeBuilder(Packet packet) {
315 ContentTypeImpl.Builder b = new ContentTypeImpl.Builder();
316 String encoding = getPacketEncoding(packet);
317 if (SOAPBindingCodec.DEFAULT_ENCODING.equalsIgnoreCase(encoding)) {
318 b.contentType = getDefaultContentType();
319 b.charset = SOAPBindingCodec.DEFAULT_ENCODING;
320 return b;
321 }
322 b.contentType = getMimeType()+" ;charset="+encoding;
323 b.charset = encoding;
324 return b;
325 }
327 }