001 /** 002 * 003 * Copyright 2003-2004 The Apache Software Foundation 004 * 005 * Licensed under the Apache License, Version 2.0 (the "License"); 006 * you may not use this file except in compliance with the License. 007 * 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 import java.io.IOException; 020 import java.io.InputStream; 021 import java.io.OutputStream; 022 import java.net.URI; 023 import java.net.URISyntaxException; 024 import java.util.HashMap; 025 import java.util.Map; 026 027 import javax.servlet.ServletException; 028 029 import org.apache.catalina.authenticator.BasicAuthenticator; 030 import org.apache.catalina.authenticator.DigestAuthenticator; 031 import org.apache.catalina.authenticator.SSLAuthenticator; 032 import org.apache.catalina.connector.Request; 033 import org.apache.catalina.connector.Response; 034 import org.apache.catalina.core.StandardContext; 035 import org.apache.catalina.deploy.LoginConfig; 036 import org.apache.catalina.deploy.SecurityCollection; 037 import org.apache.catalina.deploy.SecurityConstraint; 038 import org.apache.catalina.valves.ValveBase; 039 import org.apache.commons.logging.Log; 040 import org.apache.commons.logging.LogFactory; 041 import org.apache.geronimo.tomcat.realm.TomcatJAASRealm; 042 import org.apache.geronimo.tomcat.realm.TomcatGeronimoRealm; 043 import org.apache.geronimo.tomcat.realm.TomcatEJBWSGeronimoRealm; 044 import org.apache.geronimo.webservices.WebServiceContainer; 045 046 public class TomcatEJBWebServiceContext extends StandardContext{ 047 048 private static final Log log = LogFactory.getLog(TomcatEJBWebServiceContext.class); 049 050 private final String contextPath; 051 private final WebServiceContainer webServiceContainer; 052 private final boolean isSecureTransportGuarantee; 053 private final ClassLoader classLoader; 054 055 public TomcatEJBWebServiceContext(String contextPath, WebServiceContainer webServiceContainer, String securityRealmName, String realmName, String transportGuarantee, String authMethod, ClassLoader classLoader) { 056 057 super(); 058 059 this.contextPath = contextPath; 060 this.webServiceContainer = webServiceContainer; 061 this.setPath(contextPath); 062 this.setDocBase(""); 063 this.setParentClassLoader(classLoader); 064 this.setDelegate(true); 065 066 log.debug("EJB Webservice Context = " + contextPath); 067 if (securityRealmName != null) { 068 069 TomcatEJBWSGeronimoRealm realm = new TomcatEJBWSGeronimoRealm(); 070 realm.setAppName(securityRealmName); 071 realm.setUserClassNames("org.apache.geronimo.security.realm.providers.GeronimoUserPrincipal"); 072 realm.setRoleClassNames("org.apache.geronimo.security.realm.providers.GeronimoGroupPrincipal"); 073 setRealm(realm); 074 this.realm = realm; 075 076 if ("NONE".equals(transportGuarantee)) { 077 isSecureTransportGuarantee = false; 078 } else if ("INTEGRAL".equals(transportGuarantee) || 079 "CONFIDENTIAL".equals(transportGuarantee)) { 080 isSecureTransportGuarantee = true; 081 } else { 082 throw new IllegalArgumentException("Invalid transport-guarantee: " + transportGuarantee); 083 } 084 085 if ("BASIC".equals(authMethod) || 086 "DIGEST".equals(authMethod) || 087 "CLIENT-CERT".equals(authMethod)) { 088 089 //Setup a login configuration 090 LoginConfig loginConfig = new LoginConfig(); 091 loginConfig.setAuthMethod(authMethod); 092 loginConfig.setRealmName(realmName); 093 this.setLoginConfig(loginConfig); 094 095 //Setup a default Security Constraint 096 SecurityCollection collection = new SecurityCollection(); 097 collection.addMethod("GET"); 098 collection.addMethod("POST"); 099 collection.addPattern("/*"); 100 collection.setName("default"); 101 SecurityConstraint sc = new SecurityConstraint(); 102 sc.addAuthRole("*"); 103 sc.addCollection(collection); 104 sc.setAuthConstraint(true); 105 sc.setUserConstraint(transportGuarantee); 106 this.addConstraint(sc); 107 this.addSecurityRole("default"); 108 109 //Set the proper authenticator 110 if ("BASIC".equals(authMethod) ){ 111 this.addValve(new BasicAuthenticator()); 112 } else if ("DIGEST".equals(authMethod) ){ 113 this.addValve(new DigestAuthenticator()); 114 } else if ("CLIENT-CERT".equals(authMethod) ){ 115 this.addValve(new SSLAuthenticator()); 116 } 117 118 } else { 119 throw new IllegalArgumentException("Invalid authMethod: " + authMethod); 120 } 121 } else { 122 isSecureTransportGuarantee = false; 123 } 124 this.classLoader = classLoader; 125 this.addValve(new EJBWebServiceValve()); 126 127 } 128 129 public class EJBWebServiceValve extends ValveBase{ 130 131 public void invoke(Request req, Response res) throws IOException, ServletException { 132 req.setContentType("text/xml"); 133 RequestAdapter request = new RequestAdapter(req); 134 ResponseAdapter response = new ResponseAdapter(res); 135 req.finishRequest(); 136 if (req.getParameter("wsdl") != null) { 137 try { 138 webServiceContainer.getWsdl(request, response); 139 //WHO IS RESPONSIBLE FOR CLOSING OUT? 140 } catch (IOException e) { 141 throw e; 142 } catch (Exception e) { 143 log.error(e); 144 res.sendError(500,"Could not fetch wsdl!"); 145 return; 146 } 147 } else { 148 if (isSecureTransportGuarantee) { 149 if (!req.isSecure()) { 150 res.sendError(403); 151 return; 152 } 153 } 154 Thread currentThread = Thread.currentThread(); 155 ClassLoader oldClassLoader = currentThread.getContextClassLoader(); 156 currentThread.setContextClassLoader(classLoader); 157 try { 158 try { 159 webServiceContainer.invoke(request, response); 160 req.finishRequest(); 161 } catch (IOException e) { 162 throw e; 163 } catch (Exception e) { 164 res.sendError(500, "Could not process message!"); 165 } 166 } finally { 167 currentThread.setContextClassLoader(oldClassLoader); 168 } 169 } 170 } 171 172 } 173 174 public static class RequestAdapter implements WebServiceContainer.Request { 175 private final Request request; 176 private URI uri; 177 178 public RequestAdapter(Request request) { 179 this.request = request; 180 } 181 182 public String getHeader(String name) { 183 return request.getHeader(name); 184 } 185 186 public java.net.URI getURI() { 187 if (uri == null) { 188 try { 189 String uriString = request.getScheme() + "://" + request.getServerName() + ":" + request.getLocalPort() + request.getRequestURI(); 190 //return new java.net.URI(uri.getScheme(),uri.getHost(),uri.getPath(),uri.); 191 uri = new java.net.URI(uriString); 192 } catch (URISyntaxException e) { 193 throw new IllegalStateException(e.getMessage()); 194 } 195 } 196 return uri; 197 } 198 199 public int getContentLength() { 200 return request.getContentLength(); 201 } 202 203 public String getContentType() { 204 return request.getContentType(); 205 } 206 207 public InputStream getInputStream() throws IOException { 208 return request.getInputStream(); 209 } 210 211 public int getMethod() { 212 Integer method = (Integer) methods.get(request.getMethod()); 213 return method == null ? UNSUPPORTED : method.intValue(); 214 } 215 216 public String getParameter(String name) { 217 return request.getParameter(name); 218 } 219 220 public Map getParameters() { 221 return request.getParameterMap(); 222 } 223 224 public Object getAttribute(String name) { 225 return request.getAttribute(name); 226 } 227 228 public void setAttribute(String name, Object value) { 229 request.setAttribute(name, value); 230 } 231 232 233 private static final Map methods = new HashMap(); 234 235 static { 236 methods.put("OPTIONS", new Integer(OPTIONS)); 237 methods.put("GET", new Integer(GET)); 238 methods.put("HEAD", new Integer(HEAD)); 239 methods.put("POST", new Integer(POST)); 240 methods.put("PUT", new Integer(PUT)); 241 methods.put("DELETE", new Integer(DELETE)); 242 methods.put("TRACE", new Integer(TRACE)); 243 methods.put("CONNECT", new Integer(CONNECT)); 244 } 245 246 } 247 248 public static class ResponseAdapter implements WebServiceContainer.Response { 249 private final Response response; 250 251 public ResponseAdapter(Response response) { 252 this.response = response; 253 } 254 255 public void setHeader(String name, String value) { 256 response.setHeader(name, value); 257 } 258 259 public String getHeader(String name) { 260 return response.getHeader(name); 261 } 262 263 public OutputStream getOutputStream() { 264 return response.getStream(); 265 } 266 267 public void setStatusCode(int code) { 268 response.setStatus(code); 269 } 270 271 public int getStatusCode() { 272 return response.getStatus(); 273 } 274 275 public void setContentType(String type) { 276 response.setContentType(type); 277 } 278 279 public String getContentType() { 280 return response.getContentType(); 281 } 282 283 public void setStatusMessage(String responseString) { 284 response.setStatus(response.getStatus(), responseString); 285 } 286 } 287 288 }