From: wisberg Date: Thu, 1 May 2003 13:17:35 +0000 (+0000) Subject: minimal run-in-same-vm feature for ajbrowser X-Git-Tag: V1_1_0_RC2~97 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=85fd1bf2b7858c46ce39ad2c08fbcf2e7cb81212;p=aspectj.git minimal run-in-same-vm feature for ajbrowser --- diff --git a/ajbrowser/src/org/aspectj/tools/ajbrowser/BrowserManager.java b/ajbrowser/src/org/aspectj/tools/ajbrowser/BrowserManager.java index b2ec90571..d03e38304 100644 --- a/ajbrowser/src/org/aspectj/tools/ajbrowser/BrowserManager.java +++ b/ajbrowser/src/org/aspectj/tools/ajbrowser/BrowserManager.java @@ -14,6 +14,7 @@ package org.aspectj.tools.ajbrowser; +import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.List; @@ -23,6 +24,7 @@ import javax.swing.JFrame; import org.aspectj.ajde.Ajde; import org.aspectj.ajde.BuildConfigManager; import org.aspectj.ajde.BuildListener; +import org.aspectj.ajde.ProjectPropertiesAdapter; import org.aspectj.ajde.TaskListManager; import org.aspectj.ajde.ui.InvalidResourceException; import org.aspectj.ajde.ui.UserPreferencesAdapter; @@ -31,6 +33,8 @@ import org.aspectj.ajde.ui.swing.AjdeUIManager; import org.aspectj.ajde.ui.swing.BasicEditor; import org.aspectj.ajde.ui.swing.IconRegistry; import org.aspectj.ajde.ui.swing.MultiStructureViewPanel; +import org.aspectj.util.LangUtil; +import org.aspectj.util.Reflection; /** * IDE manager for standalone AJDE application. @@ -45,7 +49,7 @@ public class BrowserManager { public static BrowserManager getDefault() { return INSTANCE; } - + private List configFiles = new ArrayList(); public static final String TITLE = "AspectJ Browser"; @@ -131,8 +135,8 @@ public class BrowserManager { topFrame.setTitle(BrowserManager.TITLE + " - " + text); } - public void run() { - Runner.run(Ajde.getDefault().getProjectProperties().getClassToExecute()); + public void run() { + Ajde.runInSameVM(Ajde.getDefault().getProjectProperties()); } public void saveAll() { @@ -181,40 +185,31 @@ public class BrowserManager { return configs; } - private static class Runner { - public static void run(String className) { - try { - Process p = Runtime.getRuntime().exec("java " - //+ "-classpath" + Ajde.getDefault().getProjectProperties().getClasspath() + " " - + className); - } catch(IOException ioe) { - Ajde.getDefault().getErrorHandler().handleError("Coud not run: " + className, ioe); - } - } - - public static void invoke(String className) { - try { - if (className == null || className.length() == 0) { - Ajde.getDefault().getErrorHandler().handleWarning("No main class specified, please select a class to run."); - - } else { - Class[] argTypes = { String[].class }; - java.lang.reflect.Method method = Class.forName(className).getDeclaredMethod("main", argTypes); - Object[] args = { new String[0] }; - method.invoke(null, args); - } - } catch(ClassNotFoundException cnfe) { - Ajde.getDefault().getErrorHandler().handleWarning("Main class not found: " + className + - "\nMake sure that you have \".\" on your classpath."); - } catch(NoSuchMethodException nsme) { - Ajde.getDefault().getErrorHandler().handleWarning("Class: " + className + " does not declare public static void main(String[])"); - } catch(java.lang.reflect.InvocationTargetException ite) { - Ajde.getDefault().getErrorHandler().handleWarning("Could not execute: " + className); - } catch(IllegalAccessException iae) { - Ajde.getDefault().getErrorHandler().handleWarning("Class: " + className + " does not declare public main method"); - } - } - } +// private static class Runner { +// +// public static void invoke(String className) { +// try { +// if (className == null || className.length() == 0) { +// Ajde.getDefault().getErrorHandler().handleWarning("No main class specified, please select a class to run."); +// +// } else { +// Class[] argTypes = { String[].class }; +// java.lang.reflect.Method method = Class.forName(className).getDeclaredMethod("main", argTypes); +// Object[] args = { new String[0] }; +// method.invoke(null, args); +// } +// } catch(ClassNotFoundException cnfe) { +// Ajde.getDefault().getErrorHandler().handleWarning("Main class not found: " + className + +// "\nMake sure that you have \".\" on your classpath."); +// } catch(NoSuchMethodException nsme) { +// Ajde.getDefault().getErrorHandler().handleWarning("Class: " + className + " does not declare public static void main(String[])"); +// } catch(java.lang.reflect.InvocationTargetException ite) { +// Ajde.getDefault().getErrorHandler().handleWarning("Could not execute: " + className); +// } catch(IllegalAccessException iae) { +// Ajde.getDefault().getErrorHandler().handleWarning("Class: " + className + " does not declare public main method"); +// } +// } +// } private final BuildListener BUILD_MESSAGES_LISTENER = new BuildListener() { diff --git a/ajde/src/org/aspectj/ajde/Ajde.java b/ajde/src/org/aspectj/ajde/Ajde.java index 7f0292982..bc9893dea 100644 --- a/ajde/src/org/aspectj/ajde/Ajde.java +++ b/ajde/src/org/aspectj/ajde/Ajde.java @@ -14,6 +14,7 @@ package org.aspectj.ajde; +import java.io.File; import java.io.PrintStream; import java.util.List; @@ -26,6 +27,8 @@ import org.aspectj.ajde.ui.StructureViewManager; import org.aspectj.ajde.ui.StructureViewNodeFactory; import org.aspectj.asm.StructureModelManager; import org.aspectj.bridge.Version; +import org.aspectj.util.LangUtil; +import org.aspectj.util.Reflection; /** * Singleton class responsible for AJDE initialization, and the main point of access to @@ -38,6 +41,33 @@ public class Ajde { private static final Ajde INSTANCE = new Ajde(); private static final String NOT_INITIALIZED_MESSAGE = "Ajde is not initialized."; private static boolean isInitialized = false; + + /** + * Utility to run the project main class in the same VM + * using a class loader populated with the classpath + * and output path or jar. + * @param project the ProjectPropertiesAdapter specifying the + * main class, classpath, and executable arguments. + */ + public static void runInSameVM(ProjectPropertiesAdapter project) { + String mainClass = ""; + try { + mainClass = project.getClassToExecute(); + if (LangUtil.isEmpty(mainClass)) { + Ajde.getDefault().getErrorHandler().handleWarning("No main class specified"); + } + String classpath = project.getOutputPath(); + if (LangUtil.isEmpty(classpath)) { + classpath = project.getOutJar(); + } + classpath += File.pathSeparator + project.getClasspath(); + String[] args = LangUtil.split(project.getExecutionArgs()); + Reflection.runMainInSameVM(classpath, mainClass, args); + } catch(Throwable e) { + Ajde.getDefault().getErrorHandler().handleError("Error running " + mainClass, e); + } + } + private BuildManager buildManager; private EditorManager editorManager; private StructureViewManager structureViewManager; diff --git a/util/src/org/aspectj/util/Reflection.java b/util/src/org/aspectj/util/Reflection.java index bee7bd70e..6804afaa6 100644 --- a/util/src/org/aspectj/util/Reflection.java +++ b/util/src/org/aspectj/util/Reflection.java @@ -13,10 +13,15 @@ package org.aspectj.util; +import java.io.File; import java.lang.reflect.*; import java.lang.reflect.Method; +import java.net.URL; +import java.util.ArrayList; +import java.util.StringTokenizer; public class Reflection { + public static final Class[] MAIN_PARM_TYPES = new Class[] {String[].class}; private Reflection() { } @@ -103,4 +108,97 @@ public class Reflection { } } + public static void runMainInSameVM( + String classpath, + String className, + String[] args) + throws SecurityException, NoSuchMethodException, + IllegalArgumentException, IllegalAccessException, + InvocationTargetException, ClassNotFoundException { + LangUtil.throwIaxIfNull(className, "class name"); + if (LangUtil.isEmpty(classpath)) { + Class mainClass = Class.forName(className); + runMainInSameVM(mainClass, args); + return; + } + ArrayList dirs = new ArrayList(); + ArrayList libs = new ArrayList(); + ArrayList urls = new ArrayList(); + String[] entries = LangUtil.splitClasspath(classpath); + for (int i = 0; i < entries.length; i++) { + String entry = entries[i]; + URL url = makeURL(entry); + if (null != url) { + urls.add(url); + } + File file = new File(entries[i]); +// tolerate bad entries b/c bootclasspath sometimes has them +// if (!file.canRead()) { +// throw new IllegalArgumentException("cannot read " + file); +// } + if (FileUtil.hasZipSuffix(file)) { + libs.add(file); + } else if (file.isDirectory()) { + dirs.add(file); + } else { + // not URL, zip, or dir - unsure what to do + } + } + File[] dirRa = (File[]) dirs.toArray(new File[0]); + File[] libRa = (File[]) libs.toArray(new File[0]); + URL[] urlRa = (URL[]) urls.toArray(new URL[0]); + runMainInSameVM(urlRa, libRa, dirRa, className, args); + } + + public static void runMainInSameVM( + URL[] urls, + File[] libs, + File[] dirs, + String className, + String[] args) + throws SecurityException, NoSuchMethodException, + IllegalArgumentException, IllegalAccessException, + InvocationTargetException, ClassNotFoundException { + LangUtil.throwIaxIfNull(className, "class name"); + LangUtil.throwIaxIfNotAssignable(libs, File.class, "jars"); + LangUtil.throwIaxIfNotAssignable(dirs, File.class, "dirs"); + URL[] libUrls = FileUtil.getFileURLs(libs); + if (!LangUtil.isEmpty(libUrls)) { + if (!LangUtil.isEmpty(urls)) { + URL[] temp = new URL[libUrls.length + urls.length]; + System.arraycopy(urls, 0, temp, 0, urls.length); + System.arraycopy(urls, 0, temp, libUrls.length, urls.length); + urls = temp; + } else { + urls = libUrls; + } + } + UtilClassLoader loader = new UtilClassLoader(urls, dirs); + Class targetClass = null; + try { + targetClass = loader.loadClass(className); + } catch (ClassNotFoundException e) { + String s = "unable to load class " + className + + " using class loader " + loader; + throw new ClassNotFoundException(s); + } + Method main = targetClass.getMethod("main", MAIN_PARM_TYPES); + main.invoke(null, new Object[] { args }); + } + + public static void runMainInSameVM(Class mainClass, String[] args) throws SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException { + LangUtil.throwIaxIfNull(mainClass, "main class"); + Method main = mainClass.getMethod("main", MAIN_PARM_TYPES); + main.invoke(null, new Object[] { args }); + } + + /** @return URL if the input is valid as such */ + private static URL makeURL(String s) { + try { + return new URL(s); + } catch (Throwable t) { + return null; + } + } + } diff --git a/util/src/org/aspectj/util/UtilClassLoader.java b/util/src/org/aspectj/util/UtilClassLoader.java new file mode 100644 index 000000000..dc4ec6fc7 --- /dev/null +++ b/util/src/org/aspectj/util/UtilClassLoader.java @@ -0,0 +1,140 @@ +/* ******************************************************************* + * Copyright (c) 2003 Contributors. + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Isberg initial implementation + * ******************************************************************/ + +package org.aspectj.util; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; + +/** + * Load classes as File from File[] dirs or URL[] jars. + */ +public class UtilClassLoader extends URLClassLoader { + + /** seek classes in dirs first */ + List /*File*/ dirs; + + /** save URL[] only for toString */ + private URL[] urlsForDebugString; + + public UtilClassLoader(URL[] urls, File[] dirs) { + super(urls); + LangUtil.throwIaxIfNotAssignable(dirs, File.class, "dirs"); + this.urlsForDebugString = urls; + ArrayList dcopy = new ArrayList(); + + if (!LangUtil.isEmpty(dirs)) { + dcopy.addAll(Arrays.asList(dirs)); + } + this.dirs = Collections.unmodifiableList(dcopy); + } + + + public URL getResource(String name) { + return ClassLoader.getSystemResource(name); + } + + public InputStream getResourceAsStream(String name) { + return ClassLoader.getSystemResourceAsStream(name); + } + + public synchronized Class loadClass(String name, boolean resolve) + throws ClassNotFoundException { + // search the cache, our dirs (if maybe test), + // the system, the superclass (URL[]), + // and our dirs again (if not maybe test) + ClassNotFoundException thrown = null; + Class result = findLoadedClass(name); + if (null != result) { + resolve = false; + } else { + try { + result = findSystemClass(name); + } catch (ClassNotFoundException e) { + thrown = e; + } + } + if (null == result) { + try { + result = super.loadClass(name, resolve); + } catch (ClassNotFoundException e) { + thrown = e; + } + if (null != result) { // resolved by superclass + return result; + } + } + if (null == result) { + byte[] data = readClass(name); + if (data != null) { + result = defineClass(name, data, 0, data.length); + } // handle ClassFormatError? + } + + if (null == result) { + throw (null != thrown ? thrown : new ClassNotFoundException(name)); + } + if (resolve) { + resolveClass(result); + } + return result; + } + + /** @return null if class not found or byte[] of class otherwise */ + private byte[] readClass(String className) throws ClassNotFoundException { + final String fileName = className.replace('.', '/')+".class"; + for (Iterator iter = dirs.iterator(); iter.hasNext();) { + File file = new File((File) iter.next(), fileName); + if (file.canRead()) { + return getClassData(file); + } + } + return null; + } + + private byte[] getClassData(File f) { + try { + FileInputStream stream= new FileInputStream(f); + ByteArrayOutputStream out= new ByteArrayOutputStream(1000); + byte[] b= new byte[4096]; + int n; + while ((n= stream.read(b)) != -1) { + out.write(b, 0, n); + } + stream.close(); + out.close(); + return out.toByteArray(); + } catch (IOException e) { + } + return null; + } + + /** @return String with debug info: urls and classes used */ + public String toString() { + return "UtilClassLoader(urls=" + + Arrays.asList(urlsForDebugString) + + ", dirs=" + + dirs + + ")"; + } +} +