package org.jetbrains.jps.runConf.java; import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.io.IOException; import java.lang.reflect.Method; import java.net.URL; import java.net.URLClassLoader; import java.util.ArrayList; import java.util.Arrays; import java.util.List; public class MainClassLauncher { public static void main(String[] args) throws Throwable { if (args.length < 4) { return; } String className = args[0]; String testRunnerCp = args[1]; String testsRuntimeCp = args[2]; String tempArgsFileName = args[3]; URL[] testsRuntimeClasspath = getClasspathElems(testsRuntimeCp); URL[] tcRuntimeClasspath = getClasspathElems(testRunnerCp); List<String> arguments = getArguments(tempArgsFileName); System.out.println("Runtime classpath: " + Arrays.asList(testsRuntimeClasspath)); ClassLoader testsRuntimeClassloader = new URLClassLoader(testsRuntimeClasspath, null); ClassLoader mainClassLoader = new MainClassClassLoader(tcRuntimeClasspath, testsRuntimeClassloader); Class<?> main = mainClassLoader.loadClass(className); Method mainMethod = main.getMethod("main", String[].class); // we must not set mainClassLoader to context classloader, because it allows access to our classes, which we want to hide Thread.currentThread().setContextClassLoader(testsRuntimeClassloader); try { mainMethod.invoke(null, new Object[] { arguments.toArray(new String[arguments.size()])}); } catch (Throwable e) { throw new RuntimeException("Exception occurred in main class: " + main.getName() + ", error: " + e.toString(), e); } System.exit(0); } private static URL[] getClasspathElems(String tempFileName) throws IOException { List<URL> result = new ArrayList<URL>(); for (String line: loadLines(tempFileName)) { URL url = new File(line).toURL(); result.add(url); } //System.out.println("DEBUG INFO: libraries: " + result); URL[] array = new URL[result.size()]; result.toArray(array); return array; } private static List<String> getArguments(String tempFileName) throws IOException { return loadLines(tempFileName); } private static List<String> loadLines(final String tempFileName) throws IOException { List<String> result = new ArrayList<String>(); BufferedReader reader = new BufferedReader(new FileReader(tempFileName)); try { while(true) { String line = reader.readLine(); if (line == null) break; result.add(line); } //System.out.println("DEBUG INFO: arguments: " + result.toString()); return result; } finally { reader.close(); } } /** * This classloader makes classes from the specified URLs more preferrable than classes from the parent classloader. * Specified main class is loaded by this classloader. */ private static class MainClassClassLoader extends URLClassLoader { public MainClassClassLoader(final URL[] urls, final ClassLoader parent) { super(urls, parent); } public synchronized Class loadClass(String name, boolean resolve) throws ClassNotFoundException { Class c = findLoadedClass(name); if (c == null) { try { c = findClass(name); } catch (ClassNotFoundException e) { c = super.loadClass(name, resolve); } } if (resolve) { resolveClass(c); } return c; } } }