1 /**
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one or more
4 * contributor license agreements. See the NOTICE file distributed with
5 * this work for additional information regarding copyright ownership.
6 * The ASF licenses this file to You under the Apache License, Version 2.0
7 * (the "License"); you may not use this file except in compliance with
8 * the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18 package org.apache.geronimo.tomcat;
19
20 import java.beans.PropertyChangeListener;
21 import java.io.IOException;
22 import java.util.Iterator;
23 import java.util.List;
24 import java.util.Map;
25
26 import javax.naming.NamingException;
27 import javax.security.auth.Subject;
28 import javax.security.jacc.PolicyContext;
29 import javax.servlet.Servlet;
30 import javax.servlet.ServletException;
31
32 import org.apache.catalina.Container;
33 import org.apache.catalina.LifecycleException;
34 import org.apache.catalina.Loader;
35 import org.apache.catalina.Manager;
36 import org.apache.catalina.Valve;
37 import org.apache.catalina.Wrapper;
38 import org.apache.catalina.cluster.CatalinaCluster;
39 import org.apache.catalina.connector.Request;
40 import org.apache.catalina.connector.Response;
41 import org.apache.catalina.core.StandardContext;
42 import org.apache.catalina.valves.ValveBase;
43 import org.apache.commons.logging.Log;
44 import org.apache.commons.logging.LogFactory;
45 import org.apache.geronimo.common.DeploymentException;
46 import org.apache.geronimo.naming.enc.EnterpriseNamingContext;
47 import org.apache.geronimo.security.ContextManager;
48 import org.apache.geronimo.security.IdentificationPrincipal;
49 import org.apache.geronimo.security.SubjectId;
50 import org.apache.geronimo.security.deploy.DefaultPrincipal;
51 import org.apache.geronimo.security.util.ConfigurationUtil;
52 import org.apache.geronimo.tomcat.interceptor.BeforeAfter;
53 import org.apache.geronimo.tomcat.interceptor.ComponentContextBeforeAfter;
54 import org.apache.geronimo.tomcat.interceptor.InstanceContextBeforeAfter;
55 import org.apache.geronimo.tomcat.interceptor.PolicyContextBeforeAfter;
56 import org.apache.geronimo.tomcat.util.SecurityHolder;
57 import org.apache.geronimo.tomcat.valve.DefaultSubjectValve;
58 import org.apache.geronimo.tomcat.valve.GeronimoBeforeAfterValve;
59 import org.apache.geronimo.webservices.POJOWebServiceServlet;
60 import org.apache.geronimo.webservices.WebServiceContainer;
61 import org.apache.geronimo.webservices.WebServiceContainerInvoker;
62
63
64 public class GeronimoStandardContext extends StandardContext {
65
66 private static final Log log = LogFactory.getLog(GeronimoStandardContext.class);
67
68 private static final long serialVersionUID = 3834587716552831032L;
69
70 private Subject defaultSubject = null;
71
72 private Map webServiceMap = null;
73
74 private boolean pipelineInitialized;
75
76 private BeforeAfter beforeAfter = null;
77 private int contextCount = 0;
78
79 public void setContextProperties(TomcatContext ctx) throws DeploymentException {
80
81 if (ctx instanceof TomcatWebAppContext) {
82 TomcatWebAppContext tctx = (TomcatWebAppContext) ctx;
83 setJavaVMs(tctx.getJavaVMs());
84 setServer(tctx.getServer());
85 setJ2EEApplication(tctx.getJ2EEApplication());
86 setJ2EEServer(tctx.getJ2EEServer());
87 }
88
89 javax.naming.Context enc = null;
90 Map componentContext = ctx.getComponentContext();
91 try {
92 if (componentContext != null) {
93 enc = EnterpriseNamingContext.createEnterpriseNamingContext(componentContext, ctx.getUserTransaction(), ctx.getKernel(), ctx.getClassLoader());
94 }
95 } catch (NamingException ne) {
96 log.error(ne);
97 }
98
99 int index = 0;
100 BeforeAfter interceptor = new InstanceContextBeforeAfter(null, index++,
101 ctx.getUnshareableResources(),
102 ctx.getApplicationManagedSecurityResources(),
103 ctx.getTrackedConnectionAssociator());
104
105
106 if (enc != null) {
107 interceptor = new ComponentContextBeforeAfter(interceptor, index++, enc);
108 }
109
110
111 SecurityHolder securityHolder = ctx.getSecurityHolder();
112 if (securityHolder != null) {
113 if (securityHolder.getPolicyContextID() != null) {
114
115 PolicyContext.setContextID(securityHolder.getPolicyContextID());
116
117 /**
118 * Register our default subject with the ContextManager
119 */
120 DefaultPrincipal defaultPrincipal = securityHolder.getDefaultPrincipal();
121 if (defaultPrincipal != null) {
122 defaultSubject = ConfigurationUtil.generateDefaultSubject(defaultPrincipal, ctx.getClassLoader());
123 ContextManager.registerSubject(defaultSubject);
124 SubjectId id = ContextManager.getSubjectId(defaultSubject);
125 defaultSubject.getPrincipals().add(new IdentificationPrincipal(id));
126 }
127
128 interceptor = new PolicyContextBeforeAfter(interceptor, index++, index++, securityHolder.getPolicyContextID());
129 }
130 }
131
132
133 GeronimoBeforeAfterValve geronimoBAValve = new GeronimoBeforeAfterValve(interceptor, index);
134 addValve(geronimoBAValve);
135 beforeAfter = interceptor;
136 contextCount = index;
137
138
139
140
141 addValve(new SystemMethodValve());
142
143
144 List valveChain = ctx.getValveChain();
145 if (valveChain != null) {
146 Iterator iterator = valveChain.iterator();
147 while (iterator.hasNext()) {
148 Valve valve = (Valve) iterator.next();
149 addValve(valve);
150 }
151 }
152
153 CatalinaCluster cluster = ctx.getCluster();
154 if (cluster != null)
155 this.setCluster(cluster);
156
157 Manager manager = ctx.getManager();
158 if (manager != null)
159 this.setManager(manager);
160
161 pipelineInitialized = true;
162 this.webServiceMap = ctx.getWebServices();
163
164 this.setCrossContext(ctx.isCrossContext());
165
166 this.setCookies(!ctx.isDisableCookies());
167
168
169 this.addInstanceListener("org.apache.geronimo.tomcat.listener.DispatchListener");
170 }
171
172 public synchronized void start() throws LifecycleException {
173 if (pipelineInitialized) {
174 try {
175 Valve valve = getFirst();
176 valve.invoke(null, null);
177
178
179
180 Valve defaultSubjectValve = new DefaultSubjectValve(defaultSubject);
181 addValve(defaultSubjectValve);
182 } catch (IOException e) {
183 if (e.getCause() instanceof LifecycleException) {
184 throw (LifecycleException) e.getCause();
185 }
186 throw new LifecycleException(e);
187 } catch (ServletException e) {
188 throw new LifecycleException(e);
189 }
190 } else
191 super.start();
192 }
193
194 public synchronized void stop() throws LifecycleException {
195
196 if (defaultSubject != null) {
197 ContextManager.unregisterSubject(defaultSubject);
198 }
199
200 super.stop();
201 }
202
203 public void addChild(Container child) {
204 Wrapper wrapper = (Wrapper) child;
205
206 String servletClassName = wrapper.getServletClass();
207 if (servletClassName == null) {
208 super.addChild(child);
209 return;
210 }
211
212 ClassLoader cl = this.getParentClassLoader();
213
214 Class baseServletClass;
215 Class servletClass;
216 try {
217 baseServletClass = cl.loadClass(Servlet.class.getName());
218 servletClass = cl.loadClass(servletClassName);
219
220 if (!baseServletClass.isAssignableFrom(servletClass)) {
221
222 if (webServiceMap != null) {
223 WebServiceContainer webServiceContainer = (WebServiceContainer) webServiceMap.get(wrapper.getName());
224
225 if (webServiceContainer != null) {
226
227
228 wrapper.setServletClass("org.apache.geronimo.webservices.POJOWebServiceServlet");
229
230
231 String webServicecontainerID = wrapper.getName() + WebServiceContainerInvoker.WEBSERVICE_CONTAINER + webServiceContainer.hashCode();
232 getServletContext().setAttribute(webServicecontainerID, webServiceContainer);
233 wrapper.addInitParameter(WebServiceContainerInvoker.WEBSERVICE_CONTAINER, webServicecontainerID);
234
235
236 String pojoClassID = wrapper.getName() + POJOWebServiceServlet.POJO_CLASS + servletClass.hashCode();
237 getServletContext().setAttribute(pojoClassID, servletClass);
238 wrapper.addInitParameter(POJOWebServiceServlet.POJO_CLASS, pojoClassID);
239 }
240 }
241 }
242 } catch (ClassNotFoundException e) {
243 throw new RuntimeException(e.getMessage(), e);
244 }
245
246 super.addChild(child);
247 }
248
249 public synchronized void setLoader(final Loader delegate) {
250 Loader loader = new Loader() {
251
252 public void backgroundProcess() {
253 delegate.backgroundProcess();
254 }
255
256 public ClassLoader getClassLoader() {
257
258
259 return parentClassLoader;
260 }
261
262 public Container getContainer() {
263 return delegate.getContainer();
264 }
265
266 public void setContainer(Container container) {
267 delegate.setContainer(container);
268 }
269
270 public boolean getDelegate() {
271 return delegate.getDelegate();
272 }
273
274 public void setDelegate(boolean delegateBoolean) {
275 delegate.setDelegate(delegateBoolean);
276 }
277
278 public String getInfo() {
279 return delegate.getInfo();
280 }
281
282 public boolean getReloadable() {
283 return false;
284 }
285
286 public void setReloadable(boolean reloadable) {
287 if (reloadable) {
288 throw new UnsupportedOperationException("Reloadable context is not supported.");
289 }
290 }
291
292 public void addPropertyChangeListener(PropertyChangeListener listener) {
293 delegate.addPropertyChangeListener(listener);
294 }
295
296 public void addRepository(String repository) {
297 delegate.addRepository(repository);
298 }
299
300 public String[] findRepositories() {
301 return delegate.findRepositories();
302 }
303
304 public boolean modified() {
305 return delegate.modified();
306 }
307
308 public void removePropertyChangeListener(PropertyChangeListener listener) {
309 delegate.removePropertyChangeListener(listener);
310 }
311 };
312
313 super.setLoader(loader);
314 }
315
316 private class SystemMethodValve extends ValveBase {
317
318 public void invoke(Request request, Response response) throws IOException, ServletException {
319 if (request == null && response == null) {
320 try {
321 GeronimoStandardContext.super.start();
322 } catch (LifecycleException e) {
323 throw (IOException) new IOException("wrapping lifecycle exception").initCause(e);
324 }
325 } else {
326 getNext().invoke(request, response);
327 }
328
329 }
330 }
331
332
333 public BeforeAfter getBeforeAfter() {
334 return beforeAfter;
335 }
336
337 public int getContextCount() {
338 return contextCount;
339 }
340
341 }