/**
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.deephacks.westty;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
/**
* Launcher is responsible for setting the classpath and
* launching the main program.
*/
public class Launcher {
/** files to put on current thread classloader */
private final List<File> classpath = new ArrayList<>();
/** system property of main class to launch */
private static final String MAIN_CLASS_PROP = "main.class";
/** system property to determine launcher run script directory */
private static final String LAUNCHER_HOME_PROP = "WESTTY_LAUNCHER_HOME";
/** system property of directory to load westty classpath from */
private static final String LIB_DIR_PROP = "WESTTY_LIB_DIR";
/** system property of directory to load application classpath from */
private static final String APP_DIR_PROP = "WESTTY_APP_DIR";
/** system property of directory to load application classpath from */
private static final String CONF_DIR_PROP = "WESTTY_CONF_DIR";
/** Are we in debug mode, --debug */
private boolean debug = false;
public static void main(String[] args) throws Exception {
Launcher launcher = new Launcher();
for (int i = 0; i < args.length; i++) {
if ("--debug".equals(args[i].trim())) {
launcher.debug = true;
}
}
launcher.run(args);
}
public void run(String[] args) throws Exception {
String launcherHome = System.getProperty(LAUNCHER_HOME_PROP);
if (launcherHome == null || "".equals(launcherHome)) {
throw new IllegalArgumentException("set " + LAUNCHER_HOME_PROP + " system property");
}
String mainClass = System.getProperty(MAIN_CLASS_PROP);
if (mainClass == null || "".equals(launcherHome)) {
throw new IllegalArgumentException("set main.class system property");
}
String libDir = System.getProperty(LIB_DIR_PROP);
if (libDir == null || "".equals(libDir)) {
throw new IllegalArgumentException("set " + LIB_DIR_PROP + " system property");
}
String appDir = System.getProperty(APP_DIR_PROP);
if (appDir == null || "".equals(appDir)) {
throw new IllegalArgumentException("set " + APP_DIR_PROP + " system property");
}
String confDir = System.getProperty(CONF_DIR_PROP);
if (confDir == null || "".equals(confDir)) {
throw new IllegalArgumentException("set " + CONF_DIR_PROP + " system property");
}
add(new File(libDir));
add(new File(appDir));
setContextClassLoader();
initLogback(new File(confDir, "westty-logback.xml"));
Class<?> main = Thread.currentThread().getContextClassLoader().loadClass(mainClass);
main.getDeclaredMethod("main", String[].class).invoke(null, new Object[] { args });
}
public void setContextClassLoader() {
URL[] urls = new URL[classpath.size()];
for (int i = 0; i < urls.length; i++) {
urls[i] = toURL(classpath.get(i));
}
URLClassLoader loader = new URLClassLoader(urls, ClassLoader.getSystemClassLoader());
Thread.currentThread().setContextClassLoader(loader);
}
public void add(Collection<File> files) {
for (File file : files) {
add(file);
}
}
public void add(File file) {
if (!file.exists()) {
if (debug) {
System.out.println(file.getAbsolutePath() + " does not exist.");
}
}
if (file.isDirectory()) {
File[] files = file.listFiles();
for (File f : files) {
if (!f.isDirectory()) {
classpath.add(f);
}
}
} else {
classpath.add(file);
}
}
private static URL toURL(File file) {
try {
return file.toURI().toURL();
} catch (MalformedURLException e) {
throw new IllegalArgumentException(e);
}
}
void initLogback(File file) {
if (!file.exists()) {
if (debug) {
System.out.println(file.getAbsolutePath() + " does not exist.");
}
return;
}
Class<?> loggerFactoryCls = null;
Class<?> loggerContextCls = null;
Class<?> contextCls = null;
Class<?> joranConfiguratorCls = null;
try {
loggerFactoryCls = Thread.currentThread().getContextClassLoader()
.loadClass("org.slf4j.LoggerFactory");
loggerContextCls = Thread.currentThread().getContextClassLoader()
.loadClass("ch.qos.logback.classic.LoggerContext");
contextCls = Thread.currentThread().getContextClassLoader()
.loadClass("ch.qos.logback.core.Context");
joranConfiguratorCls = Thread.currentThread().getContextClassLoader()
.loadClass("ch.qos.logback.classic.joran.JoranConfigurator");
} catch (ClassNotFoundException e) {
// missing logging classes, ignore
if (debug) {
e.printStackTrace();
}
return;
}
try {
Object LoggerContext = loggerFactoryCls.getMethod("getILoggerFactory").invoke(
(Object) null);
Object JoranConfigurator = joranConfiguratorCls.newInstance();
joranConfiguratorCls.getMethod("setContext", contextCls).invoke(JoranConfigurator,
LoggerContext);
loggerContextCls.getMethod("reset", (Class<?>[]) null).invoke(LoggerContext);
joranConfiguratorCls.getMethod("doConfigure", File.class).invoke(JoranConfigurator,
file);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}