KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > web > tomcat > tc5 > Tomcat5


1 /*
2  * JBoss, the OpenSource WebOS
3  *
4  * Distributable under LGPL license.
5  * See terms of license at gnu.org.
6  */

7 package org.jboss.web.tomcat.tc5;
8
9 import java.io.File JavaDoc;
10 import java.util.Iterator JavaDoc;
11
12 import javax.management.Attribute JavaDoc;
13 import javax.management.MBeanServer JavaDoc;
14 import javax.management.Notification JavaDoc;
15 import javax.management.NotificationListener JavaDoc;
16 import javax.management.ObjectInstance JavaDoc;
17 import javax.management.ObjectName JavaDoc;
18 import javax.security.jacc.PolicyContext JavaDoc;
19
20 import org.apache.catalina.Lifecycle;
21 import org.apache.catalina.connector.Connector;
22 import org.apache.commons.modeler.Registry;
23 import org.jboss.deployment.DeploymentInfo;
24 import org.jboss.deployment.SubDeployer;
25 import org.jboss.system.server.Server;
26 import org.jboss.system.server.ServerImplMBean;
27 import org.jboss.system.ServiceControllerMBean;
28 import org.jboss.web.AbstractWebContainer;
29 import org.jboss.web.AbstractWebDeployer;
30 import org.jboss.web.tomcat.security.HttpServletRequestPolicyContextHandler;
31 import org.jboss.web.tomcat.tc5.session.SessionIDGenerator;
32 import org.jboss.security.plugins.JaasSecurityManagerServiceMBean;
33 import org.jboss.mx.util.MBeanProxyExt;
34
35
36 /**
37  * An implementation of the AbstractWebContainer for the Jakarta Tomcat5
38  * servlet container. It has no code dependency on tomcat - only the new JMX
39  * model is used.
40  * <p/>
41  * Tomcat5 is organized as a set of mbeans - just like jboss.
42  *
43  * @author Scott.Stark@jboss.org
44  * @author Costin Manolache
45  * @author Wonne.Keysers@realsoftware.be
46  * @author Dimitris.Andreadis@jboss.org
47  * @version $Revision: 1.24.2.6 $
48  * @see org.jboss.web.AbstractWebContainer
49  */

50 public class Tomcat5 extends AbstractWebContainer
51    implements Tomcat5MBean, NotificationListener JavaDoc
52 {
53    // Constants -----------------------------------------------------
54
public static final String JavaDoc NAME = "Tomcat5";
55
56    /**
57     * Default value for property <code>cacheName</code>. This name will be used by JBossCache exclusively
58     * for Tomcat clustering, e.g., session and sso replication.
59     */

60    public static final String JavaDoc DEFAULT_CACHE_NAME =
61       "jboss.cache:service=TomcatClusteringCache";
62
63    // XXX We could make this configurable - so it can support other containers
64
// that provide JMX-based deployment.
65
private String JavaDoc contextClassName =
66       "org.apache.catalina.core.StandardContext";
67
68    /**
69     * Domain for tomcat5 mbeans
70     */

71    private String JavaDoc catalinaDomain = "Catalina";
72
73    /**
74     * ObjectName of a shared TreeCache used for clustered session replication
75     * and clustered single-sign-on
76     */

77    private String JavaDoc cacheName = DEFAULT_CACHE_NAME;
78
79    /**
80     * The fully qualified name of the class that will be used for session
81     * management if <tt>distributable</tt> is set to true.
82     */

83    protected String JavaDoc managerClass = "org.jboss.web.tomcat.tc5.session.JBossCacheManager";
84
85    /**
86     * With IntervalSnapshotManager use this interval (in ms)
87     * for snapshotting
88     */

89    private int snapshotInterval = 1000;
90
91    /**
92     * Which snapshot mode should be used in clustered environment?
93     * Default: instant
94     */

95    private String JavaDoc snapshotMode = "instant"; // instant or interval
96

97    /**
98     * Should the clustering code use a local cache for the sessions?
99     */

100    private boolean useLocalCache = true;
101
102    /**
103     * Whether we are using Apache MOD_JK(2) module or not
104     */

105    private boolean useJK = false;
106
107    /**
108     * A flag indicating if the JBoss Loader should be used
109     */

110    private boolean useJBossWebLoader = true;
111
112    /**
113     * The server xml configuration file name
114     */

115    private String JavaDoc serverConfigFile = "server.xml";
116
117    /**
118     * Get the request attribute name under which the JAAS Subject is store
119     */

120    private String JavaDoc subjectAttributeName = null;
121    /**
122     * Flag indicating whether web-app specific context xmls may set the privileged flag.
123     */

124    private boolean allowSelfPrivilegedWebApps = false;
125    /** The service used to flush authentication cache on session invalidation. */
126    private JaasSecurityManagerServiceMBean secMgrService;
127    /** */
128    private String JavaDoc[] filteredPackages;
129    /** Hold a proxy reference to myself, used when registering to MainDeployer */
130    private SubDeployer thisProxy;
131
132    public Tomcat5()
133    {
134    }
135
136    public String JavaDoc getName()
137    {
138       return NAME;
139    }
140
141
142    public String JavaDoc getManagerClass()
143    {
144       return managerClass;
145    }
146
147    public void setManagerClass(String JavaDoc managerClass)
148    {
149       this.managerClass = managerClass;
150    }
151
152
153    public String JavaDoc getDomain()
154    {
155       return this.catalinaDomain;
156    }
157
158    /**
159     * The most important atteribute - defines the managed domain.
160     * A catalina instance (engine) corresponds to a JMX domain, that's
161     * how we know where to deploy webapps.
162     *
163     * @param catalinaDomain the domain portion of the JMX ObjectNames
164     */

165    public void setDomain(String JavaDoc catalinaDomain)
166    {
167       this.catalinaDomain = catalinaDomain;
168    }
169
170    public void setContextMBeanCode(String JavaDoc className)
171    {
172       this.contextClassName = className;
173    }
174
175    public String JavaDoc getContextMBeanCode()
176    {
177       return contextClassName;
178    }
179
180    /**
181     * Set the snapshot interval in milliseconds for snapshot mode = interval
182     */

183    public void setSnapshotInterval(int interval)
184    {
185       this.snapshotInterval = interval;
186    }
187
188    /**
189     * Get the snapshot interval
190     */

191    public int getSnapshotInterval()
192    {
193       return this.snapshotInterval;
194    }
195
196    /**
197     * Set the snapshot mode. Currently supported: instant or interval
198     */

199    public void setSnapshotMode(String JavaDoc mode)
200    {
201       this.snapshotMode = mode;
202    }
203
204    /**
205     * Get the snapshot mode
206     */

207    public String JavaDoc getSnapshotMode()
208    {
209       return this.snapshotMode;
210    }
211
212    /**
213     * Gets the JMX object name of a shared TreeCache to be used for clustered
214     * single-sign-on.
215     *
216     * @see #DEFAULT_CACHE_NAME
217     * @see org.jboss.web.tomcat.tc5.sso.TreeCacheSSOClusterManager
218     */

219    public String JavaDoc getCacheName()
220    {
221       return cacheName;
222    }
223
224    /**
225     * Gets the JMX object name of a shared TreeCache to be used for clustered
226     * single-sign-on.
227     * <p/>
228     * <b>NOTE:</b> TreeCache must be deployed before this service.
229     *
230     * @see #DEFAULT_CACHE_NAME
231     * @see org.jboss.web.tomcat.tc5.sso.TreeCacheSSOClusterManager
232     */

233    public void setCacheName(String JavaDoc cacheName)
234    {
235       this.cacheName = cacheName;
236    }
237
238    public boolean isUseLocalCache()
239    {
240       return useLocalCache;
241    }
242
243    public void setUseLocalCache(boolean useLocalCache)
244    {
245       this.useLocalCache = useLocalCache;
246    }
247
248    public boolean isUseJK()
249    {
250       return useJK;
251    }
252
253    public void setUseJK(boolean useJK)
254    {
255       this.useJK = useJK;
256    }
257
258    /**
259     * The SessionIdAlphabet is the set of characters used to create a session Id
260     */

261    public void setSessionIdAlphabet(String JavaDoc sessionIdAlphabet)
262    {
263        SessionIDGenerator.getInstance().setSessionIdAlphabet(sessionIdAlphabet);
264    }
265
266    /**
267     * The SessionIdAlphabet is the set of characters used to create a session Id
268     */

269    public String JavaDoc getSessionIdAlphabet()
270    {
271        return SessionIDGenerator.getInstance().getSessionIdAlphabet();
272    }
273    
274    public boolean getUseJBossWebLoader()
275    {
276       return useJBossWebLoader;
277    }
278
279    public void setUseJBossWebLoader(boolean flag)
280    {
281       this.useJBossWebLoader = flag;
282    }
283
284    public String JavaDoc getConfigFile()
285    {
286       return serverConfigFile;
287    }
288
289    public void setConfigFile(String JavaDoc configFile)
290    {
291       this.serverConfigFile = configFile;
292    }
293
294    public String JavaDoc getSubjectAttributeName()
295    {
296       return this.subjectAttributeName;
297    }
298
299    public void setSubjectAttributeName(String JavaDoc name)
300    {
301       this.subjectAttributeName = name;
302    }
303
304    public boolean isAllowSelfPrivilegedWebApps()
305    {
306       return allowSelfPrivilegedWebApps;
307    }
308
309    public void setAllowSelfPrivilegedWebApps(boolean allowSelfPrivilegedWebApps)
310    {
311       this.allowSelfPrivilegedWebApps = allowSelfPrivilegedWebApps;
312    }
313
314    public void setSecurityManagerService(JaasSecurityManagerServiceMBean mgr)
315    {
316       this.secMgrService = mgr;
317    }
318
319    public String JavaDoc[] getFilteredPackages()
320    {
321       return filteredPackages;
322    }
323    public void setFilteredPackages(String JavaDoc[] pkgs)
324    {
325       this.filteredPackages = pkgs;
326    }
327
328    public void startService()
329       throws Exception JavaDoc
330    {
331
332       System.setProperty("catalina.ext.dirs",
333          (System.getProperty("jboss.server.home.dir")
334          + File.separator + "lib"));
335
336       String JavaDoc objectNameS = catalinaDomain + ":type=server";
337       ObjectName JavaDoc objectName = new ObjectName JavaDoc(objectNameS);
338
339       // Set the modeler Registry MBeanServer to the that of the tomcat service
340
Registry.getRegistry().setMBeanServer(server);
341
342       server.createMBean("org.apache.commons.modeler.BaseModelMBean",
343          objectName,
344          new Object JavaDoc[]{"org.apache.catalina.startup.Catalina"},
345          new String JavaDoc[]{"java.lang.String"});
346
347       server.setAttribute(objectName, new Attribute JavaDoc
348          ("catalinaHome",
349             System.getProperty("jboss.server.home.dir")));
350       server.setAttribute(objectName, new Attribute JavaDoc
351          ("configFile", serverConfigFile));
352       server.setAttribute(objectName, new Attribute JavaDoc
353          ("useNaming", new Boolean JavaDoc(false)));
354       server.setAttribute(objectName, new Attribute JavaDoc
355          ("useShutdownHook", new Boolean JavaDoc(false)));
356       server.setAttribute(objectName, new Attribute JavaDoc
357          ("await", new Boolean JavaDoc(false)));
358
359       server.invoke(objectName, "create", new Object JavaDoc[]{},
360          new String JavaDoc[]{});
361
362       server.invoke(objectName, "start", new Object JavaDoc[]{},
363          new String JavaDoc[]{});
364
365       // Configure any SingleSignOn valves
366

367       ObjectName JavaDoc ssoQuery = new ObjectName JavaDoc(catalinaDomain + ":type=Valve,*");
368       Iterator JavaDoc iterator = server.queryMBeans(ssoQuery, null).iterator();
369       while (iterator.hasNext())
370       {
371          ObjectName JavaDoc ssoObjectName =
372             ((ObjectInstance JavaDoc) iterator.next()).getObjectName();
373          String JavaDoc name = ssoObjectName.getKeyProperty("name");
374          
375          /* Ensure that the SingleSignOn valve requires that each
376             request be reauthenticated to the security mgr. Should not
377             be neccessary now that we cache the principal in the session.
378          if ((name != null) && (name.indexOf("SingleSignOn") >= 0))
379          {
380             log.info("Turning on reauthentication of each request on " +
381                      ssoObjectName);
382             server.setAttribute(ssoObjectName, new Attribute
383                ("requireReauthentication", Boolean.TRUE));
384          }
385          */

386             
387          // If the valve is a ClusteredSingleSignOn and we have a shared
388
// TreeCache configured, configure the valve to use the shared one
389
if (cacheName != null && "ClusteredSingleSignOn".equals(name))
390          {
391             String JavaDoc tcName = (String JavaDoc) server.getAttribute(ssoObjectName,
392                "treeCacheName");
393             tcName = (tcName != null ? tcName : DEFAULT_CACHE_NAME);
394             ObjectName JavaDoc ssoCacheName = new ObjectName JavaDoc(tcName);
395             // Only override if the valve's cacheName property was not
396
// explicitly set in server.xml to a non-default value
397
if (ssoCacheName.equals(new ObjectName JavaDoc(DEFAULT_CACHE_NAME)))
398             {
399                log.info("Setting the cache name to " + cacheName +
400                   " on " + ssoObjectName);
401                server.setAttribute(ssoObjectName,
402                   new Attribute JavaDoc("treeCacheName", cacheName));
403             }
404          }
405       }
406
407       // Register the web container JACC PolicyContextHandlers
408
HttpServletRequestPolicyContextHandler handler = new HttpServletRequestPolicyContextHandler();
409       PolicyContext.registerHandler(HttpServletRequestPolicyContextHandler.WEB_REQUEST_KEY,
410          handler, false);
411
412       // The ServiceController used to control web app startup dependencies
413
serviceController = (ServiceControllerMBean)
414          MBeanProxyExt.create(ServiceControllerMBean.class, ServiceControllerMBean.OBJECT_NAME, server);
415
416       // make a proxy to myself, so that calls from the MainDeployer
417
// can go through the MBeanServer, so interceptors can be added
418
thisProxy = (SubDeployer)
419          MBeanProxyExt.create(SubDeployer.class, super.getServiceName(), super.getServer());
420
421       // Register with the main deployer
422
mainDeployer.addDeployer(thisProxy);
423
424       // If we are hot-deployed *after* the overall server is started
425
// we'll never receive Server.START_NOTIFICATION_TYPE, so check
426
// with the Server and start the connectors immediately, if this is the case.
427
// Otherwise register to receive the server start-up notification.
428
Boolean JavaDoc started = (Boolean JavaDoc)server.getAttribute(ServerImplMBean.OBJECT_NAME, "Started");
429       if (started.booleanValue() == true)
430       {
431          log.debug("Server '" + ServerImplMBean.OBJECT_NAME +
432                "' already started, starting connectors now");
433          
434          startConnectors();
435       }
436       else
437       {
438          // Register for notification of the overall server startup
439
log.debug("Server '" + ServerImplMBean.OBJECT_NAME +
440                "' not started, registering for start-up notification");
441          
442          server.addNotificationListener(ServerImplMBean.OBJECT_NAME, this, null, null);
443       }
444    }
445
446
447    public void stopService()
448       throws Exception JavaDoc
449    {
450
451       String JavaDoc objectNameS = catalinaDomain + ":type=server";
452       ObjectName JavaDoc objectName = new ObjectName JavaDoc(objectNameS);
453
454       server.invoke(objectName, "stop", new Object JavaDoc[]{},
455          new String JavaDoc[]{});
456
457       server.invoke(objectName, "destroy", new Object JavaDoc[]{},
458          new String JavaDoc[]{});
459
460       server.unregisterMBean(objectName);
461
462       MBeanServer JavaDoc server2 = server;
463
464       // deregister with MainDeployer
465
mainDeployer.removeDeployer(thisProxy);
466
467       // Unregister any remaining jboss.web or Catalina MBeans
468
ObjectName JavaDoc queryObjectName = new ObjectName JavaDoc
469          (catalinaDomain + ":*");
470       Iterator JavaDoc iterator =
471          server2.queryMBeans(queryObjectName, null).iterator();
472       while (iterator.hasNext())
473       {
474          ObjectInstance JavaDoc oi = (ObjectInstance JavaDoc) iterator.next();
475          ObjectName JavaDoc toRemove = oi.getObjectName();
476          // Exception: Don't unregister the service right now
477
if (!"WebServer".equals(toRemove.getKeyProperty("service")))
478          {
479             if (server2.isRegistered(toRemove))
480             {
481                server2.unregisterMBean(toRemove);
482             }
483          }
484       }
485       queryObjectName = new ObjectName JavaDoc("Catalina:*");
486       iterator = server2.queryMBeans(queryObjectName, null).iterator();
487       while (iterator.hasNext())
488       {
489          ObjectInstance JavaDoc oi = (ObjectInstance JavaDoc) iterator.next();
490          ObjectName JavaDoc name = oi.getObjectName();
491          server2.unregisterMBean(name);
492       }
493
494    }
495
496    public void startConnectors() throws Exception JavaDoc
497    {
498       ObjectName JavaDoc service = new ObjectName JavaDoc(catalinaDomain + ":type=Service,serviceName=jboss.web");
499       Object JavaDoc[] args = {};
500       String JavaDoc[] sig = {};
501       Connector[] connectors = (Connector[]) server.invoke(service,
502          "findConnectors", args, sig);
503       for (int n = 0; n < connectors.length; n++)
504       {
505          Lifecycle lc = (Lifecycle) connectors[n];
506          lc.start();
507       }
508       // Notify listeners that connectors have started processing requests
509
sendNotification(new Notification JavaDoc(TOMCAT_CONNECTORS_STARTED,
510             this, getNextNotificationSequenceNumber()));
511    }
512
513    public void stopConnectors() throws Exception JavaDoc
514    {
515       ObjectName JavaDoc service = new ObjectName JavaDoc(catalinaDomain + ":type=Service,serviceName=jboss.web");
516       Object JavaDoc[] args = {};
517       String JavaDoc[] sig = {};
518       Connector[] connectors = (Connector[]) server.invoke(service,
519          "findConnectors", args, sig);
520       for (int n = 0; n < connectors.length; n++)
521       {
522          Lifecycle lc = (Lifecycle) connectors[n];
523          lc.stop();
524       }
525    }
526
527    public void handleNotification(Notification JavaDoc msg, Object JavaDoc handback)
528    {
529       String JavaDoc type = msg.getType();
530       if (type.equals(Server.START_NOTIFICATION_TYPE))
531       {
532          log.debug("Saw " + type + " notification, starting connectors");
533          try
534          {
535             startConnectors();
536          }
537          catch (Exception JavaDoc e)
538          {
539             log.warn("Failed to startConnectors", e);
540          }
541       }
542    }
543
544    public AbstractWebDeployer getDeployer(DeploymentInfo di) throws Exception JavaDoc
545    {
546       ClassLoader JavaDoc loader = di.ucl;
547       Class JavaDoc deployerClass = loader.loadClass("org.jboss.web.tomcat.tc5.TomcatDeployer");
548       AbstractWebDeployer deployer = (AbstractWebDeployer) deployerClass.newInstance();
549       DeployerConfig config = new DeployerConfig();
550       config.setDefaultSecurityDomain(this.defaultSecurityDomain);
551       config.setSubjectAttributeName(this.subjectAttributeName);
552       config.setServiceClassLoader(getClass().getClassLoader());
553       config.setManagerClass(this.managerClass);
554       config.setJava2ClassLoadingCompliance(this.java2ClassLoadingCompliance);
555       config.setUnpackWars(this.unpackWars);
556       config.setLenientEjbLink(this.lenientEjbLink);
557       config.setCatalinaDomain(catalinaDomain);
558       config.setContextClassName(contextClassName);
559       config.setServiceName(serviceName);
560       config.setSnapshotInterval(this.snapshotInterval);
561       config.setSnapshotMode(this.snapshotMode);
562       config.setUseLocalCache(this.useLocalCache);
563       config.setUseJK(this.useJK);
564       config.setSubjectAttributeName(this.subjectAttributeName);
565       config.setUseJBossWebLoader(this.useJBossWebLoader);
566       config.setAllowSelfPrivilegedWebApps(this.allowSelfPrivilegedWebApps);
567       config.setSecurityManagerService(this.secMgrService);
568       config.setFilteredPackages(filteredPackages);
569       deployer.setServer(server);
570       deployer.init(config);
571       return deployer;
572    }
573
574 }
575
Popular Tags