diff --git a/proposal/anteater/bootstrap/Bootstrap.java b/proposal/anteater/bootstrap/Bootstrap.java index eb326c4c4..45b461938 100644 --- a/proposal/anteater/bootstrap/Bootstrap.java +++ b/proposal/anteater/bootstrap/Bootstrap.java @@ -51,7 +51,8 @@ public class Bootstrap { if (classpath == null) { command = new String[] {"javac", "./Bootstrap2.java"}; } else { - command = new String[] {"javac", "-classpath", classpath, "./Bootstrap2.java"}; + command = new String[] {"javac", "-classpath", classpath, + "./Bootstrap2.java"}; } runCommand(command); @@ -61,13 +62,20 @@ public class Bootstrap { } else { command = new String[] {"java", "-cp", classpath, "Bootstrap2"}; } - runCommand(command); + runCommand(command, args); } /** * Utility method for execing processes */ static void runCommand(String[] command) throws IOException { + + System.out.print("Exec'ing: "); + for (int i = 0; i < command.length; i++) { + System.out.print(command[i] + " "); + } + System.out.println(); + Runtime runtime = Runtime.getRuntime(); Process process = runtime.exec(command); @@ -94,5 +102,20 @@ public class Bootstrap { } } } + + /** + * Utility method for running processes that let some additional args + * be specified. + */ + static void runCommand(String[] command, String[] addtlArgs) throws IOException { + String[] newCommand = new String[command.length + addtlArgs.length]; + for (int i = 0; i < command.length; i++) { + newCommand[i] = command[i]; + } + for (int i = 0; i < addtlArgs.length; i++) { + newCommand[command.length + i] = addtlArgs[i]; + } + runCommand(newCommand); + } } diff --git a/proposal/anteater/bootstrap/Bootstrap2.java b/proposal/anteater/bootstrap/Bootstrap2.java index dd6572c68..18550a200 100644 --- a/proposal/anteater/bootstrap/Bootstrap2.java +++ b/proposal/anteater/bootstrap/Bootstrap2.java @@ -87,7 +87,7 @@ public class Bootstrap2 { cmdarray[7] = base + "source/main.ant"; cmdarray[8] = "default"; - Bootstrap.runCommand(cmdarray); + Bootstrap.runCommand(cmdarray, args); System.out.println(); System.out.println("-------------------------------------------"); diff --git a/proposal/anteater/source/main/org/apache/ant/Ant.java b/proposal/anteater/source/main/org/apache/ant/Ant.java index 5da538aed..68abecd53 100644 --- a/proposal/anteater/source/main/org/apache/ant/Ant.java +++ b/proposal/anteater/source/main/org/apache/ant/Ant.java @@ -23,22 +23,17 @@ public class Ant { /** * */ - private Hashtable abstractTaskClasses = new Hashtable(); + private File buildfile; /** - * + * The front end running this. */ - private File buildfile; + private AntFrontEnd frontEnd; /** * Manager of tasks. */ private TaskManager taskManager = new TaskManager(); - - /** - * - */ - private Vector taskPathNodes = new Vector(); /** * @@ -52,7 +47,8 @@ public class Ant { /** * Constructs a new Ant instance. */ - public Ant() { + public Ant(AntFrontEnd frontEnd) { + this.frontEnd = frontEnd; setUpTaskPath(); } @@ -61,26 +57,30 @@ public class Ant { // ----------------------------------------------------------------- /** - * Sets additional path nodes onto the task lookup path. These nodes - * take precendence over all previously set path nodes. + * Sets additional path nodes onto the task lookup path. */ public void addTaskPathNode(File node) { - taskPathNodes.insertElementAt(node, 0); taskManager.addTaskPathNode(node); } /** - * + * Builds a target. */ public void buildTarget(String targetName) throws AntException { + // notify FrontEnd that we are starting a build on a project + frontEnd.notifyProjectStart(project); + Target target = project.getTarget(targetName); + frontEnd.notifyTargetStart(target); + // XXX don't forget to execute dependancies first! Enumeration enum = target.getTasks().elements(); while (enum.hasMoreElements()) { Task task = (Task)enum.nextElement(); + frontEnd.notifyTaskStart(task); AbstractTask aTask = taskManager.getTaskInstance(task.getType()); try { aTask.setProject(project); @@ -94,7 +94,12 @@ public class Ant { // XXX yes yes yes, this shouldn't be a catch all... throw new AntException("ERR: " + e); } + frontEnd.notifyTaskEnd(task); } + + // notify frontEnd that we are done + frontEnd.notifyTargetEnd(target); + frontEnd.notifyProjectEnd(project); } /** diff --git a/proposal/anteater/source/main/org/apache/ant/AntException.java b/proposal/anteater/source/main/org/apache/ant/AntException.java index c0c6598c8..16d7a6995 100644 --- a/proposal/anteater/source/main/org/apache/ant/AntException.java +++ b/proposal/anteater/source/main/org/apache/ant/AntException.java @@ -5,17 +5,134 @@ package org.apache.ant; /** - * Signals a problem. + * Signals a problem while setting up or executing a build. * * @author James Duncan Davidson (duncan@apache.org) */ public class AntException extends Exception { + // ----------------------------------------------------------------- + // PRIVATE MEMBERS + // ----------------------------------------------------------------- + + /** + * The cause of this exception. + */ + private Throwable cause; + + /** + * Project within which this exception occured, if applicable. + */ + private Project project; + + /** + * Target within which this exception occurred, if applicable. + */ + private Target target; + + /** + * Task within which this exception occurred, if applicable. + */ + private Task task; + + // ----------------------------------------------------------------- + // CONSTRUCTORS + // ----------------------------------------------------------------- + + /** + * Constructs a new AntException with no message. + */ public AntException() { super(); } + /** + * Constructs a new AntException with the given message. + */ public AntException(String msg) { super(msg); } + + /** + * Constructs a new AntException with the given message and cause. + */ + public AntException(String msg, Throwable cause) { + super(msg); + this.cause = cause; + } + + /** + * Constructs a new AntException with the given cause and a + * detailed message of (cause==null ? null : cause.toString()) + */ + public AntException(Throwable cause) { + super(cause==null ? null : cause.toString()); + this.cause = cause; + } + + // ----------------------------------------------------------------- + // PUBLIC METHODS + // ----------------------------------------------------------------- + + /** + * Returns the cause of this exception. + */ + public Throwable getCause() { + return cause; + } + + /** + * Returns the Project within the scope of which this exception occurred, + * if applicable. Otherwise null. + */ + public Project getProject() { + return project; + } + + /** + * Returns the Target within the scope of which this exception occurred, + * if applicable. Otherwise null. + */ + public Target getTarget() { + return target; + } + + /** + * Returns the Task wihtin the scope of which this exception occurred, + * if applicable. Otherwise null. + */ + public Task getTask() { + return task; + } + + // ----------------------------------------------------------------- + // PACKAGE METHODS + // ----------------------------------------------------------------- + + /** + * Sets the project within the scope of which this exception occurred. + * This method is called by the internal error handling mechanism of + * Ant before it is propogated out. + */ + void setProject(Project project) { + this.project = project; + } + + /** + * Sets the target within the scope of which this exception occurred. + * This method is called by the internal error handling mechansim of + * Ant before it is propogated out. + */ + void setTarget(Target target) { + this.target = target; + } + + /** + * Sets the task within the scope of which this exception occurred. + * This method is called by the internal error handling mechanism of + * Ant before it is propogated out. + */ + void setTask(Task task) { + this.task = task; + } } \ No newline at end of file diff --git a/proposal/anteater/source/main/org/apache/ant/AntFrontEnd.java b/proposal/anteater/source/main/org/apache/ant/AntFrontEnd.java new file mode 100644 index 000000000..9e3081418 --- /dev/null +++ b/proposal/anteater/source/main/org/apache/ant/AntFrontEnd.java @@ -0,0 +1,103 @@ +// ------------------------------------------------------------------------------- +// Copyright (c)2000 Apache Software Foundation +// ------------------------------------------------------------------------------- + +package org.apache.ant; + +/** + * Abstract class that lets Ant talk to a front end such as a CLI front end, + * GUI front end, Servlet front end, or some other front end. + * + * @author James Duncan Davidson (duncan@apache.org) + */ +public abstract class AntFrontEnd { + + // ----------------------------------------------------------------- + // CONSTANTS + // ----------------------------------------------------------------- + + /** + * Indicates that an associated message has a low importance. + */ + public static final int MSG_LEVEL_LOW = 1; + + /** + * Indicates that an associated message has a medium importance. + */ + public static final int MSG_LEVEL_MED = 2; + + /** + * Indicates that an associated message has a high importance. + */ + public static final int MSG_LEVEL_HIGH = 3; + + // ----------------------------------------------------------------- + // PUBLIC METHODS + // ----------------------------------------------------------------- + + /** + * Send notification to the FrontEnd that execution has moved into + * the scope of a particular project. The default implementation + * does nothing. + */ + public void notifyProjectStart(Project project) { + + } + + /** + * Send notification to the FrontEnd that execution has moved out + * of the scope of a particular Project. The default implementation + * does nothing. + */ + public void notifyProjectEnd(Project project) { + + } + + /** + * Send notification to the FrontEnd that execution has moved into + * the scope of a particular target. The default implementation does + * nothing. + */ + public void notifyTargetStart(Target target) { + + } + + /** + * Send notification to the FrontEnd that execution has moved out of + * the scope of a particular target. The default implementation does + * nothing. + */ + public void notifyTargetEnd(Target target) { + + } + + /** + * Send notification to the FrontEnd that execution has moved into the + * scope of a particular task. The default implementation does nothing. + */ + public void notifyTaskStart(Task task) { + + } + + /** + * Send notification to the FrontEnd that execution has moved out of + * the scope of a particular task. The default implementation does + * nothing. + */ + public void notifyTaskEnd(Task task) { + + } + + /** + * Writes a message to the front end with a medium importance. + */ + public void writeMessage(String message) { + writeMessage(message, MSG_LEVEL_MED); + } + + /** + * Writes a message to the front end. + */ + public abstract void writeMessage(String message, int level); + +} \ No newline at end of file diff --git a/proposal/anteater/source/main/org/apache/ant/cli/CLIFrontEnd.java b/proposal/anteater/source/main/org/apache/ant/cli/CLIFrontEnd.java new file mode 100644 index 000000000..e8ee0ad73 --- /dev/null +++ b/proposal/anteater/source/main/org/apache/ant/cli/CLIFrontEnd.java @@ -0,0 +1,182 @@ +// ------------------------------------------------------------------------------- +// Copyright (c)2000 Apache Software Foundation +// ------------------------------------------------------------------------------- + +package org.apache.ant.cli; + +import java.io.*; +import java.util.*; +import org.apache.ant.*; + +/** + * Front end for the Command Line Interface that gets passed to Ant so that + * it can communicate information to the CLI. + * + * @author James Duncan Davidson (duncan@apache.org) + */ +public class CLIFrontEnd extends AntFrontEnd { + + // ----------------------------------------------------------------- + // PRIVATE MEMBERS + // ----------------------------------------------------------------- + + /** + * + */ + private Ant ant; + + /** + * + */ + private int msgLevel = MSG_LEVEL_MED; + + // ----------------------------------------------------------------- + // CONSTRUCTORS + // ----------------------------------------------------------------- + + /** + * + */ + public CLIFrontEnd() { + ant = new Ant(this); + } + + // ----------------------------------------------------------------- + // PUBLIC METHODS + // ----------------------------------------------------------------- + + /** + * Send notification to the FrontEnd that execution has moved into + * the scope of a particular project. The default implementation + * does nothing. + */ + public void notifyProjectStart(Project project) { + writeMessage("Project Start: " + project.getName(), MSG_LEVEL_LOW); + } + + /** + * Send notification to the FrontEnd that execution has moved out + * of the scope of a particular Project. The default implementation + * does nothing. + */ + public void notifyProjectEnd(Project project) { + writeMessage("Project End: " + project.getName(), MSG_LEVEL_LOW); + } + + /** + * Send notification to the FrontEnd that execution has moved into + * the scope of a particular target. The default implementation does + * nothing. + */ + public void notifyTargetStart(Target target) { + writeMessage("Target Start: " + target.getName(), MSG_LEVEL_LOW); + } + + /** + * Send notification to the FrontEnd that execution has moved out of + * the scope of a particular target. The default implementation does + * nothing. + */ + public void notifyTargetEnd(Target target) { + writeMessage("Target End: " + target.getName(), MSG_LEVEL_LOW); + } + + /** + * Send notification to the FrontEnd that execution has moved into the + * scope of a particular task. The default implementation does nothing. + */ + public void notifyTaskStart(Task task) { + writeMessage("Task Start: " + task.getType(), MSG_LEVEL_LOW); + } + + /** + * Send notification to the FrontEnd that execution has moved out of + * the scope of a particular task. The default implementation does + * nothing. + */ + public void notifyTaskEnd(Task task) { + writeMessage("Task End: " + task.getType(), MSG_LEVEL_LOW); + } + + /** + * Prints help to System.out + */ + private void printHelp() { + String ls = System.getProperty("line.separator"); + String msg = "Usage: ant [args] [target]" + ls + + " Arguments can be any of the following:" + ls + + " -help" + ls + + " -taskpath [path]" + ls + + " -buildfile [file]" +ls + + " -verbose" + ls + + " -quiet" + ls + ls + + " Note that if no buildfile argument is given, Ant will"+ls+ + " try to find one in the current directory. If there are"+ls+ + " two or more buildfiles in the current directory, it" +ls+ + " will bail."; + writeMessage(msg); + } + + /** + * + */ + public void run(String[] args) { + String target = ""; + writeMessage("Ant(Eater) -- Proposed Ant 2.0"); + + // flip through args and set things accordingly + for (int i = 0; i < args.length; i++) { + String arg = args[i]; + // scan through -- all -aaa args come first. + if (arg.startsWith("-")) { + if (arg.equals("-help")) { + printHelp(); + return; + } else if (arg.equals("-taskpath")) { + // XXX + // need to seperate on pathsep, but not today + ant.addTaskPathNode(new File(args[++i])); + } else if (arg.equals("-buildfile")) { + // XXX + // need to check file to make sure it exists! + try { + ant.setBuildfile(new File(args[++i])); + } catch (AntException ae) { + writeMessage("ICK: " + ae); + writeMessage(ae.getMessage()); + return; + } + } + } else { + target = arg; + } + } + + // XXX do something if we dont' have a buildfile set! + + // XXX really should check to make sure that the target is set to something + + // set our listeners on the project + + Project project = ant.getProject(); + project.setOutput(System.out); + + try { + ant.buildTarget(target); + } catch (AntException ae) { + writeMessage("Problem while building: " + ae); + writeMessage(ae.getMessage()); + } + } + + /** + * Writes a message to the front end. + */ + public void writeMessage(String message, int level) { + if (level >= msgLevel) { + System.out.println(message); + } + } + + +} \ No newline at end of file diff --git a/proposal/anteater/source/main/org/apache/ant/cli/Main.java b/proposal/anteater/source/main/org/apache/ant/cli/Main.java index 85dfb3972..844d04e8b 100644 --- a/proposal/anteater/source/main/org/apache/ant/cli/Main.java +++ b/proposal/anteater/source/main/org/apache/ant/cli/Main.java @@ -5,85 +5,73 @@ package org.apache.ant.cli; import java.io.*; +import java.net.*; import java.util.*; -import org.apache.ant.*; /** - * Entry point for Ant on the Command Line Interface. + * Entry point for Ant on the Command Line Interface. This class sets + * up the basic environment that Ant will execute in and then hands + * off the the CLIFrontEnd class. * * @author James Duncan Davidson (duncan@apache.org) */ public class Main { /** - * Command line entry point. + * Command line entry point. Here we set up the environment via + * a URLCLassLoader and then execute in the scope of that class loader + * so that the user doesnt have to set things up themselves. */ - public static void main(String[] args) { - Ant ant = new Ant(); - String target = ""; - - System.out.println("Ant(Eater) -- Proposed Ant 2.0"); - - // flip through args and set things accordingly - for (int i = 0; i < args.length; i++) { - String arg = args[i]; - // scan through -- all -aaa args come first. - if (arg.startsWith("-")) { - if (arg.equals("-help")) { - printHelp(); - return; - } else if (arg.equals("-taskpath")) { - // XXX - // need to seperate on pathsep, but not today - ant.addTaskPathNode(new File(args[++i])); - } else if (arg.equals("-buildfile")) { - // XXX - // need to check file to make sure it exists! - try { - ant.setBuildfile(new File(args[++i])); - } catch (AntException ae) { - System.out.println("ICK: " + ae); - System.out.println(ae.getMessage()); - return; - } - } - } else { - target = arg; + public static void main(String[] args) throws Exception { + + CLIFrontEnd frontEnd; + + // check a few things out and make sure we have the right things + // that we need in our classpath -- set those up in a custom class + // loader and execute from there... + + Vector classpathNodes = new Vector(); + + // check to see if we have a compiler on the classpath. Right now + // we're just checking for the old compiler, but that does tell us + // if we have tools.jar or not + try { + Class clazz = Class.forName("sun.tools.javac.Main"); + } catch (ClassNotFoundException cnfe) { + String javaHome = System.getProperty("java.home"); + if (javaHome.endsWith("jre")) { + javaHome = javaHome.substring(0, javaHome.length() - 4); } + // XXX should check if this exists and bail out if it doesn't + String classpath = javaHome + "/lib/tools.jar"; + URL url = new File(classpath).toURL(); + classpathNodes.addElement(url); } - // XXX do something if we dont' have a buildfile set! - - // XXX really should check to make sure that the target is set to something - - // set our listeners on the project + // XXX add handling for -cp [classpath] argument to set up more classpath + // nodes - Project project = ant.getProject(); - project.setOutput(System.out); - - System.out.println(); - System.out.println("Executing Target: " + target); + URL[] urls = new URL[classpathNodes.size()]; + Enumeration enum = classpathNodes.elements(); + int i = 0; + while (enum.hasMoreElements()) { + urls[i++] = (URL)enum.nextElement(); + } + URLClassLoader classLoader = new URLClassLoader(urls); try { - ant.buildTarget(target); - } catch (AntException ae) { - System.out.println("Problem while building: " + ae); - System.out.println(ae.getMessage()); - } - } - - // ----------------------------------------------------------------- - // PRIVATE METHODS - // ----------------------------------------------------------------- - - /** - * Prints help to System.out - */ - private static void printHelp() { - System.out.println("Usage: ant [args] [target]"); - System.out.println(" Arguments:"); - System.out.println(" -help"); - System.out.println(" -taskpath [path]"); - System.out.println(" -buildfile [file]"); + frontEnd = (CLIFrontEnd)classLoader.loadClass( + "org.apache.ant.cli.CLIFrontEnd").newInstance(); + } catch (ClassNotFoundException cnfe) { + System.out.println("Crap: " + cnfe); + return; + } catch (InstantiationException ie) { + System.out.println("Crap: " + ie); + return; + } catch (IllegalAccessException iae) { + System.out.println("Crap: " + iae); + return; + } + frontEnd.run(args); } } \ No newline at end of file