KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectweb > jonas > web > catalina55 > CatalinaJWebContainerServiceImpl


1 /**
2  * JOnAS: Java(TM) Open Application Server
3  * Copyright (C) 2005 Bull S.A.
4  * Contact: jonas-team@objectweb.org
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19  * USA
20  *
21  * --------------------------------------------------------------------------
22  * $Id: CatalinaJWebContainerServiceImpl.java,v 1.9 2005/06/17 12:44:01 sauthieg Exp $
23  * --------------------------------------------------------------------------
24  */

25
26 package org.objectweb.jonas.web.catalina55;
27
28 import java.io.File JavaDoc;
29 import java.io.FileInputStream JavaDoc;
30 import java.io.FileNotFoundException JavaDoc;
31 import java.io.InputStream JavaDoc;
32 import java.lang.reflect.Method JavaDoc;
33 import java.net.URL JavaDoc;
34 import java.rmi.RemoteException JavaDoc;
35 import java.util.ArrayList JavaDoc;
36 import java.util.Iterator JavaDoc;
37 import java.util.List JavaDoc;
38 import java.util.StringTokenizer JavaDoc;
39 import java.util.Vector JavaDoc;
40
41 import javax.management.InstanceAlreadyExistsException JavaDoc;
42 import javax.management.MBeanRegistrationException JavaDoc;
43 import javax.management.MBeanServer JavaDoc;
44 import javax.management.MalformedObjectNameException JavaDoc;
45 import javax.management.NotCompliantMBeanException JavaDoc;
46 import javax.management.ObjectName JavaDoc;
47 import javax.naming.LinkRef JavaDoc;
48 import javax.naming.NamingException JavaDoc;
49 import javax.naming.Reference JavaDoc;
50 import javax.naming.StringRefAddr JavaDoc;
51
52 import org.xml.sax.InputSource JavaDoc;
53
54 import org.apache.catalina.Container;
55 import org.apache.catalina.Context;
56 import org.apache.catalina.Engine;
57 import org.apache.catalina.Host;
58 import org.apache.catalina.Lifecycle;
59 import org.apache.catalina.LifecycleException;
60 import org.apache.catalina.Realm;
61 import org.apache.catalina.Server;
62 import org.apache.catalina.Service;
63 import org.apache.catalina.connector.Connector;
64 import org.apache.catalina.core.StandardContext;
65 import org.apache.catalina.core.StandardEngine;
66 import org.apache.catalina.core.StandardServer;
67 import org.apache.catalina.deploy.ContextResource;
68 import org.apache.catalina.deploy.NamingResources;
69 import org.apache.catalina.startup.ContextConfig;
70 import org.apache.commons.modeler.Registry;
71 import org.apache.tomcat.util.digester.Digester;
72
73 import org.objectweb.jonas_lib.I18n;
74
75 import org.objectweb.jonas.jmx.J2eeObjectName;
76 import org.objectweb.jonas.jmx.JonasObjectName;
77 import org.objectweb.jonas.security.realm.web.catalina55.JACC;
78 import org.objectweb.jonas.server.LoaderManager;
79 import org.objectweb.jonas.service.ServiceException;
80 import org.objectweb.jonas.web.AbsJWebContainerServiceImpl;
81 import org.objectweb.jonas.web.JWebContainerServiceException;
82 import org.objectweb.jonas.web.lib.PermissionManager;
83 import org.objectweb.jonas.web.wrapper.CatalinaJWebContainerService;
84
85 import org.objectweb.util.monolog.api.BasicLevel;
86
87 /**
88  * This class provides an implementation of the Catalina service
89  * (as web container service).
90  * @author Florent Benoit
91  * @author Ludovic Bert (Tomcat 4.0)
92  */

93 public class CatalinaJWebContainerServiceImpl
94     extends AbsJWebContainerServiceImpl
95     implements CatalinaJWebContainerService {
96
97     /**
98      * Relative path of the configuration file
99      */

100     protected static final String JavaDoc CONFIG_FILE = "conf/server.xml";
101
102     /**
103      * Internationalization
104      */

105     private static I18n i18n = null;
106
107     /**
108      * The reference on the catalina server.
109      */

110     private Server JavaDoc server = null;
111
112     /**
113      * The shared extensions class loader for this server.
114      */

115     private ClassLoader JavaDoc parentClassLoader = null;
116
117     /**
118      * Catalina loader
119      */

120     private ClassLoader JavaDoc catalinaLoader = null;
121
122     /**
123      * Web container started ?
124      */

125     private boolean tomcatStarted = false;
126
127
128     /**
129      * Initialize the Catalina service.
130      * @param ctx the configuration context of the service.
131      * @throws ServiceException if the initialization failed.
132      */

133     protected void doInit(javax.naming.Context JavaDoc ctx) throws ServiceException {
134         super.doInit(ctx);
135
136         // Set the environment
137
initCatalinaEnvironment();
138
139         // parent ClassLoader
140
LoaderManager lm = LoaderManager.getInstance();
141         try {
142             parentClassLoader = lm.getAppsLoader();
143             catalinaLoader = lm.getCatalinaLoader();
144         } catch (Exception JavaDoc e1) {
145             throw new ServiceException("Cannot get Application/Catalina ClassLoader", e1);
146         }
147
148         // Internationalization
149
i18n = I18n.getInstance(CatalinaJWebContainerServiceImpl.class, catalinaLoader);
150
151         // Add JOnAS-Tomcat mbean
152
if (getLogger().isLoggable(BasicLevel.DEBUG)) {
153             getLogger().log(BasicLevel.DEBUG, "Add mbeans descriptions to the JMX Registry");
154         }
155         InputStream JavaDoc stream = this.getClass().getResourceAsStream("/org/objectweb/jonas/web/catalina55/mbeans-descriptors.xml");
156         try {
157             Registry.loadRegistry(stream);
158             stream.close();
159         } catch (Exception JavaDoc e) {
160             getLogger().log(BasicLevel.ERROR, "Can't add the mbeans description into Tomcat" + e.getMessage());
161         }
162
163         // Add MBean for Catalina Connector creation
164
CatalinaConnectorFactory cf = new CatalinaConnectorFactory();
165         MBeanServer JavaDoc mbeanServer = getMbeanServer();
166         cf.setMyServer(mbeanServer);
167         if (mbeanServer != null) {
168             ObjectName JavaDoc on = null;
169             try {
170                 on = JonasObjectName.catalinaConnectorFactory(getDomainName());
171                 mbeanServer.registerMBean(cf, on);
172             } catch (MalformedObjectNameException JavaDoc e1) {
173                 getLogger().log(BasicLevel.WARN, "Can't create Objectname for CatalinaConnectorFactory MBean");
174             } catch (InstanceAlreadyExistsException JavaDoc e2) {
175                 getLogger().log(BasicLevel.WARN, "MBean named " + on.toString() + "already registered in the MBean server");
176             } catch (MBeanRegistrationException JavaDoc e2) {
177                 getLogger().log(BasicLevel.WARN, "Can't register MBean " + on.toString());
178                 e2.printStackTrace();
179             } catch (NotCompliantMBeanException JavaDoc e2) {
180                 getLogger().log(BasicLevel.WARN, "Can't register MBean " + on.toString());
181                 e2.printStackTrace();
182             }
183         }
184
185         // Add MBean for WebModule Proxy creation
186
WebModuleProxy px = new WebModuleProxy();
187         px.setMyServer(mbeanServer);
188         if (mbeanServer != null) {
189             ObjectName JavaDoc on = null;
190             try {
191                 on = JonasObjectName.webModuleProxy(getDomainName());
192                 mbeanServer.registerMBean(px, on);
193             } catch (MalformedObjectNameException JavaDoc e1) {
194                 getLogger().log(BasicLevel.WARN, "Can't create Objectname for WebModuleProxy MBean");
195             } catch (InstanceAlreadyExistsException JavaDoc e2) {
196                 getLogger().log(BasicLevel.WARN, "MBean named " + on.toString() + "already registered in the MBean server");
197             } catch (MBeanRegistrationException JavaDoc e2) {
198                 getLogger().log(BasicLevel.WARN, "Can't register MBean " + on.toString());
199                 e2.printStackTrace();
200             } catch (NotCompliantMBeanException JavaDoc e2) {
201                 getLogger().log(BasicLevel.WARN, "Can't register MBean " + on.toString());
202                 e2.printStackTrace();
203             }
204         }
205     }
206
207
208     /**
209      * Init the environment of catalina
210      * set catalina.home, catalina.base and unset the tomcat naming
211      * @throws ServiceException if catalina home is not set
212      */

213     protected void initCatalinaEnvironment() throws ServiceException {
214
215         // if the user do not specify catalina.base,
216
// set catalina.base to catalina.home.
217
String JavaDoc catalinaHome = System.getProperty("catalina.home");
218         if (catalinaHome != null) {
219             if (System.getProperty("catalina.base") == null) {
220                 System.setProperty("catalina.base", catalinaHome);
221             }
222         } else {
223             throw new ServiceException("catalina.home property is not set");
224         }
225
226         // use the JOnAS naming instead of Tomcat naming
227
System.setProperty("catalina.useNaming", "false");
228     }
229
230
231     /**
232      * Start the Catalina service in a new thread
233      * @throws ServiceException if the startup failed.
234      */

235     public void doStart() throws ServiceException {
236
237         // Create the digester for the parsing of the server.xml.
238
Digester digester = createServerDigester();
239
240         // Execute the digester for the parsing of the server.xml.
241
// And configure the catalina server.
242
File JavaDoc configFile = null;
243
244         try {
245             configFile = getConfigFile();
246         } catch (FileNotFoundException JavaDoc e) {
247             String JavaDoc err = i18n.getMessage("CatJWebServ.doStart.fileNotFound", configFile, e.getMessage());
248             getLogger().log(BasicLevel.ERROR, err);
249             throw new ServiceException(err, e);
250         }
251
252         try {
253             InputSource JavaDoc is = new InputSource JavaDoc("file://" + configFile.getAbsolutePath());
254             FileInputStream JavaDoc fis = new FileInputStream JavaDoc(configFile);
255             is.setByteStream(fis);
256             digester.push(this);
257             digester.parse(is);
258             fis.close();
259         } catch (Exception JavaDoc e) {
260             String JavaDoc err = i18n.getMessage("CatJWebServ.doStart.readfileError", configFile, e.getMessage());
261             getLogger().log(BasicLevel.ERROR, err);
262             throw new ServiceException(err, e);
263         }
264
265         javax.naming.Context JavaDoc ctxOld = setGlobalNamingResources();
266
267         // Set the Domain and the name for each known Engine
268
Iterator JavaDoc it = getEngines().iterator();
269         while (it.hasNext()) {
270             StandardEngine oSE = (StandardEngine) it.next();
271             // WARNING : the order of th two next lines is very important.
272
// The domain must be set in first and the name after.
273
// In the others cases, Tomcat 5 doesn't set correctly these two properties
274
// because there are somes controls that forbid to have a difference between
275
// the name and the domain. Certainly a bug !
276
oSE.setDomain(getDomainName());
277             oSE.setName(getDomainName());
278         }
279
280         // Finaly start catalina ...
281
if (server instanceof Lifecycle) {
282             try {
283                 server.initialize();
284                 ((Lifecycle) server).start();
285             } catch (Exception JavaDoc e) {
286                 String JavaDoc err = i18n.getMessage("CatJWebServ.doStart.startCatalinaError");
287                 getLogger().log(BasicLevel.ERROR, err);
288                 throw new ServiceException(e.getMessage(), e);
289             }
290         }
291         // Reset server context
292
getNaming().setComponentContext(ctxOld);
293
294         // Tomcat is started
295
tomcatStarted = true;
296
297         // ... and deploy wars of the jonas.properties
298
super.doStart();
299     }
300
301     /**
302      * Defines the naming resources for tomcat
303      * only use for avoid null pointer when using a server.xml of
304      * the original distribution
305      * @return the previous naming context
306      * @throws ServiceException if a naming exception occurs
307      */

308     protected javax.naming.Context JavaDoc setGlobalNamingResources() throws ServiceException {
309         // Set the global context of the server
310
NamingResources namingResources = server.getGlobalNamingResources();
311         javax.naming.Context JavaDoc globalCtx = null;
312         javax.naming.Context JavaDoc ctxold = null;
313         try {
314             globalCtx = getNaming().createEnvironmentContext("catalina_global");
315             ctxold = getNaming().setComponentContext(globalCtx);
316
317             int i;
318             // Resources
319
ContextResource[] resources = namingResources.findResources();
320             for (i = 0; i < resources.length; i++) {
321                 addResource(globalCtx, resources[i]);
322             }
323         } catch (NamingException JavaDoc e) {
324             String JavaDoc err = i18n.getMessage("CatJWebServ.doStart.populateEnvError", e.getMessage());
325             getLogger().log(BasicLevel.ERROR, err);
326             throw new ServiceException(err, e);
327         }
328         // Set the global naming context of the server
329
((StandardServer) server).setGlobalNamingContext(globalCtx);
330         return ctxold;
331     }
332
333
334     /**
335      * Stop the Catalina service.
336      * @throws ServiceException if the stop failed.
337      */

338     protected void doStop() throws ServiceException {
339         // Undeploy the wars ...
340
super.doStop();
341
342         // ... and shut down embedded catalina
343
if (server instanceof Lifecycle) {
344             try {
345                 ((Lifecycle) server).stop();
346             } catch (Exception JavaDoc e) {
347                 String JavaDoc err = i18n.getMessage("CatJWebServ.doStop.stopCatalinaError");
348                 getLogger().log(BasicLevel.ERROR, err);
349                 throw new ServiceException(e.getMessage(), e);
350             }
351         }
352
353     }
354
355
356     /**
357      * Deploy a specific WAR file specified in the context.
358      * @param ctx the context which contains the configuration in order
359      * to deploy the WAR.
360      * @throws JWebContainerServiceException if the registration of the WAR
361      * failed.
362      */

363     protected void doRegisterWar(javax.naming.Context JavaDoc ctx)
364         throws JWebContainerServiceException {
365         // Get the 7 parameters :
366
// - warURL is the URL of the war to register (required param).
367
// - contextRoot is the context root to which this application
368
// should be installed (must be unique) (required param).
369
// - hostName is the name of the host on which deploy the war
370
// (optional param taken into account only if no <context> element
371
// was declared in server.xml for this web application) .
372
// - Name of the Ear application of this war if any
373
// - java2DelegationModel the compliance to java2 delegation model
374
// - parentCL the war classloader of this war.
375
// - jonasDD JOnAS Deployment Desc content
376
// - permissionManager JACC permission manager
377

378         URL JavaDoc warURL = null;
379         URL JavaDoc earURL = null;
380         URL JavaDoc unpackedWarURL = null;
381         String JavaDoc contextRoot = null;
382         boolean java2DelegationModel = true;
383         PermissionManager permissionManager = null;
384         boolean inEarCase = true;
385         String JavaDoc earAppName = null;
386         String JavaDoc jonasDD = null;
387         try {
388             warURL = (URL JavaDoc) ctx.lookup("warURL");
389             unpackedWarURL = (URL JavaDoc) ctx.lookup("unpackedWarURL");
390             contextRoot = (String JavaDoc) ctx.lookup("contextRoot");
391             Boolean JavaDoc bool = (Boolean JavaDoc) ctx.lookup("java2DelegationModel");
392             java2DelegationModel = bool.booleanValue();
393             jonasDD = (String JavaDoc) ctx.lookup("jonasDD");
394             permissionManager = (PermissionManager) ctx.lookup("permissionManager");
395         } catch (NamingException JavaDoc e) {
396             String JavaDoc err = i18n.getMessage("CatJWebServ.doRegisterWar.gettingParamError");
397             getLogger().log(BasicLevel.ERROR, err + e.getMessage());
398             throw new JWebContainerServiceException(err, e);
399         }
400
401         try {
402             earAppName = (String JavaDoc) ctx.lookup("earAppName");
403             earURL = (URL JavaDoc) ctx.lookup("earURL");
404         } catch (NamingException JavaDoc e) {
405             // no ear case, so no ear application name
406
inEarCase = false;
407             // set earURL to something only to avoid null value
408
earURL = warURL;
409         }
410
411         ClassLoader JavaDoc webClassLoader = null;
412
413         try {
414             webClassLoader = (ClassLoader JavaDoc) ctx.lookup("parentCL");
415         } catch (NamingException JavaDoc e) {
416             String JavaDoc err = i18n.getMessage("CatJWebServ.doRegisterWar.gettingParamError");
417             getLogger().log(BasicLevel.ERROR, err + e.getMessage());
418             throw new JWebContainerServiceException(err, e);
419         }
420
421         String JavaDoc hostName = null;
422         try {
423             hostName = (String JavaDoc) ctx.lookup("hostName");
424         } catch (NamingException JavaDoc e) {
425             hostName = "";
426         }
427
428         // Install a new web application, whose web application archive is
429
// at the specified URL, into this container with the specified
430
// context root.
431
// A context root of "" (the empty string) should be used for the root
432
// application for this container. Otherwise, the context root must
433
// start with a slash.
434

435         if (contextRoot.equals("/")) {
436             contextRoot = "";
437         } else {
438             contextRoot = "/" + contextRoot;
439         }
440
441         // Install the war.
442
File JavaDoc fWar = new File JavaDoc(warURL.getFile());
443         //File fpackedWar = new File(packedWarURL.getFile());
444

445         // Unpacked path of the war
446
String JavaDoc destDir = null;
447         if (fWar.isDirectory()) {
448             destDir = warURL.getPath();
449         } else {
450             destDir = unpackedWarURL.getPath();
451         }
452
453         // META-INF/context.xml file
454
File JavaDoc contextXmlFile = new File JavaDoc(destDir + File.separator + "META-INF" + File.separator + "context.xml");
455
456
457         // Check if some contexts were configured in server.xml
458
List JavaDoc jonasContexts = getConfiguredMatchingJonasContexts(contextRoot, fWar, destDir);
459
460         Host deployer = null;
461         // The context was not found in server.xml, a new context will be created.
462
if (jonasContexts.isEmpty()) {
463             // Find host on which deploy the context
464
deployer = findHost(hostName);
465
466             // Create context (false because not in server.xml)
467
JOnASStandardContext context = new JOnASStandardContext(false, java2DelegationModel, inEarCase);
468             context.setDocBase(destDir);
469             context.setPath(contextRoot);
470             ContextConfig config = new ContextConfig();
471
472             // add the config
473
((Lifecycle) context).addLifecycleListener(config);
474             jonasContexts.add(context);
475         }
476
477         // Configure these contexts and start them
478
Iterator JavaDoc it = jonasContexts.iterator();
479         while (it.hasNext()) {
480             JOnASStandardContext jStdCtx = (JOnASStandardContext) it.next();
481
482             // Set the parent class loader
483
jStdCtx.setParentClassLoader(webClassLoader);
484
485             // Delegation model
486
jStdCtx.setDelegate(java2DelegationModel);
487             if (getLogger().isLoggable(BasicLevel.DEBUG)) {
488                 getLogger().log(BasicLevel.DEBUG, "Webapp class loader java 2 delegation model set to " + java2DelegationModel);
489             }
490
491             // META-INF/context.xml file support
492
if (contextXmlFile.exists()) {
493                 jStdCtx.setConfigFile(contextXmlFile.getAbsolutePath());
494             }
495
496             // JSR 77
497
jStdCtx.setJ2EEServer(getJonasServerName());
498             jStdCtx.setServer(J2eeObjectName.J2EEServer(getDomainName(), getJonasServerName()).toString());
499             if (getMbeanServer() != null) {
500                 try {
501                     String JavaDoc[] as = (String JavaDoc[]) getMbeanServer().getAttribute(J2eeObjectName.J2EEServer(getDomainName()
502                         , getJonasServerName()), "javaVMs");
503                     jStdCtx.setJavaVMs(as);
504                 } catch (Exception JavaDoc e) {
505                     //String err = i18n.getMessage("CatJWebServ.doRegisterWar.startContextError", jStdCtx);
506
//getLogger().log(BasicLevel.WARN, err + e.getMessage());
507
getLogger().log(BasicLevel.WARN, "Set MBean JVM error : " + e.getClass().getName() + " " + e.getMessage());
508                 }
509             }
510             if (earAppName != null) {
511                 jStdCtx.setJ2EEApplication(earAppName);
512             }
513             jStdCtx.setJonasDeploymentDescriptor(jonasDD);
514
515             // Set the realm
516
Realm ctxRealm = jStdCtx.getRealm();
517
518             // Take realm of parent
519
if (ctxRealm == null) {
520                 ctxRealm = deployer.getRealm();
521             }
522
523
524             if (ctxRealm != null && ctxRealm instanceof JACC) {
525                 JACC jaccRealm = null;
526                 try {
527                     jaccRealm = (JACC) ((JACC) ctxRealm).clone();
528                 } catch (CloneNotSupportedException JavaDoc cnse) {
529                     String JavaDoc err = "Cannot clone the realm used by the existing context or its parent realm";
530                     getLogger().log(BasicLevel.ERROR, err + cnse.getMessage());
531                     throw new JWebContainerServiceException(err, cnse);
532                 }
533                 if (getLogger().isLoggable(BasicLevel.DEBUG)) {
534                     getLogger().log(BasicLevel.DEBUG, "Setting permission manager to " + permissionManager);
535                 }
536                 jaccRealm.setPermissionManager(permissionManager);
537                 jaccRealm.setContext(jStdCtx);
538                 // Set the new realm
539
jStdCtx.setRealm(jaccRealm);
540             }
541
542             // Set the attributes transfered from the JOnAS War MBean.
543
// Note that 'java2DelegationModel' and 'inEarCase' attributes
544
// are passed asarguments to the JOnASStandardContext's constructor
545
jStdCtx.setWarURL(warURL);
546             if (inEarCase) {
547                 jStdCtx.setEarURL(earURL);
548             }
549
550             // ... and start it or add it
551
if (jStdCtx.isInServerXml()) {
552                 try {
553                     jStdCtx.setLoader(null);
554                     jStdCtx.start();
555                 } catch (LifecycleException lce) {
556                     String JavaDoc err = i18n.getMessage("CatJWebServ.doRegisterWar.startContextError", jStdCtx);
557                     getLogger().log(BasicLevel.ERROR, err + lce.getMessage());
558                     throw new JWebContainerServiceException(err, lce);
559
560                 }
561             } else {
562                 // add it
563
if (deployer == null) {
564                     String JavaDoc err = i18n.getMessage("CatJWebServ.doRegisterWar.deployerIsNull", jStdCtx);
565                     getLogger().log(BasicLevel.ERROR, err);
566                     throw new JWebContainerServiceException(err);
567                 }
568                 deployer.addChild(jStdCtx);
569             }
570
571             // ...and check if it is now configured
572
checkStartedContext(jStdCtx, permissionManager);
573
574             // Store WebModule ObjectName in Context
575
try {
576                 ctx.rebind("WebModule", jStdCtx.createObjectName(getDomainName(), jStdCtx.getParentName()));
577             } catch(Exception JavaDoc e) {
578                 // NamingException or Mbean related Exception
579
// TODO i18n
580
String JavaDoc err = "Cannot rebind WebModule ObjectName in Context";
581                 getLogger().log(BasicLevel.ERROR, err, e);
582                 throw new JWebContainerServiceException(err, e);
583             }
584         }
585     }
586
587
588     /**
589      * Check if there is a previous JOnASStandardContext which match the current context
590      * If true, deploy our context into the configured context
591      * @param contextRoot name of the context that we want to find preconfigured contexts
592      * @param fpackedWar file of the original war file
593      * @param destDir name of the unpacked directory of the war file
594      * @return true if a context was found and used
595      */

596     protected List JavaDoc getConfiguredMatchingJonasContexts(String JavaDoc contextRoot, File JavaDoc fpackedWar, String JavaDoc destDir) {
597         ArrayList JavaDoc jonasContexts = new ArrayList JavaDoc();
598         // Check contexts of all services to see if there is a configured context.
599
// that we must use instead of creating a new one.
600
// If a context is matching, we set its docbase and start it.
601
Iterator JavaDoc it = getContexts().iterator();
602         while (it.hasNext()) {
603             Context ctx = (Context) it.next();
604             // Continue if it is not a JOnAS context
605
if (!(ctx instanceof JOnASStandardContext)) {
606                 continue;
607             }
608             JOnASStandardContext jStdCtx = (JOnASStandardContext) ctx;
609             if (jStdCtx != null) {
610                 // Not created in server.xml file
611
if (!jStdCtx.isInServerXml()) {
612                     continue;
613                 }
614
615                 // The context was configured ?
616
String JavaDoc serverCtxRoot = jStdCtx.getPath();
617                 if (!serverCtxRoot.equals(contextRoot)) {
618                     continue;
619                 }
620                 if (jStdCtx.getPrivileged()) {
621                     // Can deploy a privileged context only if it's a .war file
622
if (fpackedWar.isDirectory()) {
623                         String JavaDoc err = i18n.getMessage("CatJWebServ.getConfiguredMatchingJonasContexts.privilegedContextError");
624                         getLogger().log(BasicLevel.ERROR, err);
625                     }
626                     jStdCtx.setDocBase(fpackedWar.getPath());
627                 } else {
628                     jStdCtx.setDocBase(destDir);
629                 }
630                 jonasContexts.add(jStdCtx);
631             }
632         }
633         return jonasContexts;
634     }
635
636
637     /**
638      * Check that the context that was started was right configured
639      * @param context context to check
640      * @param permissionManager the permission manager used for JACC
641      * @throws JWebContainerServiceException if the context was not right configured
642      */

643     protected void checkStartedContext(Context context, PermissionManager permissionManager) throws JWebContainerServiceException {
644         // Check if the context was configured
645
if (!context.getConfigured()) {
646             String JavaDoc err = i18n.getMessage("CatJWebServ.checkStartedContext.configuredFail", context.getName());
647             getLogger().log(BasicLevel.ERROR, err);
648             throw new JWebContainerServiceException(err);
649         }
650         ((JOnASStandardContext) context).unsetAuthenticationCaching();
651
652         // Check that JACC realm is correctly set
653
Realm ctxRealm = context.getRealm();
654         if (ctxRealm != null && ctxRealm instanceof JACC) {
655             JACC jaccRealm = (JACC) ctxRealm;
656             PermissionManager ctxPerm = jaccRealm.getPermissionManager();
657             if (ctxPerm == null && permissionManager != null) {
658                 jaccRealm.setPermissionManager(permissionManager);
659             }
660         }
661         if (getLogger().isLoggable(BasicLevel.DEBUG)) {
662             getLogger().log(BasicLevel.DEBUG, "context " + context + " started");
663         }
664
665     }
666
667     /**
668      * Gets all the engines of the current Tomcat server
669      * @return all the engines of the current Tomcat server
670      * @throws JWebContainerServiceException if engines can not be retrieved
671      */

672     protected synchronized List JavaDoc getEngines() throws JWebContainerServiceException {
673         List JavaDoc engines = new ArrayList JavaDoc();
674         Service[] services = server.findServices();
675
676         // Get contexts of each engine of each service
677
for (int s = 0; s < services.length; s++) {
678             Container cont = services[s].getContainer();
679             if (!(cont instanceof Engine)) {
680                 String JavaDoc err = "The container of the service must be an engine (server.xml)";
681                 throw new JWebContainerServiceException(err);
682             }
683             engines.add(cont);
684         }
685         return engines;
686     }
687
688     /**
689      * Gets all the contexts of the current Tomcat server
690      * @return all the contexts of the current Tomcat server
691      * @throws JWebContainerServiceException if contexts can not be retrieved
692      */

693     protected synchronized List JavaDoc getContexts() throws JWebContainerServiceException {
694         List JavaDoc contexts = new ArrayList JavaDoc();
695
696         Iterator JavaDoc itEngines = getEngines().iterator();
697         while (itEngines.hasNext()) {
698             Engine engine = (Engine) itEngines.next();
699             Container[] hosts = engine.findChildren();
700
701             for (int j = 0; j < hosts.length; j++) {
702                 Container[] containers = hosts[j].findChildren();
703                 for (int k = 0; k < containers.length; k++) {
704                     Container container = containers[k];
705                     if (container instanceof Context) {
706                         contexts.add(container);
707                     }
708                 }
709             }
710         }
711         return contexts;
712     }
713
714
715     /**
716      * Undeploy a specific WAR file specified in the context.
717      * @param ctx the context which contains the configuration in order
718      * to undeploy a WAR.
719      * @throws JWebContainerServiceException if the unregistration failed.
720      */

721     protected void doUnRegisterWar(javax.naming.Context JavaDoc ctx)
722         throws JWebContainerServiceException {
723
724         // Get the 2 parameters :
725
// - contextRoot is the context root to be removed (required param).
726
// - hostName is the name of the host to remove the war (optional).
727
String JavaDoc contextRoot = null;
728         try {
729             contextRoot = (String JavaDoc) ctx.lookup("contextRoot");
730         } catch (NamingException JavaDoc e) {
731             String JavaDoc err = i18n.getMessage("CatJWebServ.doUnRegisterWar.gettingParamError");
732             getLogger().log(BasicLevel.ERROR, err + e.getMessage());
733             throw new JWebContainerServiceException(err, e);
734         }
735
736         if (contextRoot.equals("/")) {
737             contextRoot = "";
738         } else {
739             contextRoot = "/" + contextRoot;
740         }
741
742         String JavaDoc hostName = null;
743         try {
744             hostName = (String JavaDoc) ctx.lookup("hostName");
745         } catch (NamingException JavaDoc e) {
746             if (getLogger().isLoggable(BasicLevel.DEBUG)) {
747                 getLogger().log(BasicLevel.DEBUG, "No define hostname for this context");
748             }
749         }
750
751         // Undeploy all matching context if there is no hostname provided
752
if (hostName == null) {
753             boolean found = false;
754             Iterator JavaDoc it = getContexts().iterator();
755             while (it.hasNext()) {
756                 Context context = (Context) it.next();
757                 String JavaDoc serverCtxRoot = context.getPath();
758                 if (serverCtxRoot.equals(contextRoot)) {
759                     removeContext(context);
760                     found = true;
761                 }
762             }
763             if (!found) {
764                 String JavaDoc err = i18n.getMessage("CatJWebServ.doUnRegisterWar.undeployError", contextRoot);
765                 getLogger().log(BasicLevel.ERROR, err);
766                 throw new JWebContainerServiceException(err);
767             }
768         } else {
769             // Remove the specified Context from the set of defined Contexts
770
// for its associated Host.
771
Host host = findHost(hostName);
772             org.apache.catalina.Context context = host.map(contextRoot);
773             if (context != null) {
774                 removeContext(context);
775             } else {
776                 String JavaDoc err = i18n.getMessage("CatJWebServ.doUnRegisterWar.undeployError", contextRoot);
777                 getLogger().log(BasicLevel.ERROR, err);
778                 throw new JWebContainerServiceException(err);
779             }
780         }
781     }
782
783
784     /**
785      * Remove the specified Context from the set of defined Contexts for its
786      * associated Host. If this is the last Context for this Host, the Host
787      * will also be removed.
788      *
789      * @param context The Context to be removed
790      * @throws JWebContainerServiceException if the context can not be removed
791      */

792     public synchronized void removeContext(Context context) throws JWebContainerServiceException {
793
794         // Is this Context actually among those that are deployed ?
795
boolean found = false;
796         Iterator JavaDoc it = getContexts().iterator();
797         while (it.hasNext() && !found) {
798             if (context == (Context) it.next()) {
799                 found = true;
800             }
801         }
802
803         if (!found) {
804             return;
805         }
806         // Remove this Context from the associated Host
807
// Or stop it if it is a JOnAS standard context (to keep the configuration)
808
if (context instanceof JOnASStandardContext) {
809             JOnASStandardContext jctx = (JOnASStandardContext) context;
810             if (jctx.isInServerXml()) {
811                 try {
812                     ((JOnASStandardContext) context).stop();
813                 } catch (LifecycleException le) {
814                     throw new JWebContainerServiceException("Cannot stop context (" + le.getMessage() + ")");
815                 }
816             } else {
817                 // must not persist
818
context.getParent().removeChild(context);
819                 // Bug Tomcat 5 doesn't remove MBean WebModule
820
// Delete the next line when will be fixed
821
// Bug Tomcat 5 : begin
822
if (getMbeanServer() != null) {
823                     try {
824                         // unregister WebModule MBean
825
getMbeanServer().unregisterMBean(jctx.getJmxName());
826                     } catch (Exception JavaDoc e) {
827                         getLogger().log(BasicLevel.ERROR, "Cannot remove the MBean for the WebModule " + jctx.getObjectName() + " : " + e.getMessage());
828                     }
829                 }
830             }
831         } else {
832             context.getParent().removeChild(context);
833             // Bug Tomcat 5 doesn't remove MBean WebModule
834
// Delete the next line when will be fixed
835
// Bug Tomcat 5 : begin
836
if (context instanceof StandardContext) {
837                 StandardContext ctx = (StandardContext) context;
838                 if (getMbeanServer() != null) {
839                     try {
840                         // unregister WebModule MBean
841
getMbeanServer().unregisterMBean(ctx.getJmxName());
842                     } catch (Exception JavaDoc e) {
843                         getLogger().log(BasicLevel.ERROR
844                             , "Cannot remove the MBean for the WebModule " + ctx.getObjectName()
845                             + " : " + e.getMessage());
846                     }
847                 }
848             }
849         }
850
851     }
852
853
854     /**
855      * The server is started ?
856      * @return boolean true if the catalina container is running.
857      */

858     public boolean isTomcatStarted() {
859         return tomcatStarted;
860     }
861
862
863     /**
864      * Set the server instance we are configuring.
865      *
866      * @param server The new server
867      */

868     public void setServer(Server JavaDoc server) {
869         this.server = server;
870     }
871
872
873     /**
874      * Return a File object representing the server.xml configuration file.
875      * @return a File object representing the server.xml configuration file.
876      * @throws FileNotFoundException if the configuration file is not found.
877      */

878     protected File JavaDoc getConfigFile() throws FileNotFoundException JavaDoc {
879         String JavaDoc fileName = System.getProperty("catalina.base");
880         fileName = fileName + File.separator + CONFIG_FILE;
881         File JavaDoc file = new File JavaDoc(fileName);
882         if (!file.exists()) {
883             String JavaDoc err = i18n.getMessage("CatJWebServ.getConfigFile.findfileError", fileName);
884             throw new FileNotFoundException JavaDoc(err);
885         }
886         return (file);
887     }
888
889
890     /**
891      * Find the specified host.
892      * @param hostName the name of the host to find.
893      * @return the host found.
894      * @throws JWebContainerServiceException if the specified host cannot be
895      * found.
896      */

897     public Host findHost(String JavaDoc hostName)
898         throws JWebContainerServiceException {
899
900         Service[] services = server.findServices();
901         // Check number of services
902
if (services.length < 1) {
903             String JavaDoc err = "At least one service must be define in the server.xml of Tomcat";
904             throw new JWebContainerServiceException(err);
905         }
906
907         // Two cases :
908
// 1/ No host specified
909
// -> defaulthost of the engine of the first service.
910
// 2) A host is specified in the jonas-web.xml
911
// -> find the host and deploy on this host
912

913
914         if (hostName == null || hostName.equals("")) {
915             // First case
916

917             //Take first service
918
Service service = services[0];
919
920             Container cont = service.getContainer();
921             if (!(cont instanceof Engine)) {
922                 String JavaDoc err = "The container of the service must be an engine";
923                 throw new JWebContainerServiceException(err);
924             }
925
926             Engine engine = (Engine) cont;
927             String JavaDoc defaultHost = engine.getDefaultHost();
928             if (defaultHost == null) {
929                 String JavaDoc err = "Default host must be specified in server.xml or host must be specified in jonas-web.xml";
930                 throw new JWebContainerServiceException(err);
931             }
932             Container child = engine.findChild(defaultHost);
933             // found, return it
934
if (child instanceof Host) {
935                 return (Host) child;
936             }
937             // else error
938
String JavaDoc err = "Default host " + defaultHost + " not found";
939             throw new JWebContainerServiceException(err);
940         }
941         // Get all hosts.
942
Vector JavaDoc hosts = new Vector JavaDoc();
943
944         for (int s = 0; s < services.length; s++) {
945             Container cont = services[s].getContainer();
946             if (!(cont instanceof Engine)) {
947                 String JavaDoc err = "The container of a service must be an engine";
948                 throw new JWebContainerServiceException(err);
949             }
950             Engine engine = (Engine) cont;
951             Container child = engine.findChild(hostName);
952             if (child instanceof Host) {
953                 hosts.addElement(child);
954             }
955         }
956
957         // error
958
if (hosts.size() == 0) {
959             // No host found.
960
String JavaDoc err = "Host " + hostName + " not found in all services/Engine of server.xml";
961             throw new JWebContainerServiceException(err);
962         }
963
964         // first element
965
return (Host) hosts.elementAt(0);
966     }
967
968
969     /**
970      * Set the specified resources in the naming context.
971      * @param ctx the context where the bindings are set.
972      * @param resource the resource to bind.
973      * @throws JWebContainerServiceException if the bind failed.
974      */

975     private void addResource(javax.naming.Context JavaDoc ctx, ContextResource resource) throws JWebContainerServiceException {
976
977         String JavaDoc name = resource.getName();
978         String JavaDoc type = resource.getType();
979         String JavaDoc registryName = name;
980
981         // Add only UserDatabase resources
982
if (!type.equals("org.apache.catalina.UserDatabase")) {
983             return;
984         }
985
986         // Create a reference to the resource.
987
Reference JavaDoc ref = new Reference JavaDoc("org.apache.catalina.UserDatabase", "org.apache.catalina.users.MemoryUserDatabaseFactory", null);
988
989         // Add extra parameters
990
Iterator JavaDoc params = resource.listProperties();
991         while (params.hasNext()) {
992             String JavaDoc paramName = (String JavaDoc) params.next();
993             String JavaDoc paramValue = (String JavaDoc) resource.getProperty(paramName);
994             StringRefAddr JavaDoc refAddr = new StringRefAddr JavaDoc(paramName, paramValue);
995             ref.add(refAddr);
996         }
997         try {
998             javax.naming.Context JavaDoc ictx = getNaming().getInitialContext();
999
1000            // Bind into registry
1001
ictx.rebind(registryName, ref);
1002
1003            // Bind LinkRef
1004
LinkRef JavaDoc lref = new LinkRef JavaDoc(registryName);
1005            ctx.rebind(name, lref);
1006
1007        } catch (Exception JavaDoc e) {
1008            e.printStackTrace();
1009            String JavaDoc err = "Can't add the resource " + name;
1010            throw new JWebContainerServiceException(err, e);
1011        }
1012    }
1013
1014
1015    /**
1016     * Create and configure the Digester that will be used for the xml
1017     * parsing of the configuration file.
1018     * @return Digester the digester containing the rules for the xml parsing
1019     * of the server.xml.
1020     */

1021    protected Digester createServerDigester() {
1022
1023        // Initialize the digester
1024
Digester digester = new Digester();
1025        digester.setValidating(false);
1026        digester.addRuleSet(new JCatalinaRuleSet(parentClassLoader));
1027
1028        // Use context class loader.
1029
// Could avoid problem for users putting digester in JONAS_ROOT/lib/ext folder
1030
digester.setUseContextClassLoader(true);
1031        return (digester);
1032
1033    }
1034
1035
1036    /**
1037     * Update info of the serverName and serverVersion
1038     */

1039    protected void updateServerInfos() {
1040        String JavaDoc infos = org.apache.catalina.util.ServerInfo.getServerInfo();
1041        StringTokenizer JavaDoc st = new StringTokenizer JavaDoc(infos, "/");
1042        if (st.countTokens() != 2) {
1043            setServerName(infos);
1044            setServerVersion("");
1045        } else {
1046            setServerName(st.nextToken());
1047            setServerVersion(st.nextToken());
1048        }
1049    }
1050
1051    /**
1052     * Return the Default host name of the web container.
1053     * @return the Default host name of the web container.
1054     * @throws JWebContainerServiceException when default host cannot
1055     * be resolved (multiple services).
1056     */

1057    public String JavaDoc getDefaultHost() throws JWebContainerServiceException {
1058        Engine engine = (Engine) getFirstService().getContainer();
1059        return engine.getDefaultHost();
1060    }
1061
1062
1063    /**
1064     * Return the Default HTTP port number of the web container. Returns the first
1065     * connector port if more than one are defined.
1066     * @return the Default HTTP port number of the web container.
1067     * @throws JWebContainerServiceException when default HTTP port cannot be
1068     * resolved or none are defined.
1069     */

1070    public String JavaDoc getDefaultHttpPort() throws JWebContainerServiceException {
1071        return String.valueOf(getFirstConnectorFromScheme("http").getPort());
1072    }
1073
1074
1075    /**
1076     * @param scheme URL scheme (http, ...)
1077     * @return Returns a List of Connectors for the given scheme (http, https, ...)
1078     */

1079    private Connector getFirstConnectorFromScheme(String JavaDoc scheme) {
1080        Service svc = getFirstService();
1081        // take the first service
1082
Connector[] conn = svc.findConnectors();
1083        Vector JavaDoc httpConn = new Vector JavaDoc();
1084        for (int i = 0; i < conn.length; i++) {
1085            if (conn[i].getScheme().equalsIgnoreCase(scheme)) {
1086                httpConn.add(conn[i]);
1087            }
1088        }
1089
1090        if (httpConn.isEmpty()) {
1091            // No connectors defined
1092
throw new JWebContainerServiceException("No Connectors found for scheme '" + scheme + "' in " + CONFIG_FILE);
1093        }
1094
1095        Connector c = (Connector) httpConn.get(0);
1096
1097        // Check if there are more than one HTTP connectors specified, if so, warn the administrator.
1098
if (httpConn.size() > 1) {
1099            if (getLogger().isLoggable(BasicLevel.WARN)) {
1100                getLogger().log(BasicLevel.WARN, "Found multiple Connectors for scheme '" + scheme + "' in " + CONFIG_FILE
1101                        + ", using first by default! (port:" + c.getPort() + ")");
1102            }
1103        }
1104
1105        return c;
1106    }
1107
1108
1109    /**
1110     * @return Returns the first found Service
1111     */

1112    private Service getFirstService() {
1113        Service[] svc = server.findServices();
1114        // throw exception if no service is defined
1115
if ((svc == null) || (svc.length == 0)) {
1116            // No Services specified.
1117
throw new JWebContainerServiceException("No Services found in " + CONFIG_FILE);
1118        }
1119        // Check if there are more than one services specified and if so, warn the administrator.
1120
if (svc.length > 1) {
1121            if (getLogger().isLoggable(BasicLevel.WARN)) {
1122                getLogger().log(BasicLevel.WARN, "Found multiple Services in " + CONFIG_FILE + ", using first by default!");
1123            }
1124        }
1125        return svc[0];
1126    }
1127
1128
1129    /**
1130     * Return the Default HTTPS port number of the web container (can
1131     * be null if multiple HTTPS connector has been set).
1132     * @return the Default HTTPS port number of the web container.
1133     * @throws JWebContainerServiceException when default HTTPS port cannot be
1134     * resolved (0 occurences).
1135     */

1136    public String JavaDoc getDefaultHttpsPort() throws JWebContainerServiceException {
1137        return String.valueOf(getFirstConnectorFromScheme("https").getPort());
1138    }
1139
1140    /**
1141     * Register a WAR by delegating the operation to the registerWar()
1142     * method. This is used for JMX management.
1143     * @param fileName the name of the war to deploy.
1144     * @throws RemoteException if rmi call failed.
1145     * @throws JWebContainerServiceException if the registration failed.
1146     */

1147    public void registerWarMBean(String JavaDoc fileName) throws RemoteException JavaDoc, JWebContainerServiceException {
1148        ClassLoader JavaDoc old = null;
1149        try {
1150            old = Thread.currentThread().getContextClassLoader();
1151            Thread.currentThread().setContextClassLoader(catalinaLoader);
1152            super.registerWarMBean(fileName);
1153        } catch (Exception JavaDoc e) {
1154            throw new ServiceException("Exception during registering war", e);
1155        } finally {
1156            if (old != null) {
1157                Thread.currentThread().setContextClassLoader(old);
1158            }
1159        }
1160    }
1161
1162    /**
1163     * Unregister a WAR by delegating the operation to the unRegisterWar()
1164     * method. This is used for JMX management.
1165     * @param fileName the name of the war to undeploy.
1166     * @throws RemoteException if rmi call failed.
1167     * @throws JWebContainerServiceException if the unregistration failed.
1168     */

1169    public void unRegisterWarMBean(String JavaDoc fileName) throws RemoteException JavaDoc, JWebContainerServiceException {
1170        ClassLoader JavaDoc old = null;
1171        try {
1172            old = Thread.currentThread().getContextClassLoader();
1173            Thread.currentThread().setContextClassLoader(catalinaLoader);
1174            super.unRegisterWarMBean(fileName);
1175        } catch (Exception JavaDoc e) {
1176            throw new ServiceException("Exception during unregistering war", e);
1177        } finally {
1178            if (old != null) {
1179                Thread.currentThread().setContextClassLoader(old);
1180            }
1181        }
1182    }
1183}
1184
Popular Tags