001 /**
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017 package org.apache.geronimo.tomcat;
018
019
020 import java.io.IOException;
021 import java.io.InputStream;
022 import java.io.OutputStream;
023 import java.net.URI;
024 import java.net.URISyntaxException;
025 import java.util.HashMap;
026 import java.util.Map;
027
028 import javax.servlet.ServletException;
029 import javax.servlet.http.HttpServlet;
030 import javax.servlet.http.HttpServletRequest;
031 import javax.servlet.http.HttpServletResponse;
032
033 import org.apache.catalina.Wrapper;
034 import org.apache.catalina.authenticator.BasicAuthenticator;
035 import org.apache.catalina.authenticator.DigestAuthenticator;
036 import org.apache.catalina.authenticator.NonLoginAuthenticator;
037 import org.apache.catalina.authenticator.SSLAuthenticator;
038 import org.apache.catalina.connector.Request;
039 import org.apache.catalina.connector.Response;
040 import org.apache.catalina.core.StandardContext;
041 import org.apache.catalina.deploy.LoginConfig;
042 import org.apache.catalina.deploy.SecurityCollection;
043 import org.apache.catalina.deploy.SecurityConstraint;
044 import org.apache.catalina.valves.ValveBase;
045 import org.apache.commons.logging.Log;
046 import org.apache.commons.logging.LogFactory;
047 import org.apache.geronimo.tomcat.realm.TomcatEJBWSGeronimoRealm;
048 import org.apache.geronimo.webservices.WebServiceContainer;
049
050 public class TomcatEJBWebServiceContext extends StandardContext{
051
052 private static final Log log = LogFactory.getLog(TomcatEJBWebServiceContext.class);
053
054 private final String contextPath;
055 private final WebServiceContainer webServiceContainer;
056 private final boolean isSecureTransportGuarantee;
057 private final ClassLoader classLoader;
058
059 public TomcatEJBWebServiceContext(String contextPath, WebServiceContainer webServiceContainer, String securityRealmName, String realmName, String transportGuarantee, String authMethod, ClassLoader classLoader) {
060
061 super();
062
063 this.contextPath = contextPath;
064 this.webServiceContainer = webServiceContainer;
065 this.setPath(contextPath);
066 this.setDocBase("");
067 this.setParentClassLoader(classLoader);
068 this.setDelegate(true);
069
070 log.debug("EJB Webservice Context = " + contextPath);
071 if (securityRealmName != null) {
072
073 TomcatEJBWSGeronimoRealm realm = new TomcatEJBWSGeronimoRealm();
074 realm.setAppName(securityRealmName);
075 realm.setUserClassNames("org.apache.geronimo.security.realm.providers.GeronimoUserPrincipal");
076 realm.setRoleClassNames("org.apache.geronimo.security.realm.providers.GeronimoGroupPrincipal");
077 setRealm(realm);
078 this.realm = realm;
079
080 if ("NONE".equals(transportGuarantee)) {
081 isSecureTransportGuarantee = false;
082 } else if ("INTEGRAL".equals(transportGuarantee) ||
083 "CONFIDENTIAL".equals(transportGuarantee)) {
084 isSecureTransportGuarantee = true;
085 } else {
086 throw new IllegalArgumentException("Invalid transport-guarantee: " + transportGuarantee);
087 }
088
089 if ("NONE".equals(authMethod) ||
090 "BASIC".equals(authMethod) ||
091 "DIGEST".equals(authMethod) ||
092 "CLIENT-CERT".equals(authMethod)) {
093
094 //Setup a login configuration
095 LoginConfig loginConfig = new LoginConfig();
096 loginConfig.setAuthMethod(authMethod);
097 loginConfig.setRealmName(realmName);
098 this.setLoginConfig(loginConfig);
099
100 //Setup a default Security Constraint
101 SecurityCollection collection = new SecurityCollection();
102 collection.addMethod("GET");
103 collection.addMethod("POST");
104 collection.addPattern("/*");
105 collection.setName("default");
106 SecurityConstraint sc = new SecurityConstraint();
107 sc.addAuthRole("*");
108 sc.addCollection(collection);
109 sc.setAuthConstraint(true);
110 sc.setUserConstraint(transportGuarantee);
111 this.addConstraint(sc);
112 this.addSecurityRole("default");
113
114 //Set the proper authenticator
115 if ("BASIC".equals(authMethod) ){
116 this.addValve(new BasicAuthenticator());
117 } else if ("DIGEST".equals(authMethod) ){
118 this.addValve(new DigestAuthenticator());
119 } else if ("CLIENT-CERT".equals(authMethod) ){
120 this.addValve(new SSLAuthenticator());
121 } else if ("NONE".equals(authMethod)) {
122 this.addValve(new NonLoginAuthenticator());
123 }
124
125 } else {
126 throw new IllegalArgumentException("Invalid authMethod: " + authMethod);
127 }
128 } else {
129 isSecureTransportGuarantee = false;
130 }
131
132 this.classLoader = classLoader;
133 this.addValve(new EJBWebServiceValve());
134
135 //Create a dummy wrapper
136 Wrapper wrapper = this.createWrapper();
137 String name = System.currentTimeMillis() + "";
138 wrapper.setName(name);
139 this.addChild(wrapper);
140 this.addServletMapping("/*", name);
141
142 }
143
144 public class EJBWebServiceValve extends ValveBase{
145
146 public void invoke(Request req, Response res) throws IOException, ServletException {
147 res.setContentType("text/xml");
148 RequestAdapter request = new RequestAdapter(req);
149 ResponseAdapter response = new ResponseAdapter(res);
150
151 request.setAttribute(WebServiceContainer.SERVLET_REQUEST, (HttpServletRequest)req);
152 request.setAttribute(WebServiceContainer.SERVLET_RESPONSE, (HttpServletResponse)res);
153 // TODO: add support for context
154 request.setAttribute(WebServiceContainer.SERVLET_CONTEXT, null);
155
156 req.finishRequest();
157 if (req.getParameter("wsdl") != null) {
158 try {
159 webServiceContainer.getWsdl(request, response);
160 //WHO IS RESPONSIBLE FOR CLOSING OUT?
161 } catch (IOException e) {
162 throw e;
163 } catch (Exception e) {
164 log.error(e);
165 res.sendError(500,"Could not fetch wsdl!");
166 return;
167 }
168 } else {
169 if (isSecureTransportGuarantee) {
170 if (!req.isSecure()) {
171 res.sendError(403);
172 return;
173 }
174 }
175 Thread currentThread = Thread.currentThread();
176 ClassLoader oldClassLoader = currentThread.getContextClassLoader();
177 currentThread.setContextClassLoader(classLoader);
178 try {
179 try {
180 webServiceContainer.invoke(request, response);
181 req.finishRequest();
182 } catch (IOException e) {
183 throw e;
184 } catch (Exception e) {
185 res.sendError(500, "Could not process message!");
186 }
187 } finally {
188 currentThread.setContextClassLoader(oldClassLoader);
189 }
190 }
191 }
192
193 }
194
195 public static class RequestAdapter implements WebServiceContainer.Request {
196 private final Request request;
197 private URI uri;
198
199 public RequestAdapter(Request request) {
200 this.request = request;
201 }
202
203 public String getHeader(String name) {
204 return request.getHeader(name);
205 }
206
207 public java.net.URI getURI() {
208 if (uri == null) {
209 try {
210 //String uriString = request.getScheme() + "://" + request.getServerName() + ":" + request.getLocalPort() + request.getRequestURI();
211 //return new java.net.URI(uri.getScheme(),uri.getHost(),uri.getPath(),uri.);
212 uri = new java.net.URI(request.getScheme(), null, request.getServerName(), request.getServerPort(), request.getRequestURI(), request.getQueryString(), null);
213 } catch (URISyntaxException e) {
214 throw new IllegalStateException(e.getMessage(), e);
215 }
216 }
217 return uri;
218 }
219
220 public int getContentLength() {
221 return request.getContentLength();
222 }
223
224 public String getContentType() {
225 return request.getContentType();
226 }
227
228 public InputStream getInputStream() throws IOException {
229 return request.getInputStream();
230 }
231
232 public int getMethod() {
233 Integer method = (Integer) methods.get(request.getMethod());
234 return method == null ? UNSUPPORTED : method.intValue();
235 }
236
237 public String getParameter(String name) {
238 return request.getParameter(name);
239 }
240
241 public Map getParameters() {
242 return request.getParameterMap();
243 }
244
245 public Object getAttribute(String name) {
246 return request.getAttribute(name);
247 }
248
249 public void setAttribute(String name, Object value) {
250 request.setAttribute(name, value);
251 }
252
253 public String getRemoteAddr() {
254 return request.getRemoteAddr();
255 }
256
257 public String getContextPath() {
258 return request.getContextPath();
259 }
260
261 private static final Map methods = new HashMap();
262
263 static {
264 methods.put("OPTIONS", new Integer(OPTIONS));
265 methods.put("GET", new Integer(GET));
266 methods.put("HEAD", new Integer(HEAD));
267 methods.put("POST", new Integer(POST));
268 methods.put("PUT", new Integer(PUT));
269 methods.put("DELETE", new Integer(DELETE));
270 methods.put("TRACE", new Integer(TRACE));
271 methods.put("CONNECT", new Integer(CONNECT));
272 }
273
274 }
275
276 public static class ResponseAdapter implements WebServiceContainer.Response {
277 private final Response response;
278
279 public ResponseAdapter(Response response) {
280 this.response = response;
281 }
282
283 public void setHeader(String name, String value) {
284 response.setHeader(name, value);
285 }
286
287 public String getHeader(String name) {
288 return response.getHeader(name);
289 }
290
291 public OutputStream getOutputStream() {
292 return response.getStream();
293 }
294
295 public void setStatusCode(int code) {
296 response.setStatus(code);
297 }
298
299 public int getStatusCode() {
300 return response.getStatus();
301 }
302
303 public void setContentType(String type) {
304 response.setContentType(type);
305 }
306
307 public String getContentType() {
308 return response.getContentType();
309 }
310
311 public void setStatusMessage(String responseString) {
312 response.setStatus(response.getStatus(), responseString);
313 }
314
315 public void flushBuffer() throws java.io.IOException{
316 response.flushBuffer();
317 }
318
319 }
320
321 }