You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@ant.apache.org by du...@locus.apache.org on 2000/12/08 19:06:57 UTC

cvs commit: jakarta-ant/proposal/anteater/source/main/org/apache/ant/cli CLIFrontEnd.java Main.java

duncan      00/12/08 10:06:57

  Modified:    proposal/anteater/bootstrap Bootstrap.java Bootstrap2.java
               proposal/anteater/source/main/org/apache/ant Ant.java
                        AntException.java
               proposal/anteater/source/main/org/apache/ant/cli Main.java
  Added:       proposal/anteater/source/main/org/apache/ant
                        AntFrontEnd.java
               proposal/anteater/source/main/org/apache/ant/cli
                        CLIFrontEnd.java
  Log:
  Several things all at once...
  
      * Bootstrap now passes args all the way through
      * FrontEnding implemented which allows Ant to talk back out
        to whatever front end might be driving it. Events propogated
        are project start/end, target start/end, task start/end.
        This should allow any front end (like a GUI) to move a
        progress indicator through a display of the object tree.
        Also included is a generic writeMessage(String, int) method.
      * cli/Main now plays ClassLoader games so that it can auto
        matically place needed resources (like tools.jar) into
        the classpath space of the executing Ant. Note -- this
        is the first of a few steps to make complicated shell
        launch scripts unnecessary. All that should be done
        is a single executable per platform that essentially
        calls "java -jar anteater.jar [args]". Main is also
        primed for a future CJAN so that it can download whatever
        jars are needed from CJAN and place them into the classpath
        space of the executing Ant. Of course, it's not implemented
        yet since CJAN isn't around yet -- but its ready. :)
      * AntException now has fields for embedding the location
        of an Error. Next up will be implementing the code
        around where Tasks are run so that exceptions will contain
        this information.
  
  Revision  Changes    Path
  1.4       +25 -2     jakarta-ant/proposal/anteater/bootstrap/Bootstrap.java
  
  Index: Bootstrap.java
  ===================================================================
  RCS file: /home/cvs/jakarta-ant/proposal/anteater/bootstrap/Bootstrap.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- Bootstrap.java	2000/12/06 18:26:13	1.3
  +++ Bootstrap.java	2000/12/08 18:06:51	1.4
  @@ -51,7 +51,8 @@
           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 @@
           } 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);
               
  @@ -93,6 +101,21 @@
                   count = in.read(buf, 0, buf.length);
               }
           }
  +    }
  +    
  +    /**
  +     * 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);
       }
   } 
    
  
  
  
  1.3       +1 -1      jakarta-ant/proposal/anteater/bootstrap/Bootstrap2.java
  
  Index: Bootstrap2.java
  ===================================================================
  RCS file: /home/cvs/jakarta-ant/proposal/anteater/bootstrap/Bootstrap2.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- Bootstrap2.java	2000/12/07 20:35:30	1.2
  +++ Bootstrap2.java	2000/12/08 18:06:51	1.3
  @@ -87,7 +87,7 @@
           cmdarray[7] = base + "source/main.ant"; 
           cmdarray[8] = "default";
           
  -        Bootstrap.runCommand(cmdarray);
  +        Bootstrap.runCommand(cmdarray, args);
           
           System.out.println();
           System.out.println("-------------------------------------------");
  
  
  
  1.3       +18 -13    jakarta-ant/proposal/anteater/source/main/org/apache/ant/Ant.java
  
  Index: Ant.java
  ===================================================================
  RCS file: /home/cvs/jakarta-ant/proposal/anteater/source/main/org/apache/ant/Ant.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- Ant.java	2000/12/07 20:36:11	1.2
  +++ Ant.java	2000/12/08 18:06:54	1.3
  @@ -23,22 +23,17 @@
       /**
        *
        */
  -    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 @@
       /**
        * Constructs a new Ant instance.
        */
  -    public Ant() {
  +    public Ant(AntFrontEnd frontEnd) {
  +        this.frontEnd = frontEnd;
           setUpTaskPath();
       }
       
  @@ -61,26 +57,30 @@
       // ----------------------------------------------------------------- 
       
       /**
  -     * 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 @@
                   // 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);
       }
       
       /**
  
  
  
  1.2       +118 -1    jakarta-ant/proposal/anteater/source/main/org/apache/ant/AntException.java
  
  Index: AntException.java
  ===================================================================
  RCS file: /home/cvs/jakarta-ant/proposal/anteater/source/main/org/apache/ant/AntException.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- AntException.java	2000/12/06 08:08:35	1.1
  +++ AntException.java	2000/12/08 18:06:54	1.2
  @@ -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;
       }
   }
  
  
  
  1.1                  jakarta-ant/proposal/anteater/source/main/org/apache/ant/AntFrontEnd.java
  
  Index: AntFrontEnd.java
  ===================================================================
  // -------------------------------------------------------------------------------
  // 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);
  
  }
  
  
  1.2       +52 -64    jakarta-ant/proposal/anteater/source/main/org/apache/ant/cli/Main.java
  
  Index: Main.java
  ===================================================================
  RCS file: /home/cvs/jakarta-ant/proposal/anteater/source/main/org/apache/ant/cli/Main.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- Main.java	2000/12/06 08:08:40	1.1
  +++ Main.java	2000/12/08 18:06:56	1.2
  @@ -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);
       }
   }
  
  
  
  1.1                  jakarta-ant/proposal/anteater/source/main/org/apache/ant/cli/CLIFrontEnd.java
  
  Index: CLIFrontEnd.java
  ===================================================================
  // -------------------------------------------------------------------------------
  // 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);
          }
      }
  
  
  }