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 */ 25 26 package com.sun.xml.internal.ws.transport.http; 27 28 import com.oracle.webservices.internal.api.message.BasePropertySet; 29 import com.oracle.webservices.internal.api.message.PropertySet; 30 import com.sun.istack.internal.NotNull; 31 import com.sun.istack.internal.Nullable; 32 import com.sun.xml.internal.ws.api.message.Packet; 33 import com.sun.xml.internal.ws.api.server.WebServiceContextDelegate; 34 35 import javax.xml.ws.WebServiceContext; 36 import java.io.IOException; 37 import java.io.InputStream; 38 import java.io.OutputStream; 39 import java.net.HttpURLConnection; 40 import java.security.Principal; 41 import java.util.Collections; 42 import java.util.List; 43 import java.util.Map; 44 import java.util.Set; 45 46 47 /** 48 * The view of an HTTP exchange from the point of view of JAX-WS. 49 * 50 * <p> 51 * Different HTTP server layer uses different implementations of this class 52 * so that JAX-WS can be shielded from individuality of such layers. 53 * This is an interface implemented as an abstract class, so that 54 * future versions of the JAX-WS RI can add new methods. 55 * 56 * <p> 57 * This class extends {@link PropertySet} so that a transport can 58 * expose its properties to the application and pipes. (This object 59 * will be added to {@link Packet#addSatellite(PropertySet)}.) 60 * 61 * @author Jitendra Kotamraju 62 */ 63 public abstract class WSHTTPConnection extends BasePropertySet { 64 65 public static final int OK=200; 66 public static final int ONEWAY=202; 67 public static final int UNSUPPORTED_MEDIA=415; 68 public static final int MALFORMED_XML=400; 69 public static final int INTERNAL_ERR=500; 70 71 /** 72 * Overwrites all the HTTP response headers written thus far. 73 * 74 * <p> 75 * The implementation should copy the contents of the {@link Map}, 76 * rather than retaining a reference. The {@link Map} passed as a 77 * parameter may change after this method is invoked. 78 * 79 * <p> 80 * This method may be called repeatedly, although in normal use 81 * case that's rare (so the implementation is encourage to take 82 * advantage of this usage pattern to improve performance, if possible.) 83 * 84 * <p> 85 * Initially, no header is set. 86 * 87 * <p> 88 * This parameter is usually exposed to {@link WebServiceContext} 89 * as {@link Packet#OUTBOUND_TRANSPORT_HEADERS}, and thus it 90 * should ignore {@code Content-Type} and {@code Content-Length} headers. 91 * 92 * @param headers 93 * See {@link HttpURLConnection#getHeaderFields()} for the format. 94 * This parameter may not be null, but since the user application 95 * code may invoke this method, a graceful error checking with 96 * an helpful error message should be provided if it's actually null. 97 * @see #setContentTypeResponseHeader(String) 98 */ 99 public abstract void setResponseHeaders(@NotNull Map<String,List<String>> headers); 100 101 public void setResponseHeader(String key, String value) { 102 setResponseHeader(key, Collections.singletonList(value)); 103 } 104 105 public abstract void setResponseHeader(String key, List<String> value); 106 107 /** 108 * Sets the {@code "Content-Type"} header. 109 * 110 * <p> 111 * If the Content-Type header has already been set, this method will overwrite 112 * the previously set value. If not, this method adds it. 113 * 114 * <p> 115 * Note that this method and {@link #setResponseHeaders(java.util.Map)} 116 * may be invoked in any arbitrary order. 117 * 118 * @param value 119 * strings like {@code "application/xml; charset=UTF-8"} or 120 * {@code "image/jpeg"}. 121 */ 122 public abstract void setContentTypeResponseHeader(@NotNull String value); 123 124 /** 125 * Sets the HTTP response code like {@link #OK}. 126 * 127 * <p> 128 * While JAX-WS processes a {@link WSHTTPConnection}, it 129 * will at least call this method once to set a valid HTTP response code. 130 * Note that this method may be invoked multiple times (from user code), 131 * so do not consider the value to be final until {@link #getOutput()} 132 * is invoked. 133 */ 134 135 public abstract void setStatus(int status); 136 137 /** 138 * Gets the last value set by {@link #setStatus(int)}. 139 * 140 * @return 141 * if {@link #setStatus(int)} has not been invoked yet, 142 * return 0. 143 */ 144 // I know this is ugly method! 145 public abstract int getStatus(); 146 147 /** 148 * Transport's underlying input stream. 149 * 150 * <p> 151 * This method will be invoked at most once by the JAX-WS RI to 152 * read the request body. If there's no request body, this method 153 * should return an empty {@link InputStream}. 154 * 155 * @return 156 * the stream from which the request body will be read. 157 */ 158 public abstract @NotNull InputStream getInput() throws IOException; 159 160 /** 161 * Transport's underlying output stream 162 * 163 * <p> 164 * This method will be invoked exactly once by the JAX-WS RI 165 * to start writing the response body (unless the processing aborts abnormally.) 166 * Even if there's no response body to write, this method will 167 * still be invoked only to be closed immediately. 168 * 169 * <p> 170 * Once this method is called, the status code and response 171 * headers will never change (IOW {@link #setStatus(int)}, 172 * {@link #setResponseHeaders}, and {@link #setContentTypeResponseHeader(String)} 173 * will never be invoked. 174 */ 175 public abstract @NotNull OutputStream getOutput() throws IOException; 176 177 /** 178 * Returns the {@link WebServiceContextDelegate} for this connection. 179 */ 180 public abstract @NotNull WebServiceContextDelegate getWebServiceContextDelegate(); 181 182 /** 183 * HTTP request method, such as "GET" or "POST". 184 */ 185 public abstract @NotNull String getRequestMethod(); 186 187 /** 188 * HTTP request headers. 189 * 190 * @deprecated 191 * This is a potentially expensive operation. 192 * Programs that want to access HTTP headers should consider using 193 * other methods such as {@link #getRequestHeader(String)}. 194 * 195 * @return 196 * can be empty but never null. 197 */ 198 public abstract @NotNull Map<String,List<String>> getRequestHeaders(); 199 200 /** 201 * HTTP request header names. 202 * 203 * @deprecated 204 * This is a potentially expensive operation. 205 * Programs that want to access HTTP headers should consider using 206 * other methods such as {@link #getRequestHeader(String)}. 207 * 208 * @return 209 * can be empty but never null. 210 */ 211 public abstract @NotNull Set<String> getRequestHeaderNames(); 212 213 /** 214 * @return 215 * HTTP response headers. 216 */ 217 public abstract Map<String,List<String>> getResponseHeaders(); 218 219 /** 220 * Gets an HTTP request header. 221 * 222 * <p> 223 * if multiple headers are present, this method returns one of them. 224 * (The implementation is free to choose which one it returns.) 225 * 226 * @return 227 * null if no header exists. 228 */ 229 public abstract @Nullable String getRequestHeader(@NotNull String headerName); 230 231 /** 232 * Gets an HTTP request header. 233 * 234 * @return 235 * null if no header exists. 236 */ 237 public abstract @Nullable List<String> getRequestHeaderValues(@NotNull String headerName); 238 239 /** 240 * HTTP Query string, such as "foo=bar", or null if none exists. 241 */ 242 public abstract @Nullable String getQueryString(); 243 244 /** 245 * Extra portion of the request URI after the end of the expected address of the service 246 * but before the query string 247 */ 248 public abstract @Nullable String getPathInfo(); 249 250 /** 251 * Requested path. A string like "/foo/bar/baz" 252 */ 253 public abstract @NotNull String getRequestURI(); 254 255 /** 256 * Requested scheme, e.g. "http" or "https" 257 */ 258 public abstract @NotNull String getRequestScheme(); 259 260 /** 261 * Server name 262 */ 263 public abstract @NotNull String getServerName(); 264 265 /** 266 * Server port 267 */ 268 public abstract int getServerPort(); 269 270 /** 271 * Portion of the request URI that groups related service addresses. The value, if non-empty, will 272 * always begin with '/', but will never end with '/'. Environments that do not support 273 * context paths must return an empty string. 274 */ 275 public @NotNull String getContextPath() { 276 return ""; 277 } 278 279 /** 280 * Environment specific context , if available 281 */ 282 public Object getContext() { 283 return null; 284 } 285 286 /** 287 * Gets the absolute URL up to the context path. 288 * @return 289 * String like "http://myhost/myapp" 290 * @since 2.1.2 291 */ 292 public @NotNull String getBaseAddress() { 293 throw new UnsupportedOperationException(); 294 } 295 296 /** 297 * Whether connection is HTTPS or not 298 * 299 * @return if the received request is on HTTPS, return true 300 * else false 301 */ 302 public abstract boolean isSecure(); 303 304 /** 305 * User principal associated with the request 306 * 307 * @return user principal 308 */ 309 public Principal getUserPrincipal() { 310 return null; 311 } 312 313 /** 314 * Whether user associated with the request holds the given role 315 * 316 * @param role Role to check 317 * @return if the caller holds the role 318 */ 319 public boolean isUserInRole(String role) { 320 return false; 321 } 322 323 /** 324 * Gets request metadata attribute 325 * @param key Request metadata key 326 * @return Value of metadata attribute or null, if no value present 327 */ 328 public Object getRequestAttribute(String key) { 329 return null; 330 } 331 332 private volatile boolean closed; 333 334 /** 335 * Close the connection 336 */ 337 public void close() { 338 this.closed = true; 339 } 340 341 /** 342 * Retuns whether connection is closed or not. 343 */ 344 public boolean isClosed() { 345 return closed; 346 } 347 348 /** 349 * Subclasses are expected to override 350 * 351 * @return a {@link String} containing the protocol name and version number 352 */ 353 public String getProtocol() { 354 return "HTTP/1.1"; 355 } 356 357 /** 358 * Subclasses are expected to override 359 * 360 * @since JAX-WS RI 2.2.2 361 * @return value of given cookie 362 */ 363 public String getCookie(String name) { 364 return null; 365 } 366 367 /** 368 * Subclasses are expected to override 369 * 370 * 371 * @since JAX-WS RI 2.2.2 372 */ 373 public void setCookie(String name, String value) { 374 } 375 376 /** 377 * Subclasses are expected to override 378 */ 379 public void setContentLengthResponseHeader(int value) { 380 } 381 382 }