001: /**
002: * JOnAS: Java(TM) Open Application Server
003: * Copyright (C) 2004 Bull S.A.
004: * Contact: jonas-team@objectweb.org
005: *
006: * This library is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Lesser General Public
008: * License as published by the Free Software Foundation; either
009: * version 2.1 of the License, or any later version.
010: *
011: * This library is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Lesser General Public License for more details.
015: *
016: * You should have received a copy of the GNU Lesser General Public
017: * License along with this library; if not, write to the Free Software
018: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
019: * USA
020: *
021: * --------------------------------------------------------------------------
022: * $Id: CatalinaJWebContainerServiceWrapper.java 6454 2005-03-21 15:02:45Z benoitf $
023: * --------------------------------------------------------------------------
024: */package org.objectweb.jonas.web.wrapper.catalina50;
025:
026: import java.lang.reflect.InvocationTargetException;
027: import java.lang.reflect.Method;
028: import java.net.URL;
029: import java.net.URLClassLoader;
030: import java.rmi.RemoteException;
031: import java.util.Hashtable;
032: import java.util.List;
033: import java.util.Map;
034: import java.util.Set;
035:
036: import javax.naming.Context;
037:
038: import org.objectweb.jonas.server.LoaderManager;
039: import org.objectweb.jonas.service.ServiceException;
040: import org.objectweb.jonas.web.AbsJWebContainerServiceImplMBean;
041: import org.objectweb.jonas.web.JWebContainerServiceException;
042: import org.objectweb.jonas.web.War;
043: import org.objectweb.jonas.web.wrapper.CatalinaJWebContainerService;
044:
045: /**
046: * Wrap the Catalina 5.0 Web Container Service because Catalina use Digester to parse its server.xml
047: *
048: * @author Guillaume Sauthier
049: */
050: public class CatalinaJWebContainerServiceWrapper implements
051: CatalinaJWebContainerService, AbsJWebContainerServiceImplMBean {
052:
053: /**
054: * Catalina ClassLoader
055: */
056: private ClassLoader catalinaLoader = null;
057:
058: /**
059: * CatalinaJWebContainerService instance
060: */
061: private Object catalinaService = null;
062:
063: /**
064: * cached Method Map
065: */
066: private Map methods = null;
067:
068: /**
069: * Catalina service classname
070: */
071: private static final String CATALINA_SERVICE_CLASSNAME = "org.objectweb.jonas.web.catalina50.CatalinaJWebContainerServiceImpl";
072:
073: /**
074: * Construct the instance and init the service.
075: * @throws ServiceException when Catalina Loader cannot be found
076: */
077: public CatalinaJWebContainerServiceWrapper()
078: throws ServiceException {
079: LoaderManager lm = LoaderManager.getInstance();
080: try {
081: catalinaLoader = lm.getCatalinaLoader();
082: } catch (Exception e) {
083: // TODO add i18n error message
084: throw new ServiceException(
085: "Cannot get Catalina ClassLoader", e);
086: }
087: methods = new Hashtable();
088:
089: if (catalinaService == null) {
090: catalinaService = getCatalinaServiceInstance();
091: }
092:
093: }
094:
095: /**
096: * Deploy the given wars of an ear file with the specified parent
097: * classloader (ejb classloader or ear classloader). (This method
098: * is only used for the ear applications, not for the
099: * web applications).
100: * @param ctx the context containing the configuration
101: * to deploy the wars.<BR>
102: * This context contains the following parameters :<BR>
103: * - urls the list of the urls of the wars to deploy.<BR>
104: * - earURL the URL of the ear application file.<BR>
105: * - parentClassLoader the parent classLoader of the wars.<BR>
106: * - earClassLoader the ear classLoader of the j2ee app.<BR>
107: * - altDDs the optional URI of deployment descriptor.<BR>
108: * - contextRoots the optional context root of the wars.<BR>
109: * @throws JWebContainerServiceException if an error occurs during
110: * the deployment.
111: */
112: public void deployWars(Context ctx)
113: throws JWebContainerServiceException {
114:
115: if (catalinaService == null) {
116: catalinaService = getCatalinaServiceInstance();
117: }
118:
119: // method invokation
120: Method m = (Method) methods.get("deployWars");
121: if (m == null) {
122: m = getMethod("deployWars", new Class[] { Context.class });
123: }
124:
125: invoke(m, new Object[] { ctx });
126: }
127:
128: /**
129: * Get the war identified by its URL (.war).
130: * @param url the URL of the war to get.
131: * @return the war indentified by its URL, or null if the war is not found.
132: */
133: public War getWar(URL url) {
134:
135: if (catalinaService == null) {
136: catalinaService = getCatalinaServiceInstance();
137: }
138:
139: // method invokation
140: Method m = (Method) methods.get("getWar");
141: if (m == null) {
142: m = getMethod("getWar", new Class[] { URL.class });
143: }
144:
145: return (War) invoke(m, new Object[] { url });
146:
147: }
148:
149: /**
150: * Invoke a method with the given args
151: * @param m method to invoke
152: * @param params arguments
153: * @return the object if any
154: */
155: private Object invoke(Method m, Object[] params) {
156: ClassLoader old = null;
157: try {
158: old = Thread.currentThread().getContextClassLoader();
159: Thread.currentThread()
160: .setContextClassLoader(catalinaLoader);
161: return m.invoke(catalinaService, params);
162: } catch (InvocationTargetException e) {
163: if (e.getTargetException() instanceof Error) {
164: throw (Error) e.getTargetException();
165: } else if (e.getTargetException() instanceof ServiceException) {
166: throw (ServiceException) e.getTargetException();
167: } else {
168: // TODO add i18n error message
169: throw new ServiceException("Problems when invoking "
170: + m.getName(), e.getTargetException());
171: }
172: } catch (Exception e) {
173: // TODO add i18n error message
174: throw new ServiceException("Problems when invoking "
175: + m.getName(), e);
176: } finally {
177: if (old != null) {
178: Thread.currentThread().setContextClassLoader(old);
179: }
180: }
181: }
182:
183: /**
184: * Gets the method object for a given method name /types
185: * @param methodName name of the method
186: * @param paramTypes arguments
187: * @throws ServiceException if the method cannot be retrieved
188: * @return the wanted method
189: */
190: private Method getMethod(String methodName, Class[] paramTypes)
191: throws ServiceException {
192: try {
193: Method m = catalinaService.getClass().getMethod(methodName,
194: paramTypes);
195: methods.put(methodName, m);
196: return m;
197: } catch (Exception e) {
198: throw new ServiceException("Problems when retrieving "
199: + methodName + " method", e);
200: }
201: }
202:
203: /**
204: * @return Returns a new CatalinaService instance
205: * @throws ServiceException if the instance cannot be retrieved
206: */
207: private Object getCatalinaServiceInstance() throws ServiceException {
208: try {
209: Class service = catalinaLoader
210: .loadClass(CATALINA_SERVICE_CLASSNAME);
211: return service.newInstance();
212: } catch (Exception e) {
213: throw new JWebContainerServiceException(
214: "Problems when loading "
215: + CATALINA_SERVICE_CLASSNAME, e);
216: }
217: }
218:
219: /**
220: * Undeploy the given wars of an ear file with the specified parent
221: * classloader (ejb classloader or ear classloader). (This method
222: * is only used for the ear applications, not for the
223: * war applications).
224: * @param urls the list of the urls of the wars to undeploy.
225: */
226: public void unDeployWars(URL[] urls) {
227:
228: if (catalinaService == null) {
229: catalinaService = getCatalinaServiceInstance();
230: }
231: // method invokation
232: Method m = (Method) methods.get("unDeployWars");
233: if (m == null) {
234: m = getMethod("unDeployWars", new Class[] { URL[].class });
235: }
236:
237: invoke(m, new Object[] { urls });
238:
239: }
240:
241: /**
242: * Make a cleanup of the cache of deployment descriptor. This method must
243: * be invoked after the ear deployment by the EAR service.
244: * @param earClassLoader the ClassLoader of the ear application to
245: * remove from the cache.
246: */
247: public void removeCache(ClassLoader earClassLoader) {
248:
249: if (catalinaService == null) {
250: catalinaService = getCatalinaServiceInstance();
251: }
252: // method invokation
253: Method m = (Method) methods.get("removeCache");
254: if (m == null) {
255: m = getMethod("removeCache",
256: new Class[] { ClassLoader.class });
257: }
258:
259: invoke(m, new Object[] { earClassLoader });
260:
261: }
262:
263: /**
264: * Register a WAR by delegating the operation to the registerWar()
265: * method. This is used for JMX management.
266: * @param fileName the name of the war to deploy.
267: * @throws RemoteException if rmi call failed.
268: * @throws JWebContainerServiceException if the registration failed.
269: */
270: public void registerWarMBean(String fileName)
271: throws RemoteException, JWebContainerServiceException {
272:
273: if (catalinaService == null) {
274: catalinaService = getCatalinaServiceInstance();
275: }
276: // method invokation
277: Method m = (Method) methods.get("registerWarMBean");
278: if (m == null) {
279: m = getMethod("registerWarMBean",
280: new Class[] { String.class });
281: }
282:
283: invoke(m, new Object[] { fileName });
284:
285: }
286:
287: /**
288: * Unregister a WAR by delegating the operation to the unRegisterWar()
289: * method. This is used for JMX management.
290: * @param fileName the name of the war to undeploy.
291: * @throws RemoteException if rmi call failed.
292: * @throws JWebContainerServiceException if the unregistration failed.
293: */
294: public void unRegisterWarMBean(String fileName)
295: throws RemoteException, JWebContainerServiceException {
296:
297: if (catalinaService == null) {
298: catalinaService = getCatalinaServiceInstance();
299: }
300: // method invokation
301: Method m = (Method) methods.get("unRegisterWarMBean");
302: if (m == null) {
303: m = getMethod("unRegisterWarMBean",
304: new Class[] { String.class });
305: }
306:
307: invoke(m, new Object[] { fileName });
308:
309: }
310:
311: /**
312: * Return the list of installed web applications.
313: * The WAR files or the directories with expanded web application are searched
314: * in JONAS_BASE/webapps and all webapps directories 'autoload'.
315: * @return The list of WAR files or the directories with expanded web application found
316: * @throws Exception if the list can't be retrieved
317: */
318: public List getInstalledWars() throws Exception {
319:
320: if (catalinaService == null) {
321: catalinaService = getCatalinaServiceInstance();
322: }
323: // method invokation
324: Method m = (Method) methods.get("getInstalledWars");
325: if (m == null) {
326: m = getMethod("getInstalledWars", new Class[] {});
327: }
328:
329: return (List) invoke(m, new Object[] {});
330:
331: }
332:
333: /**
334: * @return current number of wars deployed in the JOnAS server
335: */
336: public Integer getCurrentNumberOfWars() {
337:
338: if (catalinaService == null) {
339: catalinaService = getCatalinaServiceInstance();
340: }
341: // method invokation
342: Method m = (Method) methods.get("getCurrentNumberOfWars");
343: if (m == null) {
344: m = getMethod("getCurrentNumberOfWars", new Class[] {});
345: }
346:
347: return (Integer) invoke(m, new Object[] {});
348:
349: }
350:
351: /**
352: * This method is added temporarily. It will disapear when Wars will have their associated MBeans
353: * (when Wars will become manageable)
354: * @return the names of the wars currently deployed in the JOnAS server
355: */
356: public Set getWarNames() {
357:
358: if (catalinaService == null) {
359: catalinaService = getCatalinaServiceInstance();
360: }
361: // method invokation
362: Method m = (Method) methods.get("getWarNames");
363: if (m == null) {
364: m = getMethod("getWarNames", new Class[] {});
365: }
366:
367: return (Set) invoke(m, new Object[] {});
368:
369: }
370:
371: /**
372: * Test if the specified filename is already deployed or not
373: * @param fileName the name of the war file.
374: * @return true if the war is deployed, else false.
375: */
376: public boolean isWarLoaded(String fileName) {
377:
378: if (catalinaService == null) {
379: catalinaService = getCatalinaServiceInstance();
380: }
381: // method invokation
382: Method m = (Method) methods.get("isWarLoaded");
383: if (m == null) {
384: m = getMethod("isWarLoaded", new Class[] { String.class });
385: }
386:
387: return ((Boolean) invoke(m, new Object[] { fileName }))
388: .booleanValue();
389:
390: }
391:
392: /**
393: * Gets the name of the server which is the web container
394: * @return the name of the server which is the web container
395: */
396: public String getServerName() {
397:
398: if (catalinaService == null) {
399: catalinaService = getCatalinaServiceInstance();
400: }
401: // method invokation
402: Method m = (Method) methods.get("getServerName");
403: if (m == null) {
404: m = getMethod("getServerName", new Class[] {});
405: }
406:
407: return (String) invoke(m, new Object[] {});
408:
409: }
410:
411: /**
412: * Gets the version of the server which is the web container
413: * @return the version of the server which is the web container
414: */
415: public String getServerVersion() {
416:
417: if (catalinaService == null) {
418: catalinaService = getCatalinaServiceInstance();
419: }
420: // method invokation
421: Method m = (Method) methods.get("getServerVersion");
422: if (m == null) {
423: m = getMethod("getServerVersion", new Class[] {});
424: }
425:
426: return (String) invoke(m, new Object[] {});
427:
428: }
429:
430: /**
431: * Return the list of all loaded web applications.
432: *
433: * @return The list of deployed web applications
434: */
435: public List getDeployedWars() {
436:
437: if (catalinaService == null) {
438: catalinaService = getCatalinaServiceInstance();
439: }
440: // method invokation
441: Method m = (Method) methods.get("getDeployedWars");
442: if (m == null) {
443: m = getMethod("getDeployedWars", new Class[] {});
444: }
445:
446: return (List) invoke(m, new Object[] {});
447:
448: }
449:
450: /**
451: * Return the list of installed web applications ready to deploy.
452: *
453: * @return The list of deployable web applications
454: * @throws Exception if the list can't be retrieved
455: */
456: public List getDeployableWars() throws Exception {
457:
458: if (catalinaService == null) {
459: catalinaService = getCatalinaServiceInstance();
460: }
461: // method invokation
462: Method m = (Method) methods.get("getDeployableWars");
463: if (m == null) {
464: m = getMethod("getDeployableWars", new Class[] {});
465: }
466:
467: return (List) invoke(m, new Object[] {});
468:
469: }
470:
471: /**
472: * Return the list of "autoload" directories for web applications.
473: * @return The list of all "autoload" directories
474: */
475: public List getAutoloadDirectories() {
476:
477: if (catalinaService == null) {
478: catalinaService = getCatalinaServiceInstance();
479: }
480: // method invokation
481: Method m = (Method) methods.get("getAutoloadDirectories");
482: if (m == null) {
483: m = getMethod("getAutoloadDirectories", new Class[] {});
484: }
485:
486: return (List) invoke(m, new Object[] {});
487:
488: }
489:
490: /**
491: * Return the WebApps directory.
492: * @return The WebApps directory
493: */
494: public String getWebappsDirectory() {
495:
496: if (catalinaService == null) {
497: catalinaService = getCatalinaServiceInstance();
498: }
499: // method invokation
500: Method m = (Method) methods.get("getWebappsDirectory");
501: if (m == null) {
502: m = getMethod("getWebappsDirectory", new Class[] {});
503: }
504:
505: return (String) invoke(m, new Object[] {});
506:
507: }
508:
509: /**
510: * Initialize the Catalina service.
511: * @param ctx the configuration context of the service.
512: * @throws ServiceException if the initialization failed.
513: * @see org.objectweb.jonas.service.Service#init(javax.naming.Context)
514: */
515: public void init(Context ctx) throws ServiceException {
516:
517: if (catalinaService == null) {
518: catalinaService = getCatalinaServiceInstance();
519: }
520: // method invokation
521: Method m = (Method) methods.get("init");
522: if (m == null) {
523: m = getMethod("init", new Class[] { Context.class });
524: }
525:
526: invoke(m, new Object[] { ctx });
527:
528: }
529:
530: /**
531: * Start the Catalina service in a new thread
532: * @throws ServiceException if the startup failed.
533: * @see org.objectweb.jonas.service.Service#start()
534: */
535: public void start() throws ServiceException {
536:
537: if (catalinaService == null) {
538: catalinaService = getCatalinaServiceInstance();
539: }
540: // method invokation
541: Method m = (Method) methods.get("start");
542: if (m == null) {
543: m = getMethod("start", new Class[] {});
544: }
545:
546: invoke(m, new Object[] {});
547: }
548:
549: /**
550: * Stop the Catalina service.
551: * @throws ServiceException if the stop failed.
552: * @see org.objectweb.jonas.service.Service#stop()
553: */
554: public void stop() throws ServiceException {
555:
556: if (catalinaService == null) {
557: catalinaService = getCatalinaServiceInstance();
558: }
559: // method invokation
560: Method m = (Method) methods.get("stop");
561: if (m == null) {
562: m = getMethod("stop", new Class[] {});
563: }
564:
565: invoke(m, new Object[] {});
566:
567: }
568:
569: /**
570: * @return true if the service is started, false otherwise
571: */
572: public boolean isStarted() {
573:
574: if (catalinaService == null) {
575: catalinaService = getCatalinaServiceInstance();
576: }
577: // method invokation
578: Method m = (Method) methods.get("isStarted");
579: if (m == null) {
580: m = getMethod("isStarted", new Class[] {});
581: }
582:
583: return ((Boolean) invoke(m, new Object[] {})).booleanValue();
584:
585: }
586:
587: /**
588: * Set the service's name
589: * @param name to set
590: */
591: public void setName(String name) {
592:
593: if (catalinaService == null) {
594: catalinaService = getCatalinaServiceInstance();
595: }
596: // method invokation
597: Method m = (Method) methods.get("setName");
598: if (m == null) {
599: m = getMethod("setName", new Class[] { String.class });
600: }
601:
602: invoke(m, new Object[] { name });
603:
604: }
605:
606: /**
607: * @return the service's name
608: */
609: public String getName() {
610:
611: if (catalinaService == null) {
612: catalinaService = getCatalinaServiceInstance();
613: }
614: // method invokation
615: Method m = (Method) methods.get("getName");
616: if (m == null) {
617: m = getMethod("getName", new Class[] {});
618: }
619:
620: return (String) invoke(m, new Object[] {});
621:
622: }
623:
624: /**
625: * Return the Default host name of the web container.
626: * @return the Default host name of the web container.
627: * @throws JWebContainerServiceException when it is impossible to get the Default Host.
628: */
629: public String getDefaultHost() throws JWebContainerServiceException {
630:
631: if (catalinaService == null) {
632: catalinaService = getCatalinaServiceInstance();
633: }
634: // method invokation
635: Method m = (Method) methods.get("getDefaultHost");
636: if (m == null) {
637: m = getMethod("getDefaultHost", new Class[] {});
638: }
639:
640: return (String) invoke(m, new Object[] {});
641:
642: }
643:
644: /**
645: * Return the Default HTTP port number of the web container (can
646: * be null if multiple HTTP connector has been set).
647: * @return the Default HTTP port number of the web container.
648: * @throws JWebContainerServiceException when it is impossible to get the Default Http port.
649: */
650: public String getDefaultHttpPort()
651: throws JWebContainerServiceException {
652:
653: if (catalinaService == null) {
654: catalinaService = getCatalinaServiceInstance();
655: }
656: // method invokation
657: Method m = (Method) methods.get("getDefaultHttpPort");
658: if (m == null) {
659: m = getMethod("getDefaultHttpPort", new Class[] {});
660: }
661:
662: return (String) invoke(m, new Object[] {});
663:
664: }
665:
666: /**
667: * Return the Default HTTPS port number of the web container (can
668: * be null if multiple HTTPS connector has been set).
669: * @return the Default HTTPS port number of the web container.
670: * @throws JWebContainerServiceException when it is impossible to get the Default Https port.
671: */
672: public String getDefaultHttpsPort()
673: throws JWebContainerServiceException {
674:
675: if (catalinaService == null) {
676: catalinaService = getCatalinaServiceInstance();
677: }
678: // method invokation
679: Method m = (Method) methods.get("getDefaultHttpsPort");
680: if (m == null) {
681: m = getMethod("getDefaultHttpsPort", new Class[] {});
682: }
683:
684: return (String) invoke(m, new Object[] {});
685:
686: }
687:
688: /**
689: * Return the class loader of the given warURL. Unpack the associated war
690: * and build the loader if it's not in the cache.
691: * @param warURL the url of the war we want to get the loader
692: * @param earAppName the name of the ear application containing
693: * the war. May be null in non ear case.
694: * @param parentLoader the ejb class loader of the ear.
695: * May be null in non ear case.
696: * @return the class loader of the given warURL.
697: * @throws JWebContainerServiceException if the process failed.
698: */
699: public URLClassLoader getClassLoader(URL warURL, String earAppName,
700: ClassLoader parentLoader)
701: throws JWebContainerServiceException {
702:
703: if (catalinaService == null) {
704: catalinaService = getCatalinaServiceInstance();
705: }
706: // method invokation
707: Method m = (Method) methods.get("getClassLoader");
708: if (m == null) {
709: m = getMethod("getClassLoader", new Class[] { URL.class,
710: String.class, ClassLoader.class });
711: }
712:
713: return (URLClassLoader) invoke(m, new Object[] { warURL,
714: earAppName, parentLoader });
715:
716: }
717:
718: /**
719: * The server is started ?
720: * @return boolean true if the catalina container is running.
721: */
722: public boolean isTomcatStarted() {
723:
724: if (catalinaService == null) {
725: catalinaService = getCatalinaServiceInstance();
726: }
727: // method invokation
728: Method m = (Method) methods.get("isTomcatStarted");
729: if (m == null) {
730: m = getMethod("isTomcatStarted", new Class[] {});
731: }
732:
733: return ((Boolean) invoke(m, new Object[] {})).booleanValue();
734:
735: }
736:
737: /**
738: * @param url the URL of the webapp
739: * @return Returns the ClassLoader used to link a JNDI environnment to a webapp
740: */
741: public ClassLoader getContextLinkedClassLoader(URL url) {
742:
743: if (catalinaService == null) {
744: catalinaService = getCatalinaServiceInstance();
745: }
746: // method invokation
747: Method m = (Method) methods.get("getContextLinkedClassLoader");
748: if (m == null) {
749: m = getMethod("getContextLinkedClassLoader",
750: new Class[] { URL.class });
751: }
752:
753: return (ClassLoader) invoke(m, new Object[] { url });
754:
755: }
756:
757: }
|