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    }