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

Thu, 31 Aug 2017 15:18:52 +0800

author
aoqi
date
Thu, 31 Aug 2017 15:18:52 +0800
changeset 637
9c07ef4934dd
parent 397
b99d7e355d4b
parent 0
373ffda63c9a
permissions
-rw-r--r--

merge

     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 }

mercurial