package org.aspectj.ajde;
-import java.io.File;
-import java.io.PrintStream;
-import java.util.List;
-
import org.aspectj.ajde.internal.AspectJBuildManager;
import org.aspectj.ajde.internal.LstBuildConfigManager;
import org.aspectj.ajde.ui.EditorManager;
import org.aspectj.util.LangUtil;
import org.aspectj.util.Reflection;
+import java.io.PrintStream;
+import java.util.Arrays;
+import java.util.List;
+
/**
* Singleton class responsible for AJDE initialization, and the main point of access to
* Ajde functionality.
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 = "<none>";
- 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;
}
}
+ /**
+ * Utility to run the project main class from the project
+ * properties in the same VM
+ * using a class loader populated with the classpath
+ * and output path or jar.
+ * Errors are logged to the ErrorHandler.
+ * @param project the ProjectPropertiesAdapter specifying the
+ * main class, classpath, and executable arguments.
+ * @return Thread running with process, or null if unable to start
+ */
+ public Thread runInSameVM() {
+ final RunProperties props
+ = new RunProperties(getProjectProperties(), getErrorHandler());
+ if (!props.valid) {
+ return null; // error already handled
+ }
+ Runnable runner = new Runnable() {
+ public void run() {
+ try {
+ Reflection.runMainInSameVM(
+ props.classpath,
+ props.mainClass,
+ props.args);
+ } catch(Throwable e) {
+ Ajde.getDefault().getErrorHandler().handleError("Error running " + props.mainClass, e);
+ }
+ }
+ };
+ Thread result = new Thread(runner, props.mainClass);
+ result.start();
+ return result;
+ }
+
+ /**
+ * Utility to run the project main class from the project
+ * properties in a new VM.
+ * Errors are logged to the ErrorHandler.
+ * @return LangUtil.ProcessController running with process,
+ * or null if unable to start
+ */
+ public LangUtil.ProcessController runInNewVM() {
+ final RunProperties props
+ = new RunProperties(getProjectProperties(), getErrorHandler());
+ if (!props.valid) {
+ return null; // error already handled
+ }
+ // setup to run asynchronously, pipe streams through, and report errors
+ final StringBuffer command = new StringBuffer();
+ LangUtil.ProcessController controller
+ = new LangUtil.ProcessController() {
+ protected void doCompleting(Throwable thrown, int result) {
+ LangUtil.ProcessController.Thrown any = getThrown();
+ if (!any.thrown && (null == thrown) && (0 == result)) {
+ return; // no errors
+ }
+ // handle errors
+ String context = props.mainClass
+ + " command \""
+ + command
+ + "\"";
+ if (null != thrown) {
+ String m = "Exception running " + context;
+ getErrorHandler().handleError(m, thrown);
+ } else if (0 != result) {
+ String m = "Result of running " + context;
+ getErrorHandler().handleError(m + ": " + result);
+ }
+ if (null != any.fromInPipe) {
+ String m = "Error processing input pipe for " + context;
+ getErrorHandler().handleError(m, any.fromInPipe);
+ }
+ if (null != any.fromOutPipe) {
+ String m = "Error processing output pipe for " + context;
+ getErrorHandler().handleError(m, any.fromOutPipe);
+ }
+ if (null != any.fromErrPipe) {
+ String m = "Error processing error pipe for " + context;
+ getErrorHandler().handleError(m, any.fromErrPipe);
+ }
+ }
+ };
+
+ controller = LangUtil.makeProcess(
+ controller,
+ props.classpath,
+ props.mainClass,
+ props.args);
+
+ command.append(Arrays.asList(controller.getCommand()).toString());
+
+ // now run the process
+ controller.start();
+ return controller;
+ }
+
private final BuildConfigListener STRUCTURE_UPDATE_CONFIG_LISTENER = new BuildConfigListener() {
public void currConfigChanged(String configFilePath) {
if (configFilePath != null) Ajde.getDefault().getStructureModelManager().readStructureModel(configFilePath);
this.errorHandler = errorHandler;
}
+ /** struct class to interpret project properties */
+ private static class RunProperties {
+ final String mainClass;
+ final String classpath;
+ final String[] args;
+ final boolean valid;
+ RunProperties(
+ ProjectPropertiesAdapter project,
+ ErrorHandler handler) {
+ // XXX really run arbitrary handler in constructor? hmm.
+ LangUtil.throwIaxIfNull(project, "project");
+ LangUtil.throwIaxIfNull(handler, "handler");
+ String mainClass = null;
+ String classpath = null;
+ String[] args = null;
+ boolean valid = false;
+
+ mainClass = project.getClassToExecute();
+ if (LangUtil.isEmpty(mainClass)) {
+ handler.handleWarning("No main class specified");
+ } else {
+ classpath = LangUtil.makeClasspath(
+ project.getBootClasspath(),
+ project.getClasspath(),
+ project.getOutputPath(),
+ project.getOutJar());
+ if (LangUtil.isEmpty(classpath)) {
+ handler.handleWarning("No classpath specified");
+ } else {
+ args = LangUtil.split(project.getExecutionArgs());
+ valid = true;
+ }
+ }
+ this.mainClass = mainClass;
+ this.classpath = classpath;
+ this.args = args;
+ this.valid = valid;
+ }
+ }
}