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 }