package com.redhat.ceylon.launcher;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
/**
* This is the earliest bootstrap class for the Ceylon tool chain.
* It does nothing more than trying to locate the system repository
* and load an appropriate ceylon.bootstrap module.
* Appropriate in this case means it will try to find the version this
* class was compiled with (see <code>Versions.CEYLON_VERSION_NUMBER</code>)
* or the version specified by the <code>CEYLON_VERSION</code> environment
* variable.
* After it locates the module it will pass the execution on to the
* <code>Launcher.main()</code> it contains.
*
* IMPORTANT This class should contain as little logic as possible and
* delegate as soon as it can to the <code>Launcher</code> in the
* ceylon.bootstrap module. This way we can maintain backward and forward
* compatibility as much as possible.
*
* @author Tako Schotanus
*/
public class Bootstrap {
public static void main(String[] args) throws Throwable {
// we don't need to clean up the class loader when run from main because the JVM will either exit, or
// keep running with daemon threads in which case it will keep needing this classloader open
int exit = run(args);
// WARNING: NEVER CALL EXIT IF WE STILL HAVE DAEMON THREADS RUNNING AND WE'VE NO REASON TO EXIT WITH A NON-ZERO CODE
if (exit != 0) {
System.exit(exit);
}
}
public static int run(String... args) throws Throwable {
CeylonClassLoader cl = null;
try {
Integer result = -1;
Method runMethod = null;
try {
String ceylonVersion = LauncherUtil.determineSystemVersion();
File module = CeylonClassLoader.getRepoJar("ceylon.bootstrap", ceylonVersion);
cl = CeylonClassLoader.newInstance(Arrays.asList(module));
Class<?> launcherClass = cl.loadClass("com.redhat.ceylon.launcher.Launcher");
runMethod = launcherClass.getMethod("run", String[].class);
} catch (Exception e) {
System.err.println("Fatal: Ceylon command could not be executed");
throw e;
}
try {
result = (Integer)runMethod.invoke(null, (Object)args);
} catch (InvocationTargetException e) {
throw e.getCause();
}
return result.intValue();
} finally {
if (cl != null) {
cl.clearCache();
try {
cl.close();
} catch (IOException e) {
// Ignore
}
}
}
}
}