1 /*
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3 *
4 * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
5 *
6 * The contents of this file are subject to the terms of either the GNU
7 * General Public License Version 2 only ("GPL") or the Common Development
8 * and Distribution License("CDDL") (collectively, the "License"). You
9 * may not use this file except in compliance with the License. You can obtain
10 * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
11 * or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
12 * language governing permissions and limitations under the License.
13 *
14 * When distributing the software, include this License Header Notice in each
15 * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
16 * Sun designates this particular file as subject to the "Classpath" exception
17 * as provided by Sun in the GPL Version 2 section of the License file that
18 * accompanied this code. If applicable, add the following below the License
19 * Header, with the fields enclosed by brackets [] replaced by your own
20 * identifying information: "Portions Copyrighted [year]
21 * [name of copyright owner]"
22 *
23 * Contributor(s):
24 *
25 * If you wish your version of this file to be governed by only the CDDL or
26 * only the GPL Version 2, indicate your decision by adding "[Contributor]
27 * elects to include this software in this distribution under the [CDDL or GPL
28 * Version 2] license." If you don't indicate a single choice of license, a
29 * recipient has the option to distribute your version of this file under
30 * either the CDDL, the GPL Version 2 or to extend the choice of license to
31 * its licensees as provided above. However, if you add GPL Version 2 code
32 * and therefore, elected the GPL Version 2 license, then the option applies
33 * only if the new code is made subject to such option by the copyright
34 * holder.
35 */
36
37 package com.sun.xml.ws.transport.http.server;
38
39 import com.sun.istack.NotNull;
40 import com.sun.istack.Nullable;
41 import com.sun.net.httpserver.HttpExchange;
42 import com.sun.net.httpserver.HttpHandler;
43 import com.sun.net.httpserver.HttpsExchange;
44 import com.sun.xml.ws.resources.HttpserverMessages;
45 import com.sun.xml.ws.transport.http.HttpAdapter;
46 import com.sun.xml.ws.transport.http.WSHTTPConnection;
47
48 import java.io.IOException;
49 import java.util.List;
50 import java.util.concurrent.Executor;
51 import java.util.logging.Logger;
52
53 /**
54 * {@link HttpHandler} implementation that serves the actual request.
55 *
56 * @author Jitendra Kotamraju
57 * @author Kohsuke Kawaguhi
58 */
59 final class WSHttpHandler implements HttpHandler {
60
61 private static final String GET_METHOD = "GET";
62 private static final String POST_METHOD = "POST";
63 private static final String HEAD_METHOD = "HEAD";
64 private static final String PUT_METHOD = "PUT";
65 private static final String DELETE_METHOD = "DELETE";
66
67 private static final Logger logger =
68 Logger.getLogger(
69 com.sun.xml.ws.util.Constants.LoggingDomain + ".server.http");
70
71 private final HttpAdapter adapter;
72 private final Executor executor;
73
74 public WSHttpHandler(@NotNull HttpAdapter adapter, @Nullable Executor executor) {
75 assert adapter!=null;
76 this.adapter = adapter;
77 this.executor = executor;
78 }
79
80 /**
81 * Called by HttpServer when there is a matching request for the context
82 */
83 public void handle(HttpExchange msg) {
84 try {
85 logger.fine("Received HTTP request:"+msg.getRequestURI());
86 if (executor != null) {
87 // Use application's Executor to handle request. Application may
88 // have set an executor using Endpoint.setExecutor().
89 executor.execute(new HttpHandlerRunnable(msg));
90 } else {
91 handleExchange(msg);
92 }
93 } catch(Throwable e) {
94 // Dont't propagate the exception otherwise it kills the httpserver
95 e.printStackTrace();
96 }
97 }
98
99 public void handleExchange(HttpExchange msg) throws IOException {
100 WSHTTPConnection con = new ServerConnectionImpl(adapter,msg);
101 try {
102 logger.fine("Received HTTP request:"+msg.getRequestURI());
103 String method = msg.getRequestMethod();
104 if(method.equals(GET_METHOD) || method.equals(POST_METHOD) || method.equals(HEAD_METHOD)
105 || method.equals(PUT_METHOD) || method.equals(DELETE_METHOD)) {
106 adapter.handle(con);
107 } else {
108 logger.warning(HttpserverMessages.UNEXPECTED_HTTP_METHOD(method));
109 }
110 } finally {
111 msg.close();
112 }
113 }
114
115 /**
116 * Wrapping the processing of request in a Runnable so that it can be
117 * executed in Executor.
118 */
119 class HttpHandlerRunnable implements Runnable {
120 final HttpExchange msg;
121
122 HttpHandlerRunnable(HttpExchange msg) {
123 this.msg = msg;
124 }
125
126 public void run() {
127 try {
128 handleExchange(msg);
129 } catch (Throwable e) {
130 // Does application's executor handle this exception ?
131 e.printStackTrace();
132 }
133 }
134 }
135
136
137 /**
138 * Computes the Endpoint's address from the request. Use "Host" header
139 * so that it has correct address(IP address or someother hostname) through
140 * which the application reached the endpoint.
141 *
142 * @return
143 * a string like "http://foo.bar:1234/abc/def"
144 */
145 static @NotNull String getRequestAddress(HttpExchange msg) {
146 StringBuilder strBuf = new StringBuilder();
147 strBuf.append((msg instanceof HttpsExchange) ? "https" : "http");
148 strBuf.append("://");
149
150 List<String> hostHeader = msg.getRequestHeaders().get("Host");
151 if (hostHeader != null) {
152 strBuf.append(hostHeader.get(0)); // Uses Host header
153 } else {
154 strBuf.append(msg.getLocalAddress().getHostName());
155 strBuf.append(":");
156 strBuf.append(msg.getLocalAddress().getPort());
157 }
158 strBuf.append(msg.getRequestURI().getPath());
159
160 return strBuf.toString();
161 }
162 }