| /* |
| * Copyright 2005-2006 Sun Microsystems, Inc. All Rights Reserved. |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| * |
| * This code is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License version 2 only, as |
| * published by the Free Software Foundation. Sun designates this |
| * particular file as subject to the "Classpath" exception as provided |
| * by Sun in the LICENSE file that accompanied this code. |
| * |
| * This code is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| * version 2 for more details (a copy is included in the LICENSE file that |
| * accompanied this code). |
| * |
| * You should have received a copy of the GNU General Public License version |
| * 2 along with this work; if not, write to the Free Software Foundation, |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| * |
| * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, |
| * CA 95054 USA or visit www.sun.com if you need additional information or |
| * have any questions. |
| */ |
| |
| package com.sun.xml.internal.ws.transport.http.server; |
| |
| import com.sun.istack.internal.NotNull; |
| import com.sun.net.httpserver.Headers; |
| import com.sun.net.httpserver.HttpExchange; |
| import com.sun.net.httpserver.HttpsExchange; |
| import com.sun.xml.internal.ws.api.message.Packet; |
| import com.sun.xml.internal.ws.api.server.WSEndpoint; |
| import com.sun.xml.internal.ws.api.server.WebServiceContextDelegate; |
| import com.sun.xml.internal.ws.transport.http.HttpAdapter; |
| import com.sun.xml.internal.ws.transport.http.WSHTTPConnection; |
| |
| import javax.xml.ws.handler.MessageContext; |
| import java.io.*; |
| import java.net.URI; |
| import java.security.Principal; |
| import java.util.ArrayList; |
| import java.util.List; |
| import java.util.Map; |
| |
| |
| /** |
| * {@link WSHTTPConnection} used with Java SE endpoints. It provides connection |
| * implementation using {@link HttpExchange} object. |
| * |
| * @author Jitendra Kotamraju |
| */ |
| final class ServerConnectionImpl extends WSHTTPConnection implements WebServiceContextDelegate { |
| |
| private final HttpExchange httpExchange; |
| private int status; |
| private final HttpAdapter adapter; |
| private boolean outputWritten; |
| |
| |
| public ServerConnectionImpl(@NotNull HttpAdapter adapter, @NotNull HttpExchange httpExchange) { |
| this.adapter = adapter; |
| this.httpExchange = httpExchange; |
| } |
| |
| @Override |
| @Property(value = {MessageContext.HTTP_REQUEST_HEADERS, Packet.INBOUND_TRANSPORT_HEADERS}) |
| public @NotNull Map<String,List<String>> getRequestHeaders() { |
| return httpExchange.getRequestHeaders(); |
| } |
| |
| @Override |
| public String getRequestHeader(String headerName) { |
| return httpExchange.getRequestHeaders().getFirst(headerName); |
| } |
| |
| @Override |
| public void setResponseHeaders(Map<String,List<String>> headers) { |
| Headers r = httpExchange.getResponseHeaders(); |
| r.clear(); |
| for(Map.Entry <String, List<String>> entry : headers.entrySet()) { |
| String name = entry.getKey(); |
| List<String> values = entry.getValue(); |
| if (name.equalsIgnoreCase("Content-Length") || name.equalsIgnoreCase("Content-Type")) { |
| continue; // ignore headers that interfere with our correct operations |
| } else { |
| r.put(name,new ArrayList<String>(values)); |
| } |
| } |
| } |
| @Override |
| @Property({MessageContext.HTTP_RESPONSE_HEADERS,Packet.OUTBOUND_TRANSPORT_HEADERS}) |
| public Map<String,List<String>> getResponseHeaders() { |
| return httpExchange.getResponseHeaders(); |
| } |
| |
| @Override |
| public void setContentTypeResponseHeader(@NotNull String value) { |
| httpExchange.getResponseHeaders().set("Content-Type",value); |
| } |
| |
| @Override |
| public void setStatus(int status) { |
| this.status = status; |
| } |
| |
| @Override |
| @Property(MessageContext.HTTP_RESPONSE_CODE) |
| public int getStatus() { |
| return status; |
| } |
| |
| public @NotNull InputStream getInput() { |
| // Light weight http server's InputStream.close() throws exception if |
| // all the bytes are not read. Work around until it is fixed. |
| return new FilterInputStream(httpExchange.getRequestBody()) { |
| @Override |
| public void close() throws IOException { |
| try { |
| while (read() != -1); |
| } catch(IOException e) { |
| //Ignore |
| } |
| super.close(); |
| } |
| }; |
| } |
| |
| public @NotNull OutputStream getOutput() throws IOException { |
| assert !outputWritten; |
| outputWritten = true; |
| |
| List<String> lenHeader = httpExchange.getResponseHeaders().get("Content-Length"); |
| int length = (lenHeader != null) ? Integer.parseInt(lenHeader.get(0)) : 0; |
| httpExchange.sendResponseHeaders(getStatus(), length); |
| |
| // Light weight http server's OutputStream.close() throws exception if |
| // all the bytes are not read on the client side(StreamMessage on the client |
| // side doesn't read all bytes. |
| return new FilterOutputStream(httpExchange.getResponseBody()) { |
| @Override |
| public void close() throws IOException { |
| try { |
| super.close(); |
| } catch(IOException ioe) { |
| // Ignoring purposefully. |
| } |
| } |
| }; |
| } |
| |
| public @NotNull WebServiceContextDelegate getWebServiceContextDelegate() { |
| return this; |
| } |
| |
| public Principal getUserPrincipal(Packet request) { |
| return httpExchange.getPrincipal(); |
| } |
| |
| public boolean isUserInRole(Packet request, String role) { |
| return false; |
| } |
| |
| public @NotNull String getEPRAddress(Packet request, WSEndpoint endpoint) { |
| return WSHttpHandler.getRequestAddress(httpExchange); |
| } |
| |
| public String getWSDLAddress(@NotNull Packet request, @NotNull WSEndpoint endpoint) { |
| String eprAddress = getEPRAddress(request,endpoint); |
| if(adapter.getEndpoint().getPort() != null) |
| return eprAddress+"?wsdl"; |
| else |
| return null; |
| } |
| |
| @Override |
| public boolean isSecure() { |
| return (httpExchange instanceof HttpsExchange); |
| } |
| |
| @Override |
| @Property(MessageContext.HTTP_REQUEST_METHOD) |
| public @NotNull String getRequestMethod() { |
| return httpExchange.getRequestMethod(); |
| } |
| |
| @Override |
| @Property(MessageContext.QUERY_STRING) |
| public String getQueryString() { |
| URI requestUri = httpExchange.getRequestURI(); |
| String query = requestUri.getQuery(); |
| if (query != null) |
| return query; |
| return null; |
| } |
| |
| @Override |
| @Property(MessageContext.PATH_INFO) |
| public String getPathInfo() { |
| URI requestUri = httpExchange.getRequestURI(); |
| String reqPath = requestUri.getPath(); |
| String ctxtPath = httpExchange.getHttpContext().getPath(); |
| if (reqPath.length() > ctxtPath.length()) { |
| return reqPath.substring(ctxtPath.length()); |
| } |
| return null; |
| } |
| |
| @Override |
| public String getProtocol() { |
| return httpExchange.getProtocol(); |
| } |
| |
| @Override |
| public void setContentLengthResponseHeader(int value) { |
| httpExchange.getResponseHeaders().set("Content-Length", ""+value); |
| } |
| |
| protected PropertyMap getPropertyMap() { |
| return model; |
| } |
| |
| private static final PropertyMap model; |
| |
| static { |
| model = parse(ServerConnectionImpl.class); |
| } |
| } |