1/*
2 * Copyright (c) 2005, 2015, 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
26package javax.xml.ws.spi.http;
27
28import javax.xml.ws.handler.MessageContext;
29import java.io.InputStream;
30import java.io.OutputStream;
31import java.io.IOException;
32import java.net.InetSocketAddress;
33import java.util.List;
34import java.util.Map;
35import java.util.Set;
36import java.security.Principal;
37
38/**
39 * This class encapsulates a HTTP request received and a
40 * response to be generated in one exchange. It provides methods
41 * for examining the request from the client, and for building and
42 * sending the response.
43 * <p>
44 * A {@code HttpExchange} must be closed to free or reuse
45 * underlying resources. The effect of failing to close an exchange
46 * is undefined.
47 *
48 * @author Jitendra Kotamraju
49 * @since 1.7, JAX-WS 2.2
50 */
51public abstract class HttpExchange {
52
53    /**
54     * Standard property: cipher suite value when the request is received
55     * over HTTPS
56     * <p>Type: String
57     */
58    public static final String REQUEST_CIPHER_SUITE =
59            "javax.xml.ws.spi.http.request.cipher.suite";
60
61    /**
62     * Standard property: bit size of the algorithm when the request is
63     * received over HTTPS
64     * <p>Type: Integer
65     */
66    public static final String REQUEST_KEY_SIZE =
67            "javax.xml.ws.spi.http.request.key.size";
68
69    /**
70     * Standard property: A SSL certificate, if any, associated with the request
71     *
72     * <p>Type: java.security.cert.X509Certificate[]
73     * The order of this array is defined as being in ascending order of trust.
74     * The first certificate in the chain is the one set by the client, the next
75     * is the one used to authenticate the first, and so on.
76     */
77    public static final String REQUEST_X509CERTIFICATE =
78            "javax.xml.ws.spi.http.request.cert.X509Certificate";
79
80    /**
81     * Returns an immutable Map containing the HTTP headers that were
82     * included with this request. The keys in this Map will be the header
83     * names, while the values will be a List of Strings containing each value
84     * that was included (either for a header that was listed several times,
85     * or one that accepts a comma-delimited list of values on a single line).
86     * In either of these cases, the values for the header name will be
87     * presented in the order that they were included in the request.
88     * <p>
89     * The keys in Map are case-insensitive.
90     *
91     * @return an immutable Map which can be used to access request headers
92     */
93    public abstract Map<String, List<String>> getRequestHeaders();
94
95    /**
96     * Returns the value of the specified request header. If the request
97     * did not include a header of the specified name, this method returns
98     * null. If there are multiple headers with the same name, this method
99     * returns the first header in the request. The header name is
100     * case-insensitive. This is a convienence method to get a header
101     * (instead of using the {@link #getRequestHeaders}).
102     *
103     * @param name the name of the request header
104     * @return returns the value of the requested header,
105     *         or null if the request does not have a header of that name
106     */
107     public abstract String getRequestHeader(String name);
108
109    /**
110     * Returns a mutable Map into which the HTTP response headers can be stored
111     * and which will be transmitted as part of this response. The keys in the
112     * Map will be the header names, while the values must be a List of Strings
113     * containing each value that should be included multiple times
114     * (in the order that they should be included).
115     * <p>
116     * The keys in Map are case-insensitive.
117     *
118     * @return a mutable Map which can be used to set response headers.
119     */
120    public abstract Map<String, List<String>> getResponseHeaders();
121
122    /**
123     * Adds a response header with the given name and value. This method
124     * allows a response header to have multiple values. This is a
125     * convenience method to add a response header(instead of using the
126     * {@link #getResponseHeaders()}).
127     *
128     * @param name the name of the header
129     * @param value the additional header value. If it contains octet string,
130     *        it should be encoded according to
131     *        RFC 2047 (http://www.ietf.org/rfc/rfc2047.txt)
132     *
133     * @see #getResponseHeaders
134     */
135    public abstract void addResponseHeader(String name, String value);
136
137    /**
138     * Returns the part of the request's URI from the protocol
139     * name up to the query string in the first line of the HTTP request.
140     * Container doesn't decode this string.
141     *
142     * @return the request URI
143     */
144    public abstract String getRequestURI();
145
146    /**
147     * Returns the context path of all the endpoints in an application.
148     * This path is the portion of the request URI that indicates the
149     * context of the request. The context path always comes first in a
150     * request URI. The path starts with a "/" character but does not
151     * end with a "/" character. If this method returns "", the request
152     * is for default context. The container does not decode this string.
153     *
154     * <p>
155     * Context path is used in computing the endpoint address. See
156     * {@link HttpContext#getPath}
157     *
158     * @return context path of all the endpoints in an application
159     * @see HttpContext#getPath
160     */
161    public abstract String getContextPath();
162
163    /**
164     * Get the HTTP request method
165     *
166     * @return the request method
167     */
168    public abstract String getRequestMethod();
169
170    /**
171     * Returns a {@link HttpContext} for this exchange.
172     * Container matches the request with the associated Endpoint's HttpContext
173     *
174     * @return the HttpContext for this exchange
175     */
176    public abstract HttpContext getHttpContext();
177
178    /**
179     * This must be called to end an exchange. Container takes care of
180     * closing request and response streams. This must be called so that
181     * the container can free or reuse underlying resources.
182     *
183     * @throws IOException if any i/o error
184     */
185    public abstract void close() throws IOException;
186
187    /**
188     * Returns a stream from which the request body can be read.
189     * Multiple calls to this method will return the same stream.
190     *
191     * @return the stream from which the request body can be read.
192     * @throws IOException if any i/o error during request processing
193     */
194    public abstract InputStream getRequestBody() throws IOException;
195
196    /**
197     * Returns a stream to which the response body must be
198     * written. {@link #setStatus}) must be called prior to calling
199     * this method. Multiple calls to this method (for the same exchange)
200     * will return the same stream.
201     *
202     * @return the stream to which the response body is written
203     * @throws IOException if any i/o error during response processing
204     */
205    public abstract OutputStream getResponseBody() throws IOException;
206
207    /**
208     * Sets the HTTP status code for the response.
209     *
210     * <p>
211     * This method must be called prior to calling {@link #getResponseBody}.
212     *
213     * @param status the response code to send
214     * @see #getResponseBody
215     */
216    public abstract void setStatus(int status);
217
218    /**
219     * Returns the unresolved address of the remote entity invoking
220     * this request.
221     *
222     * @return the InetSocketAddress of the caller
223     */
224    public abstract InetSocketAddress getRemoteAddress();
225
226    /**
227     * Returns the unresolved local address on which the request was received.
228     *
229     * @return the InetSocketAddress of the local interface
230     */
231    public abstract InetSocketAddress getLocalAddress();
232
233    /**
234     * Returns the protocol string from the request in the form
235     * <i>protocol/majorVersion.minorVersion</i>. For example,
236     * "HTTP/1.1"
237     *
238     * @return the protocol string from the request
239     */
240    public abstract String getProtocol();
241
242    /**
243     * Returns the name of the scheme used to make this request,
244     * for example: http, or https.
245     *
246     * @return name of the scheme used to make this request
247     */
248    public abstract String getScheme();
249
250    /**
251     * Returns the extra path information that follows the web service
252     * path but precedes the query string in the request URI and will start
253     * with a "/" character.
254     *
255     * <p>
256     * This can be used for {@link MessageContext#PATH_INFO}
257     *
258     * @return decoded extra path information of web service.
259     *         It is the path that comes
260     *         after the web service path but before the query string in the
261     *         request URI
262     *         {@code null} if there is no extra path in the request URI
263     */
264    public abstract String getPathInfo();
265
266    /**
267     * Returns the query string that is contained in the request URI
268     * after the path.
269     *
270     * <p>
271     * This can be used for {@link MessageContext#QUERY_STRING}
272     *
273     * @return undecoded query string of request URI, or
274     *         {@code null} if the request URI doesn't have one
275     */
276    public abstract String getQueryString();
277
278    /**
279     * Returns an attribute that is associated with this
280     * {@code HttpExchange}. JAX-WS handlers and endpoints may then
281     * access the attribute via {@link MessageContext}.
282     * <p>
283     * Servlet containers must expose {@link MessageContext#SERVLET_CONTEXT},
284     * {@link MessageContext#SERVLET_REQUEST}, and
285     * {@link MessageContext#SERVLET_RESPONSE}
286     * as attributes.
287     *
288     * <p>If the request has been received by the container using HTTPS, the
289     * following information must be exposed as attributes. These attributes
290     * are {@link #REQUEST_CIPHER_SUITE}, and {@link #REQUEST_KEY_SIZE}.
291     * If there is a SSL certificate associated with the request, it must
292     * be exposed using {@link #REQUEST_X509CERTIFICATE}
293     *
294     * @param name attribute name
295     * @return the attribute value, or {@code null} if the attribute doesn't
296     *         exist
297     */
298    public abstract Object getAttribute(String name);
299
300    /**
301     * Gives all the attribute names that are associated with
302     * this {@code HttpExchange}.
303     *
304     * @return set of all attribute names
305     * @see #getAttribute(String)
306     */
307    public abstract Set<String> getAttributeNames();
308
309    /**
310     * Returns the {@link Principal} that represents the authenticated
311     * user for this {@code HttpExchange}.
312     *
313     * @return Principal for an authenticated user, or
314     *         {@code null} if not authenticated
315     */
316    public abstract Principal getUserPrincipal();
317
318    /**
319     * Indicates whether an authenticated user is included in the specified
320     * logical "role".
321     *
322     * @param role specifies the name of the role
323     * @return {@code true} if the user making this request belongs to a
324     *         given role
325     */
326    public abstract boolean isUserInRole(String role);
327
328}
329