1 package org.codehaus.classworlds;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49 import java.io.FileInputStream;
50 import java.io.InputStream;
51 import java.lang.reflect.InvocationTargetException;
52 import java.lang.reflect.Method;
53 import java.lang.reflect.Modifier;
54
55 /***
56 * Command-line invokable application launcher.
57 * <p/>
58 * <p/>
59 * This launcher class assists in the creation of classloaders and <code>ClassRealm</code>s
60 * from a configuration file and the launching of the application's <code>main</code>
61 * method from the correct class loaded through the correct classloader.
62 * </p>
63 * <p/>
64 * <p/>
65 * The path to the configuration file is specified using the <code>classworlds.conf</code>
66 * system property, typically specified using the <code>-D</code> switch to
67 * <code>java</code>.
68 * </p>
69 *
70 * @author <a href="mailto:bob@eng.werken.com">bob mcwhirter</a>
71 * @version $Id: EmbeddedLauncher.java,v 1.1.1.1 2004/07/01 13:59:19 jvanzyl Exp $
72 */
73 public class EmbeddedLauncher
74 extends Launcher
75 {
76 private static String LAUNCH_METHOD = "execute";
77
78 public EmbeddedLauncher()
79 {
80 super();
81 }
82
83
84
85
86
87 /***
88 * Set the application's main entrypoint.
89 *
90 * @param mainClassName The main class name.
91 * @param mainRealmName The realm to load the class from.
92 */
93 public void setAppMain( String mainClassName,
94 String mainRealmName )
95 {
96 this.mainClassName = mainClassName;
97 this.mainRealmName = mainRealmName;
98 }
99
100 /***
101 * Retrieve the main entry realm name.
102 *
103 * @return The main entry realm name.
104 */
105 public String getMainRealmName()
106 {
107 return this.mainRealmName;
108 }
109
110 /***
111 * Retrieve the main entry class name.
112 *
113 * @return The main entry class name.
114 */
115 public String getMainClassName()
116 {
117 return this.mainClassName;
118 }
119
120 /***
121 * Retrieve the main entry class.
122 *
123 * @return The main entry class.
124 * @throws ClassNotFoundException If the class cannot be found.
125 * @throws NoSuchRealmException If the specified main entry realm does not exist.
126 */
127 public Class getMainClass()
128 throws ClassNotFoundException, NoSuchRealmException
129 {
130 return getMainRealm().loadClass( getMainClassName() );
131 }
132
133 /***
134 * Retrieve the main entry realm.
135 *
136 * @return The main entry realm.
137 * @throws NoSuchRealmException If the specified main entry realm does not exist.
138 */
139 public ClassRealm getMainRealm()
140 throws NoSuchRealmException
141 {
142 return getWorld().getRealm( getMainRealmName() );
143 }
144
145 /***
146 * Retrieve the enhanced main entry method.
147 *
148 * @return The enhanced main entry method.
149 * @throws ClassNotFoundException If the main entry class cannot be found.
150 * @throws NoSuchMethodException If the main entry method cannot be found.
151 * @throws NoSuchRealmException If the main entry realm cannot be found.
152 */
153 protected Method getEnhancedMainMethod()
154 throws ClassNotFoundException, NoSuchMethodException, NoSuchRealmException
155 {
156 Method[] methods = getMainClass().getMethods();
157
158 for ( int i = 0; i < methods.length; ++i )
159 {
160 final Method method = methods[i];
161
162 if ( !LAUNCH_METHOD.equals( method.getName() ) )
163 {
164 continue;
165 }
166
167 int modifiers = method.getModifiers();
168
169 if ( !( Modifier.isPublic( modifiers ) ) )
170 {
171 continue;
172 }
173
174 if ( method.getReturnType() != Void.TYPE )
175 {
176 continue;
177 }
178
179 Class[] paramTypes = method.getParameterTypes();
180
181 if ( paramTypes.length != 2 )
182 {
183 continue;
184 }
185
186 if ( paramTypes[0] != String[].class )
187 {
188 continue;
189 }
190
191 if ( paramTypes[1] != ClassWorld.class )
192 {
193 continue;
194 }
195
196 return method;
197 }
198
199 throw new NoSuchMethodException( "public void execute(ClassWorld world)" );
200 }
201
202 /***
203 * Attempt to launch the application through the enhanced main method.
204 * <p/>
205 * <p/>
206 * This will seek a method with the exact signature of:
207 * </p>
208 * <p/>
209 * <pre>
210 * public static void main(String[] args, ClassWorld world)
211 * </pre>
212 *
213 * @throws ClassNotFoundException If the main entry class cannot be found.
214 * @throws IllegalAccessException If the method cannot be accessed.
215 * @throws java.lang.reflect.InvocationTargetException
216 * If the target of the invokation is
217 * invalid.
218 * @throws NoSuchMethodException If the main entry method cannot be found.
219 * @throws NoSuchRealmException If the main entry realm cannot be found.
220 */
221 protected void launchX()
222 throws ClassNotFoundException, IllegalAccessException,
223 InvocationTargetException, NoSuchMethodException, NoSuchRealmException
224 {
225 ClassRealm mainRealm = getMainRealm();
226 Class mainClass = getMainClass();
227 Method mainMethod = getEnhancedMainMethod();
228
229 Thread.currentThread().setContextClassLoader( mainRealm.getClassLoader() );
230
231 mainMethod.invoke( mainClass, new Object[]{getWorld()} );
232 }
233
234
235
236
237
238 public void launch()
239 throws Exception
240 {
241 String classworldsConf = System.getProperty( CLASSWORLDS_CONF );
242
243 InputStream is = null;
244
245 if ( classworldsConf != null )
246 {
247 is = new FileInputStream( classworldsConf );
248 }
249 else
250 {
251 ClassLoader cl = Thread.currentThread().getContextClassLoader();
252
253 if ( "true".equals( System.getProperty( "classworlds.bootstrapped" ) ) )
254 {
255 is = cl.getResourceAsStream( UBERJAR_CONF_DIR + CLASSWORLDS_CONF );
256 }
257 else
258 {
259 is = cl.getResourceAsStream( CLASSWORLDS_CONF );
260 }
261 }
262
263 if ( is == null )
264 {
265 throw new Exception( "classworlds configuration not specified nor found "
266 + "in the classpath" );
267 }
268
269 configure( is );
270
271 try
272 {
273 launchX();
274 }
275 catch ( InvocationTargetException e )
276 {
277
278 Throwable t = e.getTargetException();
279 if ( t instanceof Exception )
280 {
281 throw (Exception) t;
282 }
283 if ( t instanceof Error )
284 {
285 throw (Error) t;
286 }
287
288
289 throw e;
290 }
291 }
292 }