001: /**
002: * JOnAS: Java(TM) Open Application Server
003: * Copyright (C) 1999-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: LoaderManager.java 7549 2005-10-20 17:06:30Z benoitf $
023: * --------------------------------------------------------------------------
024: */package org.objectweb.jonas.server;
025:
026: import java.io.File;
027: import java.util.Hashtable;
028: import java.util.Map;
029: import java.util.StringTokenizer;
030:
031: import org.objectweb.jonas.common.JProp;
032:
033: /**
034: * This class create all the ClassLoader necessary for JOnAS.
035: *
036: * <code>
037: * system ($CLASSPATH)
038: * |
039: * commons
040: * /\
041: * / \
042: * / \
043: * apps tools
044: * \
045: * catalina
046: * </code>
047: *
048: * @author Guillaume Sauthier (initial developer)
049: */
050: public class LoaderManager {
051:
052: /**
053: * Singleton instance of LoaderManager
054: */
055: private static LoaderManager instance = null;
056:
057: /**
058: * ClassLoader name for Commons libs
059: */
060: private static final String COMMONS = "loader.commons";
061:
062: /**
063: * ClassLoader name for Tools libs
064: */
065: private static final String TOOLS = "loader.tools";
066:
067: /**
068: * ClassLoader name for Applications
069: */
070: private static final String APPS = "loader.apps";
071:
072: /**
073: * ClassLoader name for Catalina
074: */
075: private static final String CATALINA = "loader.catalina";
076:
077: /**
078: * Catalina Bootstrap.jar (used to know if we're using external revision of Tomcat)
079: */
080: private static final String CATALINA_BOOTSTRAP_JAR = "bin"
081: + File.separator + "bootstrap.jar";
082:
083: /**
084: * Jetty org.mortbay.jetty.jar (used to know if we're using external revision of Jetty)
085: */
086: private static final String MORTBAY_JETTY_JAR = "lib"
087: + File.separator + "org.mortbay.jetty.jar";
088:
089: /**
090: * JProp instance
091: */
092: private JProp jp = null;
093:
094: /**
095: * ClassLoaders
096: */
097: private Map loaders = null;
098:
099: /**
100: * $JONAS_ROOT/lib
101: */
102: private static File jonasLib = null;
103:
104: /**
105: * $JONAS_ROOT/lib/catalina
106: */
107: private static File catalinaLib = null;
108:
109: /**
110: * $JONAS_ROOT/lib/jetty
111: */
112: private static File jettyLib = null;
113:
114: /**
115: * $JONAS_BASE
116: */
117: private static String jonasBase = null;
118:
119: /**
120: * $CATALINA_HOME
121: */
122: private static String catalinaHome = null;
123:
124: /**
125: * $JETTY_HOME
126: */
127: private static String jettyHome = null;
128:
129: /**
130: * true if JOnAS is launched with web container
131: */
132: private boolean hasWeb = false;
133:
134: /**
135: * Use the default Classpath ?
136: */
137: private boolean useDefaultClassPath = false;
138:
139: /**
140: * is the web container provided by Catalina
141: */
142: private boolean isCatalina = false;
143:
144: /**
145: * ${jonas.root}/lib/commons
146: */
147: private File jonasCommonsDir;
148:
149: /**
150: * ${jonas.root}/lib/tools
151: */
152: private File jonasToolsDir;
153:
154: /**
155: * ${jonas.root}/lib/apps
156: */
157: private File jonasAppsDir;
158:
159: /**
160: * Create a LoaderManager instance
161: */
162: private LoaderManager() {
163: // Get the $JONAS_ROOT/lib directories
164: String jonasRoot = System.getProperty("install.root");
165: if (jonasRoot == null) {
166: System.err.println("JONAS_ROOT is not set");
167: System.exit(2);
168: }
169:
170: jonasLib = new File(jonasRoot, "lib");
171: jonasCommonsDir = new File(jonasLib, "commons");
172: jonasToolsDir = new File(jonasLib, "tools");
173: jonasAppsDir = new File(jonasLib, "apps");
174: catalinaLib = new File(jonasLib, "catalina");
175: jettyLib = new File(jonasLib, "jetty");
176:
177: // Init loaders map
178: loaders = new Hashtable();
179: }
180:
181: /**
182: * @return Returns the unique instance of LoaderManager.
183: */
184: public static LoaderManager getInstance() {
185: if (instance == null) {
186: instance = new LoaderManager();
187: }
188: return instance;
189: }
190:
191: /**
192: * Initialize the LoaderManager with a JProp instance.
193: *
194: * @param props JProp used to configure JOnAS
195: */
196: public void init(JProp props) {
197: jp = props;
198: // Get $JONAS_BASE
199: jonasBase = JProp.getJonasBase();
200:
201: useDefaultClassPath = jp.getValueAsBoolean(
202: "jonas.default.classloader", false);
203:
204: // find web services
205: String[] services = props.getValueAsArray("jonas.services");
206: if (services != null) {
207: for (int i = 0; i < services.length; i++) {
208: if (services[i].equals("web")) {
209: hasWeb = true;
210: String classname = props
211: .getValue("jonas.service.web.class");
212: if (classname.matches(".*Catalina.*")) {
213: isCatalina = true;
214: }
215: }
216: }
217: }
218:
219: catalinaHome = System.getProperty("catalina.home");
220: jettyHome = System.getProperty("jetty.home");
221:
222: // Set in all case catalina.home and base to $JONAS_BASE
223: // if library is found. Useful if a user want to run in
224: // a same environment JOnAS/Tomcat and Tomcat with different
225: // versions
226: if (hasEmbeddedCatalina()) {
227: System.setProperty("catalina.home", catalinaLib.getPath());
228: System.setProperty("catalina.base", jonasBase);
229: catalinaHome = catalinaLib.getPath();
230: }
231:
232: // Set jetty.home to $JONAS_BASE if library is found
233: // and if jetty.home isn't set.
234: if (jettyHome == null) {
235: if (hasEmbeddedJetty()) {
236: System.setProperty("jetty.home", jettyLib.getPath());
237: jettyHome = jettyLib.getPath();
238: }
239: }
240:
241: }
242:
243: /**
244: * @return Returns true if using embedded catalina classes.
245: */
246: private boolean hasEmbeddedCatalina() {
247: return new File(catalinaLib, CATALINA_BOOTSTRAP_JAR).exists();
248: }
249:
250: /**
251: * @return Returns true if using embedded jetty classes.
252: */
253: private boolean hasEmbeddedJetty() {
254: return new File(jettyLib, MORTBAY_JETTY_JAR).exists();
255: }
256:
257: /**
258: * @return Returns the Commons ClassLoader
259: * @throws Exception When ClassLoader cannot be created.
260: */
261: public JClassLoader getCommonsLoader() throws Exception {
262: JClassLoader commons = getLoader(COMMONS);
263: if (commons == null) {
264: commons = createCommonsClassLoader();
265: setLoader(COMMONS, commons);
266: }
267: return commons;
268: }
269:
270: /**
271: * @return returns the Tools ClassLoader
272: * @throws Exception When ClassLoader cannot be created
273: */
274: public JClassLoader getToolsLoader() throws Exception {
275: JClassLoader tools = getLoader(TOOLS);
276: if (tools == null) {
277: tools = createToolsClassLoader();
278: setLoader(TOOLS, tools);
279: }
280: return tools;
281: }
282:
283: /**
284: * @return Returns the Application ClassLoader
285: * @throws Exception When ClassLoader cannot be created
286: */
287: public JClassLoader getAppsLoader() throws Exception {
288: JClassLoader apps = getLoader(APPS);
289: if (apps == null) {
290: apps = createAppsClassLoader();
291: setLoader(APPS, apps);
292: }
293: return apps;
294: }
295:
296: /**
297: * @return Returns the Catalina ClassLoader
298: * @throws Exception When ClassLoader cannot be created.
299: */
300: public JClassLoader getCatalinaLoader() throws Exception {
301: JClassLoader catalina = getLoader(CATALINA);
302: if (catalina == null) {
303: catalina = createCatalinaClassLoader();
304: setLoader(CATALINA, catalina);
305: }
306: return catalina;
307: }
308:
309: /**
310: * Return an array containing all the resources declared in the classpath
311: * environment variable.
312: *
313: * @param xtracp XTRA classpath
314: *
315: * @return a list containing all the resources declared in the classpath
316: * environment variable.
317: *
318: * @throws Exception if a resource cannot be found.
319: */
320: private static JURLs getClassPath(boolean xtracp) throws Exception {
321: String cpprop = "java.class.path";
322: if (xtracp) {
323: cpprop = "jonas.classpath";
324: }
325: String cpValue = System.getProperty(cpprop);
326: //System.out.println("classpath=" + cpValue); // DEBUG
327: String sep = File.pathSeparator;
328: JURLs jurls = new JURLs();
329: StringTokenizer tokenizer = new StringTokenizer(cpValue, sep);
330: while (tokenizer.hasMoreTokens()) {
331: File file = new File(tokenizer.nextToken());
332: if (file.isDirectory()) {
333: jurls.addDir(file);
334: } else {
335: // TODO check for ${jonas.root}/lib/bootstrap
336: // do not re-add bootstrap.jar inside classloader
337: if (!file.getName().equals("ow_jonas_bootstrap.jar")) {
338: jurls.add(file);
339: }
340: }
341: }
342: return jurls;
343: }
344:
345: /**
346: * Returns a JClassLoader.
347: *
348: * @param name name of the loader
349: *
350: * @return Returns the JClassLoader
351: */
352: private JClassLoader getLoader(String name) {
353: return (JClassLoader) loaders.get(name);
354: }
355:
356: /**
357: * Add a couple (name, ClassLoader).
358: *
359: * @param name ClassLoader name
360: * @param loader the ClassLoader
361: */
362: private void setLoader(String name, JClassLoader loader) {
363: loaders.put(name, loader);
364: }
365:
366: /**
367: * Constructs the Commons ClassLoader.
368: *
369: * @return Returns the Commons ClassLoader.
370: * @throws Exception When ClassLoader cannot be created from CLASSPATH or resources cannot be added to URLs List.
371: */
372: private JClassLoader createCommonsClassLoader() throws Exception {
373:
374: JURLs jurls = new JURLs();
375:
376: // add classpath in loader
377: jurls.merge(getClassPath(useDefaultClassPath));
378:
379: // Load $JONAS_ROOT/lib/commons/**/*.jar
380: jurls.add(jonasCommonsDir, ".jar");
381:
382: // Load $JONAS_BASE/lib/commons
383: File jonasBaseLibCommons = new File(jonasBase, "lib"
384: + File.separator + "commons");
385: if (jonasBaseLibCommons.exists()) {
386: jurls.add(jonasBaseLibCommons, ".jar");
387: }
388:
389: // add jonas.base/lib/ext only if jonas.base != jonas.root
390: // jonas.base/lib/ext is added before jonas.root/lib/ext
391: if (!System.getProperty("install.root").toLowerCase().equals(
392: jonasBase.toLowerCase())) {
393: File jonasBaseLibExt = new File(jonasBase + File.separator
394: + "lib" + File.separator + "ext");
395: if (jonasBaseLibExt.exists()) {
396: jurls.add(jonasBaseLibExt, ".jar");
397: }
398: }
399:
400: // add jonas.root/lib/ext
401: jurls.add(new File(jonasLib, "ext"), ".jar");
402:
403: if (hasWeb) {
404: // resources for catalina have been put in apps ClassLoader
405:
406: // add resources for jetty if required
407: if (jettyHome != null && !isCatalina) {
408: File jettyLibDir = new File(jettyHome, "lib");
409: File jettyExtDir = new File(jettyHome, "ext");
410: File jettyExtraDir = new File(new File(jettyHome,
411: "extra"), "lib");
412: jurls.add(jettyLibDir, ".jar");
413: jurls.add(jettyExtDir, ".jar");
414: jurls.add(jettyExtraDir, "jsr77.jar");
415: if (!hasEmbeddedJetty()) {
416: // load ${jonas.root}/jetty/lib/ow_jonas_jetty.jar
417: File jonasJetty5Glue = new File(new File(jettyLib,
418: "lib"), "ow_jonas_jetty.jar");
419: jurls.add(jonasJetty5Glue);
420: }
421: }
422: // else user has not set the webcontainer HOME var
423: }
424:
425: return new JClassLoader("Commons", jurls.toURLs());
426: }
427:
428: /**
429: * Constructs the Tools ClassLoader using Commons ClassLoader as parent.
430: *
431: * @return Returns the Tools ClassLoader
432: *
433: * @throws Exception When resources cannot be added to URL list.
434: */
435: private JClassLoader createToolsClassLoader() throws Exception {
436: JURLs jurls = new JURLs();
437:
438: jurls.add(jonasToolsDir, ".jar");
439:
440: // Load $JONAS_BASE/lib/toolds
441: File jonasBaseLibTools = new File(jonasBase, "lib"
442: + File.separator + "tools");
443: if (jonasBaseLibTools.exists()) {
444: jurls.add(jonasBaseLibTools, ".jar");
445: }
446:
447: return new JClassLoader("Tools", jurls.toURLs(),
448: getCommonsLoader());
449: }
450:
451: /**
452: * Constructs the Application ClassLoader with Commons ClassLoader as parent.
453: * At this time, this is an empty ClassLoader
454: *
455: * @return the Application ClassLoader
456: *
457: * @throws Exception When resources cannot be added to URL list.
458: */
459: private JClassLoader createAppsClassLoader() throws Exception {
460: JURLs jurls = new JURLs();
461:
462: // ${jonas.root}/lib/apps
463: jurls.add(jonasAppsDir, ".jar");
464:
465: // Load $JONAS_BASE/lib/apps
466: File jonasBaseLibApps = new File(jonasBase, "lib"
467: + File.separator + "apps");
468: if (jonasBaseLibApps.exists()) {
469: jurls.add(jonasBaseLibApps, ".jar");
470: }
471:
472: if (hasWeb) {
473: // add resources for catalina if required
474: if (catalinaHome != null && isCatalina) {
475: File catalinaBinDir = new File(catalinaHome, "bin");
476: File catalinaCommonLibDir = new File(catalinaHome,
477: "common" + File.separator + "lib");
478: File catalinaSharedLibDir = new File(catalinaHome,
479: "shared" + File.separator + "lib");
480: jurls.add(new File(catalinaBinDir, "bootstrap.jar"));
481: jurls.add(catalinaCommonLibDir, ".jar");
482: jurls.add(catalinaSharedLibDir, ".jar");
483: }
484: }
485: return new JClassLoader("Apps", jurls.toURLs(),
486: getCommonsLoader());
487: }
488:
489: /**
490: * Constructs the Catalina ClassLoader with Applications ClassLoader as parent.
491: *
492: * @return the Catalina ClassLoader
493: *
494: * @throws Exception When resources cannot be added to URL list.
495: */
496: private JClassLoader createCatalinaClassLoader() throws Exception {
497: JURLs jurls = new JURLs();
498:
499: // ${jonas.root}/catalina/server/lib/ow_jonas_tomcat5.jar
500: if (!hasEmbeddedCatalina()) {
501: // add ow_jonas_tomcat.jar only if using external Tomcat
502: File jonasTomcat5Glue = new File(catalinaLib, "server"
503: + File.separator + "lib" + File.separator
504: + "ow_jonas_tomcat5.jar");
505: File jonasTomcat55Glue = new File(catalinaLib, "server"
506: + File.separator + "lib" + File.separator
507: + "ow_jonas_tomcat55.jar");
508: if (jonasTomcat5Glue.exists()) {
509: jurls.add(jonasTomcat5Glue);
510: } else if (jonasTomcat55Glue.exists()) {
511: jurls.add(jonasTomcat55Glue);
512: } else {
513: System.out
514: .println("WARN : No ow_jonas_tomcat5.jar found in "
515: + catalinaLib
516: + "/server/lib directory.");
517: }
518: }
519:
520: // ${catalina.home}/server/lib/*jar
521: File catalinaServerLibDir = new File(catalinaHome, "server"
522: + File.separator + "lib");
523: jurls.add(catalinaServerLibDir, ".jar");
524:
525: return new JClassLoader("Catalina", jurls.toURLs(),
526: getAppsLoader());
527: }
528: }
|