src/share/jaxws_classes/com/sun/xml/internal/ws/transport/http/server/ServerConnectionImpl.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

     1 /*
     2  * Copyright (c) 1997, 2012, 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.transport.http.server;
    28 import com.sun.istack.internal.NotNull;
    29 import com.sun.net.httpserver.Headers;
    30 import com.sun.net.httpserver.HttpExchange;
    31 import com.sun.net.httpserver.HttpsExchange;
    32 import com.sun.xml.internal.ws.api.message.Packet;
    33 import com.sun.xml.internal.ws.api.server.WSEndpoint;
    34 import com.sun.xml.internal.ws.api.server.WebServiceContextDelegate;
    35 import com.sun.xml.internal.ws.api.server.PortAddressResolver;
    36 import com.sun.xml.internal.ws.transport.http.HttpAdapter;
    37 import com.sun.xml.internal.ws.transport.http.WSHTTPConnection;
    38 import com.sun.xml.internal.ws.developer.JAXWSProperties;
    39 import com.sun.xml.internal.ws.resources.WsservletMessages;
    40 import com.sun.xml.internal.ws.util.ReadAllStream;
    42 import javax.xml.ws.handler.MessageContext;
    43 import javax.xml.ws.WebServiceException;
    44 import java.io.FilterInputStream;
    45 import java.io.FilterOutputStream;
    46 import java.io.IOException;
    47 import java.io.InputStream;
    48 import java.io.OutputStream;
    49 import java.net.URI;
    50 import java.security.Principal;
    51 import java.util.ArrayList;
    52 import java.util.List;
    53 import java.util.Map;
    54 import java.util.Set;
    57 /**
    58  * {@link WSHTTPConnection} used with Java SE endpoints. It provides connection
    59  * implementation using {@link HttpExchange} object.
    60  *
    61  * @author Jitendra Kotamraju
    62  */
    63 final class ServerConnectionImpl extends WSHTTPConnection implements WebServiceContextDelegate {
    65     private final HttpExchange httpExchange;
    66     private int status;
    67     private final HttpAdapter adapter;
    68     private LWHSInputStream in;
    69     private OutputStream out;
    72     public ServerConnectionImpl(@NotNull HttpAdapter adapter, @NotNull HttpExchange httpExchange) {
    73         this.adapter = adapter;
    74         this.httpExchange = httpExchange;
    75     }
    77     @Override
    78     @Property(value = {MessageContext.HTTP_REQUEST_HEADERS, Packet.INBOUND_TRANSPORT_HEADERS})
    79     public @NotNull Map<String,List<String>> getRequestHeaders() {
    80         return httpExchange.getRequestHeaders();
    81     }
    83     @Override
    84     public String getRequestHeader(String headerName) {
    85         return httpExchange.getRequestHeaders().getFirst(headerName);
    86     }
    88     @Override
    89     public void setResponseHeaders(Map<String,List<String>> headers) {
    90         Headers r = httpExchange.getResponseHeaders();
    91         r.clear();
    92         for(Map.Entry <String, List<String>> entry : headers.entrySet()) {
    93             String name = entry.getKey();
    94             List<String> values = entry.getValue();
    95             // ignore headers that interfere with our correct operations
    96             if (!"Content-Length".equalsIgnoreCase(name) && !"Content-Type".equalsIgnoreCase(name)) {
    97                 r.put(name,new ArrayList<String>(values));
    98             }
    99         }
   100     }
   102     @Override
   103         public void setResponseHeader(String key, List<String> value) {
   104                 httpExchange.getResponseHeaders().put(key, value);
   105         }
   107         @Override
   108         public Set<String> getRequestHeaderNames() {
   109         return httpExchange.getRequestHeaders().keySet();
   110         }
   112         @Override
   113         public List<String> getRequestHeaderValues(String headerName) {
   114                 return httpExchange.getRequestHeaders().get(headerName);
   115         }
   117     @Override
   118     @Property({MessageContext.HTTP_RESPONSE_HEADERS,Packet.OUTBOUND_TRANSPORT_HEADERS})
   119     public Map<String,List<String>> getResponseHeaders() {
   120         return httpExchange.getResponseHeaders();
   121     }
   123     @Override
   124     public void setContentTypeResponseHeader(@NotNull String value) {
   125         httpExchange.getResponseHeaders().set("Content-Type",value);
   126     }
   128     @Override
   129     public void setStatus(int status) {
   130         this.status = status;
   131     }
   133     @Override
   134     @Property(MessageContext.HTTP_RESPONSE_CODE)
   135     public int getStatus() {
   136         return status;
   137     }
   139     public @NotNull InputStream getInput() {
   140         if (in == null) {
   141             in = new LWHSInputStream(httpExchange.getRequestBody());
   142         }
   143         return in;
   144     }
   146     // Light weight http server's InputStream.close() throws exception if
   147     // all the bytes are not read. Work around until it is fixed.
   148     private static class LWHSInputStream extends FilterInputStream {
   149         // Workaround for "SJSXP XMLStreamReader.next() closes stream".
   150         boolean closed;
   151         boolean readAll;
   153         LWHSInputStream(InputStream in) {
   154             super(in);
   155         }
   157         void readAll() throws IOException {
   158             if (!closed && !readAll) {
   159                 ReadAllStream all = new ReadAllStream();
   160                 all.readAll(in, 4000000);
   161                 in.close();
   162                 in = all;
   163                 readAll = true;
   164             }
   165         }
   167         @Override
   168         public void close() throws IOException {
   169             if (!closed) {
   170                 readAll();
   171                 super.close();
   172                 closed = true;
   173             }
   174         }
   176     }
   179     public @NotNull OutputStream getOutput() throws IOException {
   180         if (out == null) {
   181             String lenHeader = httpExchange.getResponseHeaders().getFirst("Content-Length");
   182             int length = (lenHeader != null) ? Integer.parseInt(lenHeader) : 0;
   183             httpExchange.sendResponseHeaders(getStatus(), length);
   185             // Light weight http server's OutputStream.close() throws exception if
   186             // all the bytes are not read on the client side(StreamMessage on the client
   187             // side doesn't read all bytes.
   188             out =  new FilterOutputStream(httpExchange.getResponseBody()) {
   189                 boolean closed;
   190                 @Override
   191                 public void close() throws IOException {
   192                     if (!closed) {
   193                         closed = true;
   194                         // lwhs closes input stream, when you close the output stream
   195                         // This causes problems for streaming in one-way cases
   196                         in.readAll();
   197                         try {
   198                             super.close();
   199                         } catch(IOException ioe) {
   200                             // Ignoring purposefully.
   201                         }
   202                     }
   203                 }
   205                 // Otherwise, FilterOutpuStream writes byte by byte
   206                 @Override
   207                 public void write(byte[] buf, int start, int len) throws IOException {
   208                     out.write(buf, start, len);
   209                 }
   210             };
   211         }
   212         return out;
   213     }
   215     public @NotNull WebServiceContextDelegate getWebServiceContextDelegate() {
   216         return this;
   217     }
   219     public Principal getUserPrincipal(Packet request) {
   220         return httpExchange.getPrincipal();
   221     }
   223     public boolean isUserInRole(Packet request, String role) {
   224         return false;
   225     }
   227     public @NotNull String getEPRAddress(Packet request, WSEndpoint endpoint) {
   228         //return WSHttpHandler.getRequestAddress(httpExchange);
   230         PortAddressResolver resolver = adapter.owner.createPortAddressResolver(getBaseAddress(), endpoint.getImplementationClass());
   231         String address = resolver.getAddressFor(endpoint.getServiceName(), endpoint.getPortName().getLocalPart());
   232         if(address==null)
   233             throw new WebServiceException(WsservletMessages.SERVLET_NO_ADDRESS_AVAILABLE(endpoint.getPortName()));
   234         return address;
   236     }
   238     public String getWSDLAddress(@NotNull Packet request, @NotNull WSEndpoint endpoint) {
   239         String eprAddress = getEPRAddress(request,endpoint);
   240         if(adapter.getEndpoint().getPort() != null)
   241             return eprAddress+"?wsdl";
   242         else
   243             return null;
   244     }
   246     @Override
   247     public boolean isSecure() {
   248         return (httpExchange instanceof HttpsExchange);
   249     }
   251     @Override
   252     @Property(MessageContext.HTTP_REQUEST_METHOD)
   253     public @NotNull String getRequestMethod() {
   254         return httpExchange.getRequestMethod();
   255     }
   257     @Override
   258     @Property(MessageContext.QUERY_STRING)
   259     public String getQueryString() {
   260         URI requestUri = httpExchange.getRequestURI();
   261         String query = requestUri.getQuery();
   262         if (query != null)
   263             return query;
   264         return null;
   265     }
   267     @Override
   268     @Property(MessageContext.PATH_INFO)
   269     public String getPathInfo() {
   270         URI requestUri = httpExchange.getRequestURI();
   271         String reqPath = requestUri.getPath();
   272         String ctxtPath = httpExchange.getHttpContext().getPath();
   273         if (reqPath.length() > ctxtPath.length()) {
   274             return reqPath.substring(ctxtPath.length());
   275         }
   276         return null;
   277     }
   279     @Property(JAXWSProperties.HTTP_EXCHANGE)
   280     public HttpExchange getExchange() {
   281         return httpExchange;
   282     }
   284     @Override @NotNull
   285     public String getBaseAddress() {
   286         /*
   287          * Computes the Endpoint's address from the request. Use "Host" header
   288          * so that it has correct address(IP address or someother hostname)
   289          * through which the application reached the endpoint.
   290          *
   291          */
   292         StringBuilder strBuf = new StringBuilder();
   293         strBuf.append((httpExchange instanceof HttpsExchange) ? "https" : "http");
   294         strBuf.append("://");
   296         String hostHeader = httpExchange.getRequestHeaders().getFirst("Host");
   297         if (hostHeader != null) {
   298             strBuf.append(hostHeader);   // Uses Host header
   299         } else {
   300             strBuf.append(httpExchange.getLocalAddress().getHostName());
   301             strBuf.append(":");
   302             strBuf.append(httpExchange.getLocalAddress().getPort());
   303         }
   304         //Do not include URL pattern here
   305         //strBuf.append(httpExchange.getRequestURI().getPath());
   307         return strBuf.toString();
   308     }
   310     @Override
   311     public String getProtocol() {
   312         return httpExchange.getProtocol();
   313     }
   315     @Override
   316     public void setContentLengthResponseHeader(int value) {
   317         httpExchange.getResponseHeaders().set("Content-Length", ""+value);
   318     }
   320         @Override
   321         public String getRequestURI() {
   322                 return httpExchange.getRequestURI().toString();
   323         }
   325         @Override
   326         public String getRequestScheme() {
   327                 return (httpExchange instanceof HttpsExchange) ? "https" : "http";
   328         }
   330         @Override
   331         public String getServerName() {
   332                 return httpExchange.getLocalAddress().getHostName();
   333         }
   335         @Override
   336         public int getServerPort() {
   337                 return httpExchange.getLocalAddress().getPort();
   338         }
   340     protected PropertyMap getPropertyMap() {
   341         return model;
   342     }
   344     private static final PropertyMap model;
   346     static {
   347         model = parse(ServerConnectionImpl.class);
   348     }
   349 }

mercurial