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  */
25 
26 package com.sun.xml.internal.ws.transport.http.server;
27 
28 import com.sun.istack.internal.NotNull;
29 import com.sun.xml.internal.ws.api.message.Packet;
30 import com.sun.xml.internal.ws.api.server.WSEndpoint;
31 import com.sun.xml.internal.ws.api.server.WebServiceContextDelegate;
32 import com.sun.xml.internal.ws.api.server.PortAddressResolver;
33 import com.sun.xml.internal.ws.transport.http.HttpAdapter;
34 import com.sun.xml.internal.ws.transport.http.WSHTTPConnection;
35 import com.sun.xml.internal.ws.developer.JAXWSProperties;
36 import com.sun.xml.internal.ws.resources.WsservletMessages;
37 
38 import javax.xml.ws.handler.MessageContext;
39 import javax.xml.ws.WebServiceException;
40 import javax.xml.ws.spi.http.HttpExchange;
41 import java.io.IOException;
42 import java.io.InputStream;
43 import java.io.OutputStream;
44 import java.security.Principal;
45 import java.util.ArrayList;
46 import java.util.List;
47 import java.util.Map;
48 import java.util.Set;
49 
50 /**
51  * {@link WSHTTPConnection} used with Java SE endpoints. It provides connection
52  * implementation using {@link HttpExchange} object.
53  *
54  * @author Jitendra Kotamraju
55  */
56 final class PortableConnectionImpl extends WSHTTPConnection implements WebServiceContextDelegate {
57 
58     private final HttpExchange httpExchange;
59     private int status;
60     private final HttpAdapter adapter;
61     private boolean outputWritten;
62 
PortableConnectionImpl(@otNull HttpAdapter adapter, @NotNull HttpExchange httpExchange)63     public PortableConnectionImpl(@NotNull HttpAdapter adapter, @NotNull HttpExchange httpExchange) {
64         this.adapter = adapter;
65         this.httpExchange = httpExchange;
66     }
67 
68     @Override
69     @Property(value = {MessageContext.HTTP_REQUEST_HEADERS, Packet.INBOUND_TRANSPORT_HEADERS})
getRequestHeaders()70     public @NotNull Map<String,List<String>> getRequestHeaders() {
71         return httpExchange.getRequestHeaders();
72     }
73 
74     @Override
getRequestHeader(String headerName)75     public String getRequestHeader(String headerName) {
76         return httpExchange.getRequestHeader(headerName);
77     }
78 
79     @Override
setResponseHeaders(Map<String,List<String>> headers)80     public void setResponseHeaders(Map<String,List<String>> headers) {
81         Map<String, List<String>> r = httpExchange.getResponseHeaders();
82         r.clear();
83         for(Map.Entry <String, List<String>> entry : headers.entrySet()) {
84             String name = entry.getKey();
85             List<String> values = entry.getValue();
86             // ignore headers that interfere with our correct operations
87             if (!name.equalsIgnoreCase("Content-Length") && !name.equalsIgnoreCase("Content-Type")) {
88                 r.put(name,new ArrayList<String>(values));
89             }
90         }
91     }
92 
93     @Override
setResponseHeader(String key, List<String> value)94     public void setResponseHeader(String key, List<String> value) {
95         httpExchange.getResponseHeaders().put(key, value);
96     }
97 
98     @Override
getRequestHeaderNames()99     public Set<String> getRequestHeaderNames() {
100         return httpExchange.getRequestHeaders().keySet();
101     }
102 
103     @Override
getRequestHeaderValues(String headerName)104     public List<String> getRequestHeaderValues(String headerName) {
105         return httpExchange.getRequestHeaders().get(headerName);
106     }
107 
108     @Override
109     @Property({MessageContext.HTTP_RESPONSE_HEADERS,Packet.OUTBOUND_TRANSPORT_HEADERS})
getResponseHeaders()110     public Map<String,List<String>> getResponseHeaders() {
111         return httpExchange.getResponseHeaders();
112     }
113 
114     @Override
setContentTypeResponseHeader(@otNull String value)115     public void setContentTypeResponseHeader(@NotNull String value) {
116         httpExchange.addResponseHeader("Content-Type", value);
117     }
118 
119     @Override
setStatus(int status)120     public void setStatus(int status) {
121         this.status = status;
122     }
123 
124     @Override
125     @Property(MessageContext.HTTP_RESPONSE_CODE)
getStatus()126     public int getStatus() {
127         return status;
128     }
129 
getInput()130     public @Override @NotNull InputStream getInput() throws IOException {
131         return httpExchange.getRequestBody();
132     }
133 
getOutput()134     public @Override @NotNull OutputStream getOutput() throws IOException {
135         assert !outputWritten;
136         outputWritten = true;
137 
138         httpExchange.setStatus(getStatus());
139         return httpExchange.getResponseBody();
140     }
141 
getWebServiceContextDelegate()142     public @Override @NotNull WebServiceContextDelegate getWebServiceContextDelegate() {
143         return this;
144     }
145 
146     @Override
getUserPrincipal(Packet request)147     public Principal getUserPrincipal(Packet request) {
148         return httpExchange.getUserPrincipal();
149     }
150 
151     @Override
isUserInRole(Packet request, String role)152     public boolean isUserInRole(Packet request, String role) {
153         return httpExchange.isUserInRole(role);
154     }
155 
getEPRAddress(Packet request, WSEndpoint endpoint)156     public @Override @NotNull String getEPRAddress(Packet request, WSEndpoint endpoint) {
157         PortAddressResolver resolver = adapter.owner.createPortAddressResolver(getBaseAddress(), endpoint.getImplementationClass());
158         String address = resolver.getAddressFor(endpoint.getServiceName(), endpoint.getPortName().getLocalPart());
159         if(address==null) {
160             throw new WebServiceException(WsservletMessages.SERVLET_NO_ADDRESS_AVAILABLE(endpoint.getPortName()));
161         }
162         return address;
163     }
164 
165     @Property(MessageContext.SERVLET_CONTEXT)
getServletContext()166     public Object getServletContext() {
167         return httpExchange.getAttribute(MessageContext.SERVLET_CONTEXT);
168     }
169 
170     @Property(MessageContext.SERVLET_RESPONSE)
getServletResponse()171     public Object getServletResponse() {
172         return httpExchange.getAttribute(MessageContext.SERVLET_RESPONSE);
173     }
174 
175     @Property(MessageContext.SERVLET_REQUEST)
getServletRequest()176     public Object getServletRequest() {
177         return httpExchange.getAttribute(MessageContext.SERVLET_REQUEST);
178     }
179 
180     @Override
getWSDLAddress(@otNull Packet request, @NotNull WSEndpoint endpoint)181     public String getWSDLAddress(@NotNull Packet request, @NotNull WSEndpoint endpoint) {
182         String eprAddress = getEPRAddress(request,endpoint);
183         if(adapter.getEndpoint().getPort() != null) {
184             return eprAddress+"?wsdl";
185         } else {
186             return null;
187         }
188     }
189 
190     @Override
isSecure()191     public boolean isSecure() {
192         return httpExchange.getScheme().equals("https");
193     }
194 
195     @Override
196     @Property(MessageContext.HTTP_REQUEST_METHOD)
getRequestMethod()197     public @NotNull String getRequestMethod() {
198         return httpExchange.getRequestMethod();
199     }
200 
201     @Override
202     @Property(MessageContext.QUERY_STRING)
getQueryString()203     public String getQueryString() {
204         return httpExchange.getQueryString();
205     }
206 
207     @Override
208     @Property(MessageContext.PATH_INFO)
getPathInfo()209     public String getPathInfo() {
210         return httpExchange.getPathInfo();
211     }
212 
213     @Property(JAXWSProperties.HTTP_EXCHANGE)
getExchange()214     public HttpExchange getExchange() {
215         return httpExchange;
216     }
217 
218     @Override @NotNull
getBaseAddress()219     public String getBaseAddress() {
220         StringBuilder sb = new StringBuilder();
221         sb.append(httpExchange.getScheme());
222         sb.append("://");
223         sb.append(httpExchange.getLocalAddress().getHostName());
224         sb.append(":");
225         sb.append(httpExchange.getLocalAddress().getPort());
226         sb.append(httpExchange.getContextPath());
227         return sb.toString();
228     }
229 
230     @Override
getProtocol()231     public String getProtocol() {
232         return httpExchange.getProtocol();
233     }
234 
235     @Override
setContentLengthResponseHeader(int value)236     public void setContentLengthResponseHeader(int value) {
237         httpExchange.addResponseHeader("Content-Length", ""+value);
238     }
239 
240     @Override
getRequestURI()241     public String getRequestURI() {
242         return httpExchange.getRequestURI().toString();
243     }
244 
245     @Override
getRequestScheme()246     public String getRequestScheme() {
247         return httpExchange.getScheme();
248     }
249 
250     @Override
getServerName()251     public String getServerName() {
252         return httpExchange.getLocalAddress().getHostName();
253     }
254 
255     @Override
getServerPort()256     public int getServerPort() {
257         return httpExchange.getLocalAddress().getPort();
258     }
259 
260     @Override
getPropertyMap()261     protected PropertyMap getPropertyMap() {
262         return model;
263     }
264 
265     private static final PropertyMap model;
266 
267     static {
268         model = parse(PortableConnectionImpl.class);
269     }
270 }
271