metridoc.runner.MetridocRunner Maven / Gradle / Ivy
/*
* Copyright 2010 Trustees of the University of Pennsylvania Licensed under the
* Educational Community 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.osedu.org/licenses/ECL-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 metridoc.runner;
import java.io.*;
import java.lang.reflect.Method;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLClassLoader;
import java.security.ProtectionDomain;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.zip.ZipEntry;
/**
* Created by IntelliJ IDEA.
* User: tbarker
* Date: 2/4/12
* Time: 8:26 PM
*/
public class MetridocRunner {
public static final int BAD_URI_SYNTAX = 1;
public static final int COULD_NOT_OPEN_CURRENT_JAR = 2;
public static final int COULD_NOT_OPEN_OR_MANIPULATE_FILE = 3;
public static final int COULD_NOT_LOAD_CONSOLE = 4;
public static final int COULD_NOT_RUN_COMMAND = 5;
public static final String METRIDOC_CONSOLE = "metridoc.console.MetridocConsole";
public static final String SET_CONSOLE_CLASS_LOADER = "setClassLoader";
public static final String RUN_CONSOLE_COMMAND = "runConsoleCommand";
public static final boolean DO_LOGGING = Boolean.valueOf(System.getProperty("metridoc.runner.logging", "false"));
private static final int DEFAULT_BUFFER_SIZE = 1024 * 4;
public static void main(String[] args) {
JarFile thisJar = getCurrentFile();
URL[] urlArray = createLibJarCopies(thisJar);
log("the following number of urls will be added to the classpath: " + urlArray.length);
for (URL url : urlArray) {
log("adding the following url to classpath: " + url.toString());
}
runJob(urlArray, args);
}
private static JarFile getCurrentFile(){
ProtectionDomain domain = MetridocRunner.class.getProtectionDomain();
URL location = domain.getCodeSource().getLocation();
File thisFile = null;
try {
thisFile = new File(location.toURI());
} catch (URISyntaxException e) {
error(e, BAD_URI_SYNTAX);
}
JarFile thisJar = null;
try {
thisJar = new JarFile(thisFile);
} catch (IOException e) {
error(e, COULD_NOT_OPEN_CURRENT_JAR);
}
return thisJar;
}
private static void runJob(URL[] urlArray, String[] args){
URLClassLoader urlClassLoader = new URLClassLoader(urlArray);
Method runConsoleCommand = null;
Object console = null;
try {
Class consoleClass = urlClassLoader.loadClass(METRIDOC_CONSOLE);
console = consoleClass.newInstance();
Method setClassLoader = consoleClass.getMethod(SET_CONSOLE_CLASS_LOADER, ClassLoader.class);
setClassLoader.invoke(console, urlClassLoader);
runConsoleCommand = consoleClass.getMethod(RUN_CONSOLE_COMMAND, String[].class);
} catch (Exception e) {
error(e, COULD_NOT_LOAD_CONSOLE);
}
Thread.currentThread().setContextClassLoader(urlClassLoader);
try {
Object[] params = new Object[1];
params[0] = args;
runConsoleCommand.invoke(console, params);
} catch (Exception e) {
error(e, COULD_NOT_RUN_COMMAND);
}
}
private static URL[] createLibJarCopies(JarFile mainJar){
Enumeration entries = mainJar.entries();
List urls = new ArrayList();
while (entries.hasMoreElements()) {
ZipEntry entry = entries.nextElement();
String entryName = entry.getName();
boolean isJar = entryName.startsWith("META-INF/lib/") && entryName.endsWith(".jar");
if (isJar) {
log("Preparing to add entry " + entryName + " to the classpath");
String temporaryFileName = entryName.replace("/", "_");
try {
File jarTempFile = File.createTempFile(temporaryFileName, ".tmp");
jarTempFile.deleteOnExit();
OutputStream outputStream = new FileOutputStream(jarTempFile);
InputStream inputStream = mainJar.getInputStream(entry);
copy(inputStream, outputStream);
log(jarTempFile.toURI().toURL().toString());
urls.add(jarTempFile.toURI().toURL());
} catch (IOException e) {
error(e, COULD_NOT_OPEN_OR_MANIPULATE_FILE);
}
}
}
return urls.toArray(new URL[urls.size()]);
}
/**
* Basically stolen from IOUtils in apache commons. Just wanted to avoid as much dependency issues as possible
*
* TODO: maybe we should do this in parallel to make it faster?
*
* @param inputStream stream that will be copied
* @param outputStream destination for the stream
* @throws IOException occurrs if copy operation occurs
*/
private static void copy(InputStream inputStream, OutputStream outputStream) throws IOException {
byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
int n = 0;
while (-1 != (n = inputStream.read(buffer))) {
outputStream.write(buffer, 0, n);
}
}
private static void log(String message) {
if (DO_LOGGING) {
System.out.println(message);
}
}
private static void error(Exception exception, int exitCode) {
exception.printStackTrace();
System.exit(exitCode);
}
}