View Javadoc

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.jetty;
19  
20  import java.io.IOException;
21  import java.util.Map;
22  import java.util.Set;
23  
24  import javax.security.auth.Subject;
25  import javax.servlet.ServletException;
26  import javax.servlet.ServletRequest;
27  import javax.servlet.ServletResponse;
28  import javax.servlet.UnavailableException;
29  
30  import org.apache.geronimo.gbean.GBeanInfo;
31  import org.apache.geronimo.gbean.GBeanInfoBuilder;
32  import org.apache.geronimo.j2ee.j2eeobjectnames.NameFactory;
33  import org.apache.geronimo.management.Servlet;
34  import org.apache.geronimo.security.Callers;
35  import org.apache.geronimo.security.ContextManager;
36  import org.mortbay.jetty.servlet.ServletHolder;
37  
38  
39  /**
40   * This ServletHolder's sole purpose is to provide the thread's current
41   * ServletHolder for realms that are interested in the current servlet, e.g.
42   * current servlet name.
43   * <p/>
44   * It is also being our servlet gbean for now.  We could gbean-ize the superclass to avoid the thread local access.
45   *
46   * @version $Rev: 470597 $ $Date: 2006-11-02 15:30:55 -0800 (Thu, 02 Nov 2006) $
47   * @see JAASJettyRealm#isUserInRole(java.security.Principal, String)
48   */
49  public class JettyServletHolder extends ServletHolder implements Servlet {
50      private static final ThreadLocal currentServletName = new ThreadLocal();
51      private final Subject runAsSubject;
52      private final String objectName;
53  
54      //todo consider interface instead of this constructor for endpoint use.
55      public JettyServletHolder() {
56          this.objectName = null;
57          this.runAsSubject = null;
58      }
59  
60      public JettyServletHolder(String objectName,
61              String servletName,
62              String servletClassName,
63              String jspFile,
64              Map initParams,
65              Integer loadOnStartup,
66              Set servletMappings,
67              Subject runAsSubject,
68              ServletHolder previous,  //dependency for startup ordering
69              JettyServletRegistration context) throws Exception {
70          super(context == null ? null : context.getServletHandler(), servletName, servletClassName, jspFile);
71          //context will be null only for use as "default servlet info holder" in deployer.
72  
73          if (context != null) {
74              putAll(initParams);
75              if (loadOnStartup != null) {
76                  //This has no effect on the actual start order, the gbean references "previous" control that.
77                  setInitOrder(loadOnStartup.intValue());
78              }
79              //this now starts the servlet in the appropriate context
80              context.registerServletHolder(this, servletName, servletMappings, objectName);
81          }
82          this.runAsSubject = runAsSubject;
83          this.objectName = objectName;
84      }
85  
86      //todo how do we stop/destroy the servlet?
87      //todo is start called twice???
88  
89      public String getServletName() {
90          return getName();
91      }
92  
93      //TODO probably need to override init and destroy (?) to handle runAsSubject since we are not setting it in the superclass any more.
94  
95      /**
96       * Service a request with this servlet.  Set the ThreadLocal to hold the
97       * current JettyServletHolder.
98       */
99      public void handle(ServletRequest request, ServletResponse response)
100             throws ServletException, UnavailableException, IOException {
101 
102         setCurrentServletName(getServletName());
103         if (runAsSubject == null) {
104             super.handle(request, response);
105         } else {
106             Callers oldCallers = ContextManager.pushNextCaller(runAsSubject);
107             try {
108                 super.handle(request, response);
109             } finally {
110                 ContextManager.popCallers(oldCallers);
111             }
112         }
113     }
114 
115     /**
116      * Provide the thread's current JettyServletHolder
117      *
118      * @return the thread's current JettyServletHolder
119      * @see org.apache.geronimo.jetty.JAASJettyRealm#isUserInRole(java.security.Principal, java.lang.String)
120      */
121     static String getCurrentServletName() {
122         return (String) currentServletName.get();
123     }
124 
125     static void setCurrentServletName(String servletName) {
126         currentServletName.set(servletName);
127     }
128 
129     public String getObjectName() {
130         return objectName;
131     }
132 
133     public boolean isStateManageable() {
134         return false;
135     }
136 
137     public boolean isStatisticsProvider() {
138         return false;
139     }
140 
141     public boolean isEventProvider() {
142         return false;
143     }
144 
145     public static final GBeanInfo GBEAN_INFO;
146 
147     static {
148         GBeanInfoBuilder infoBuilder = GBeanInfoBuilder.createStatic(JettyServletHolder.class, NameFactory.SERVLET);
149         //todo replace with interface
150         infoBuilder.addInterface(ServletHolder.class);
151 
152         infoBuilder.addAttribute("servletName", String.class, true);
153         infoBuilder.addAttribute("servletClass", String.class, true);
154         infoBuilder.addAttribute("jspFile", String.class, true);
155         infoBuilder.addAttribute("initParams", Map.class, true);
156         infoBuilder.addAttribute("loadOnStartup", Integer.class, true);
157         infoBuilder.addAttribute("servletMappings", Set.class, true);
158         infoBuilder.addAttribute("runAsSubject", Subject.class, true);
159         infoBuilder.addAttribute("objectName", String.class, false);
160         infoBuilder.addInterface(Servlet.class);
161 
162         infoBuilder.addReference("Previous", ServletHolder.class, NameFactory.SERVLET);
163         infoBuilder.addReference("JettyServletRegistration", JettyServletRegistration.class, NameFactory.WEB_MODULE);
164 
165         infoBuilder.setConstructor(new String[]{"objectName",
166                 "servletName",
167                 "servletClass",
168                 "jspFile",
169                 "initParams",
170                 "loadOnStartup",
171                 "servletMappings",
172                 "runAsSubject",
173                 "Previous",
174                 "JettyServletRegistration"});
175 
176         GBEAN_INFO = infoBuilder.getBeanInfo();
177     }
178 
179     public static GBeanInfo getGBeanInfo() {
180         return GBEAN_INFO;
181     }
182 }