001: package com.tagtraum.bootstrap;
002:
003: import java.io.File;
004: import java.io.FilenameFilter;
005: import java.lang.reflect.InvocationTargetException;
006: import java.lang.reflect.Method;
007: import java.net.MalformedURLException;
008: import java.net.URL;
009: import java.net.URLClassLoader;
010: import java.util.*;
011:
012: /**
013: * Bootstrap class that initializes a number of named classloaders, uses one to load a particular
014: * class and invokes the main method of that class.
015: *
016: * @author <a href="mailto:hs@tagtraum.com">Hendrik Schreiber</a>
017: * @version 1.1beta1 $Id: Bootstrap.java,v 1.5 2005/03/15 15:55:25 hendriks73 Exp $
018: */
019: public class Bootstrap {
020:
021: private static ResourceBundle localStrings = ResourceBundle
022: .getBundle("com.tagtraum.bootstrap.localStrings");
023: private static String pathSeparator = System
024: .getProperty("path.separator");
025: private static String fileSeparator = System
026: .getProperty("file.separator");
027: private static char fileSeparatorChar = fileSeparator.charAt(0);
028:
029: private static Bootstrap instance;
030:
031: private Map classLoaderMap;
032: private String[] args;
033: private Class mainClass;
034: private String mainClassName;
035: private String mainClassLoaderName;
036:
037: private Bootstrap(String[] args) throws MalformedURLException,
038: ClassNotFoundException, NoSuchMethodException,
039: IllegalAccessException, InvocationTargetException {
040: classLoaderMap = new HashMap();
041: int i = 0;
042: if ((!args[i].startsWith("cl."))) {
043: throw new IllegalArgumentException(localStrings
044: .getString("expected_cl")
045: + " " + args[i]);
046: }
047: for (; i < args.length && args[i].startsWith("cl."); i++) {
048: parseClassLoader(args[i]);
049: }
050: if (i >= args.length || (!args[i].startsWith("main."))) {
051: throw new IllegalArgumentException(localStrings
052: .getString("expected_main")
053: + " " + args[i]);
054: } else {
055: parseMainClass(args[i]);
056: }
057: i++;
058: this .args = new String[args.length - i];
059: for (int idx = 0; i < args.length; i++) {
060: this .args[idx++] = args[i];
061: }
062: ClassLoader classLoader = getClassLoader(mainClassLoaderName);
063: mainClass = classLoader.loadClass(mainClassName);
064: invokeMainMethod();
065: }
066:
067: private void parseClassLoader(String parameter)
068: throws MalformedURLException {
069: int equals = parameter.indexOf('=');
070: if (equals == -1)
071: throw new IllegalArgumentException(localStrings
072: .getString("parameter_must_contain_equalsign")
073: + " " + parameter);
074: String key = parameter.substring(0, equals);
075: String value = "";
076: if (equals < parameter.length() - 1)
077: value = parameter.substring(equals + 1);
078: String name = getName(key, "cl.".length());
079: URL[] urls = parseClasspath(value);
080: registerClassLoader(name, new URLClassLoader(urls));
081: }
082:
083: private void parseMainClass(String parameter) {
084: int equals = parameter.indexOf('=');
085: if (equals == -1)
086: throw new IllegalArgumentException(localStrings
087: .getString("parameter_must_contain_equalsign")
088: + " " + parameter);
089: String key = parameter.substring(0, equals);
090: String value = "";
091: if (equals < parameter.length() - 1)
092: value = parameter.substring(equals + 1);
093: String name = getName(key, "main.".length());
094: this .mainClassName = value;
095: this .mainClassLoaderName = name;
096: }
097:
098: private URL[] parseClasspath(String classpath)
099: throws MalformedURLException {
100: StringTokenizer st = new StringTokenizer(classpath,
101: pathSeparator);
102: List urlList = new ArrayList();
103: while (st.hasMoreTokens()) {
104: String token = st.nextToken();
105: token = token.replace('/', fileSeparatorChar);
106: token = token.replace('\\', fileSeparatorChar);
107: File[] file = resolveClasspathToken(token);
108: for (int i = 0; i < file.length; i++) {
109: urlList.add(file[i].toURL());
110: }
111: }
112: return (URL[]) urlList.toArray(new URL[urlList.size()]);
113: }
114:
115: /**
116: * This is pattern matching for 'poor' people. You may use exactly one <code>*</code>.
117: * TODO: use reg expr., once we support only JDK 1.4 or greater
118: *
119: * @param token
120: * @return array of matching files or a matching directory
121: */
122: private File[] resolveClasspathToken(String token) {
123: File[] files = null;
124: int star = token.indexOf('*');
125: if (star == -1) {
126: File file = new File(token).getAbsoluteFile();
127: if (file.isDirectory())
128: file = new File(file.toString() + fileSeparator);
129: files = new File[1];
130: files[0] = file;
131: } else {
132: File starParent = new File(token.substring(0, star))
133: .getAbsoluteFile();
134: if (!starParent.isDirectory())
135: starParent = starParent.getParentFile();
136: int slash = token.lastIndexOf(fileSeparatorChar) + 1;
137: slash = star < slash || slash == -1 ? 0 : slash;
138: files = starParent
139: .listFiles(new StarFileFilter(token.substring(
140: slash, star), token.substring(star + 1)));
141: }
142: return files;
143: }
144:
145: private void invokeMainMethod() throws NoSuchMethodException,
146: IllegalAccessException, InvocationTargetException {
147: Method mainMethod = mainClass.getMethod("main",
148: new Class[] { String[].class });
149: mainMethod.invoke(null, new Object[] { args });
150: }
151:
152: private String getName(String key, int startIndex) {
153: return key.substring(startIndex);
154: }
155:
156: public Class getMainClass() {
157: return mainClass;
158: }
159:
160: public String[] getArgs() {
161: return args;
162: }
163:
164: public void registerClassLoader(String name, ClassLoader classLoader) {
165: classLoaderMap.put(name, classLoader);
166: }
167:
168: public ClassLoader getClassLoader(String name) {
169: return (ClassLoader) classLoaderMap.get(name);
170: }
171:
172: public synchronized static Bootstrap getInstance() {
173: return instance;
174: }
175:
176: /**
177: * @param args cl.>name<=>classpath< main.>name<=>main class< args
178: */
179: public synchronized static void main(String[] args)
180: throws MalformedURLException, ClassNotFoundException,
181: NoSuchMethodException, IllegalAccessException,
182: InvocationTargetException {
183: try {
184: instance = new Bootstrap(args);
185: } catch (IllegalArgumentException e) {
186: usage();
187: throw e;
188: }
189: }
190:
191: private static void usage() {
192: System.out.println();
193: System.out
194: .println("Bootstrap - © 2002-2005 by tagtraum industries - http://www.tagtraum.com/");
195: System.out.println();
196: System.out.println("Usage:");
197: System.out
198: .println("\tjava -cp bootstrap.jar com.tagtraum.bootstrap.Bootstrap cl.<name>=<classpath> [cl.<name>=<classpath>]* main.name=<main class> [arg]*");
199: System.out.println();
200: }
201:
202: private static class StarFileFilter implements FilenameFilter {
203: private String start;
204: private String end;
205:
206: public StarFileFilter(String start, String end) {
207: this .start = start;
208: this .end = end;
209: }
210:
211: public boolean accept(File dir, String name) {
212: return name.startsWith(start) && name.endsWith(end)
213: && new File(dir, name).isFile();
214: }
215: }
216:
217: }
|