package gov.nasa.jpl.mbee.mdk.test.framework; import com.nomagic.runtime.ApplicationExitedException; import org.gradle.process.internal.streams.EncodedStream; import java.io.DataInputStream; import java.io.File; import java.io.IOException; import java.io.ObjectInputStream; import java.lang.management.ManagementFactory; import java.lang.management.RuntimeMXBean; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.net.*; import java.util.*; import java.util.stream.Collectors; /** * Created by igomes on 10/22/16. */ public class GradleMagicDrawLauncher { private static final String FRAMEWORK_LAUNCHER_CLASS = System.getProperty("com.nomagic.osgi.launcher", "com.nomagic.osgi.launcher.ProductionFrameworkLauncher"); private URLClassLoader urlClassLoader; private String mainClass; private String[] mainClassArgs = new String[]{}; public static void main(String... args) throws Exception { new GradleMagicDrawLauncher().run(args); } public void run(String... args) throws Exception { urlClassLoader = (URLClassLoader) getClass().getClassLoader(); parseArgs(args); invokeMainMethod(FRAMEWORK_LAUNCHER_CLASS); } private void invokeMainMethod(String clazzName) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, ApplicationExitedException { Class<?> clazz = Class.forName(clazzName, true, urlClassLoader); Method mainMethod = clazz.getMethod("main", String[].class); System.setProperty("com.nomagic.magicdraw.launcher", mainClass); mainMethod.invoke(null, new Object[]{mainClassArgs}); } private void parseArgs(String... args) throws IOException { int mainClassIndex = -1; List<URL> cpElements = new ArrayList<>(); for (int i = 0; i < args.length; i++) { String arg = args[i]; if ((arg.equals("-cp") || arg.equals("-classpath")) && i + 1 < args.length) { String newClassPath = args[++i]; StringTokenizer tokenizer = new StringTokenizer(newClassPath, File.pathSeparator); while(tokenizer.hasMoreTokens()) { String cpElement = tokenizer.nextToken(); try { cpElements.add((new File(".")).toURI().resolve((new File(cpElement)).toURI()).toURL()); } catch (MalformedURLException ignored) { } String currentClassPath = System.getProperty("java.class.path"); System.setProperty("java.class.path", (currentClassPath != null ? currentClassPath + File.pathSeparatorChar + cpElement : cpElement)); } continue; } if (arg.startsWith("-D")) { arg = arg.substring(2); String[] parts = arg.split("="); String key = parts[0]; String value = parts.length > 1 ? "" : null; for (int j = 1; j < parts.length; j++) { value += parts[j]; } String ignored = value != null ? System.setProperty(key, value) : System.clearProperty(key); continue; } if (arg.contains("org.gradle")) { mainClass = arg; mainClassIndex = i; break; } } if (mainClassIndex >= 0) { mainClassArgs = Arrays.copyOfRange(args, mainClassIndex + 1, args.length); } /** * This is used to load all the necessary libraries into the classpath and is usually done in GradleWorkerMain. * However, we need them added to the classpath before launching the OSGi framework and additionally need to add them to java.class.path. * To achieve that we've overridden the usual GradleWorkerMain with one that excludes the classloading and done it here. * {@link worker.org.gradle.process.internal.worker.GradleWorkerMain} * Gradle likes it's class overriding hacks, so to avoid issues caused by ones we haven't discovered we're loading Gradle libraries first. */ DataInputStream instr = new DataInputStream(new EncodedStream.EncodedInput(System.in)); // Read shared packages int sharedPackagesCount = instr.readInt(); List<String> sharedPackages = new ArrayList<>(sharedPackagesCount); for (int i = 0; i < sharedPackagesCount; i++) { sharedPackages.add(instr.readUTF()); } // Read worker implementation classpath int classPathLength = instr.readInt(); List<String> files = new ArrayList<>(classPathLength); List<URL> moreCpElements = new ArrayList<>(1 + cpElements.size() + classPathLength); for (int i = 0; i < classPathLength; i++) { String cpElement = instr.readUTF(); files.add(cpElement); moreCpElements.add(new URL(cpElement)); } moreCpElements.addAll(cpElements); cpElements = moreCpElements; if (!files.isEmpty()) { String currentClassPath = System.getProperty("java.class.path"); String newClassPath = files.stream().collect(Collectors.joining(File.pathSeparator)); System.setProperty("java.class.path", (currentClassPath != null ? newClassPath + File.pathSeparatorChar + currentClassPath : newClassPath)); } /** * Adds our tests-hack.jar to the front of the classloader (and java.class.path) so our patches to Gradle's hacks can do their jobs. * For an example see {@link org.gradle.internal.logging.slf4j.Slf4jLoggingConfigurer}. */ URL runtimeJar = getClass().getProtectionDomain().getCodeSource().getLocation(); if (runtimeJar != null) { cpElements.add(0, runtimeJar); String currentClassPath = System.getProperty("java.class.path"); try { String runtimeJarPath = runtimeJar.toURI().getPath(); System.setProperty("java.class.path", (currentClassPath != null ? runtimeJarPath + File.pathSeparatorChar + currentClassPath : runtimeJarPath)); } catch (URISyntaxException e) { e.printStackTrace(); } } if (!cpElements.isEmpty()) { urlClassLoader = new URLClassLoader(cpElements.toArray(new URL[cpElements.size()])); } } }