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

cvs commit: jakarta-ant/src/main/org/apache/tools/ant/taskdefs Ant.java Javac.java

conor       00/06/24 03:55:47

  Modified:    src/main/org/apache/tools/ant Main.java Project.java
                        ProjectHelper.java Target.java
               src/main/org/apache/tools/ant/taskdefs Ant.java Javac.java
  Added:       src/main/org/apache/tools/ant BuildEvent.java
                        BuildListener.java DefaultLogger.java
                        XmlLogger.java
  Log:
  Add BuildEvents to Ant
  
  The basic idea is to keep the core build engine "clean" and free of any
  presentation logic, and to make it easier to extend Ant with other features
  without cluttering up the core. To do this, I've defined a BuildListener
  interface and added an "addBuildListener" method to Project that can be
  used to register listener objects. Listeners could be implemented to
  generate reports, send out emails when the build is complete, create a
  bill of materials, etc...
  
  The only new functionality visible to the end-user is a "-listener" option
  on the command line that will let you specify the name of a class. An
  instance of this class will be added as a listener to the project. I've
  included a listener that will generate an XML log file, which you can use
  by typing the command below.
  
  build -listener org.apache.tools.ant.XmlLogger
  
  Submitted by:	Matt Foemmel <mp...@ThoughtWorks.com>
  
  Revision  Changes    Path
  1.8       +67 -17    jakarta-ant/src/main/org/apache/tools/ant/Main.java
  
  Index: Main.java
  ===================================================================
  RCS file: /home/cvs/jakarta-ant/src/main/org/apache/tools/ant/Main.java,v
  retrieving revision 1.7
  retrieving revision 1.8
  diff -u -r1.7 -r1.8
  --- Main.java	2000/06/18 02:22:23	1.7
  +++ Main.java	2000/06/24 10:55:38	1.8
  @@ -73,20 +73,28 @@
   public class Main {
   
       /** Our current message output status. Follows Project.MSG_XXX */
  -    private static int msgOutputLevel = Project.MSG_INFO;
  +    private int msgOutputLevel = Project.MSG_INFO;
   
       /** File that we are using for configuration */
  -    private static File buildFile = new File("build.xml");
  +    private File buildFile = new File("build.xml");
   
       /** Stream that we are using for logging */
  -    private static PrintStream out = System.out;
  +    private PrintStream out = System.out;
   
       /** The build targets */
  -    private static Vector targets = new Vector(5);
  +    private Vector targets = new Vector(5);
   
       /** Set of properties that can be used by tasks */
  -    private static Properties definedProps = new Properties();
  +    private Properties definedProps = new Properties();
   
  +    /** Names of classes to add as listeners to project */
  +    private Vector listeners = new Vector(5);
  +
  +    /**
  +     * Indicates if this ant should be run.
  +     */
  +    private boolean readyToRun = false;
  +
       /**
        * Command line entry point. This method kicks off the building
        * of a project object and executes a build using either a given
  @@ -94,9 +102,12 @@
        *
        * @param args Command line args.
        */
  -
       public static void main(String[] args) {
  +        new Main(args).runBuild();
  +    }
   
  +    protected Main(String[] args) {
  +
           // cycle through given args
   
           for (int i = 0; i < args.length; i++) {
  @@ -137,6 +148,16 @@
                       System.out.println(msg);
                       return;
                   }
  +            } else if (arg.equals("-listener")) {
  +                try {
  +                    listeners.addElement(args[i+1]);
  +                    i++;
  +                } catch (ArrayIndexOutOfBoundsException aioobe) {
  +                    String msg = "You must specify a classname when " +
  +                        "using the -listener argument";
  +                    System.out.println(msg);
  +                    return;
  +                }
               } else if (arg.startsWith("-D")) {
   
                   /* Interestingly enough, we get to here when a user
  @@ -170,6 +191,7 @@
                   // if it's no other arg, it may be the target
                   targets.addElement(arg);
               }
  +            
           }
   
           // make sure buildfile exists
  @@ -186,19 +208,20 @@
               System.out.println("What? Buildfile: " + buildFile + " is a dir!");
               return;
           }
  -
  -        // ok, so if we've made it here, let's run the damn build allready
  -        runBuild();
   
  -        return;
  +        readyToRun = true;
       }
   
       /**
        * Executes the build.
        */
   
  -    private static void runBuild() {
  +    private void runBuild() {
   
  +        if (!readyToRun) {
  +            return;
  +        }
  +        
           // track when we started
   
           long startTime = System.currentTimeMillis();
  @@ -206,7 +229,10 @@
               System.out.println("Buildfile: " + buildFile);
           }
   
  -        Project project = new Project(out, msgOutputLevel);
  +        Project project = new Project();
  +        addBuildListeners(project);
  +        project.fireBuildStarted();
  +        project.init();
   
           // set user-define properties
           Enumeration e = definedProps.keys();
  @@ -215,7 +241,8 @@
               String value = (String)definedProps.get(arg);
               project.setUserProperty(arg, value);
           }
  -	project.setUserProperty( "ant.file" , buildFile.getAbsolutePath() );
  +
  +        project.setUserProperty( "ant.file" , buildFile.getAbsolutePath() );
   
           // first use the ProjectHelper to create the project object
           // from the given build file.
  @@ -248,10 +275,7 @@
   
           // actually do some work
           try {
  -            Enumeration en = targets.elements();
  -            while (en.hasMoreElements()) {
  -                project.executeTarget((String) en.nextElement());
  -            }
  +            project.executeTargets(targets);
           } catch (BuildException be) {
               String msg = "\nBUILD FATAL ERROR\n\n";
               System.out.println(msg + be.toString());
  @@ -270,6 +294,31 @@
           }
       }
   
  +    protected void addBuildListeners(Project project) {
  +
  +        // Add the default listener
  +        project.addBuildListener(createDefaultBuildListener());
  +
  +        for (int i = 0; i < listeners.size(); i++) {
  +            String className = (String) listeners.elementAt(i);
  +            try {
  +                BuildListener listener =
  +                    (BuildListener) Class.forName(className).newInstance();
  +                project.addBuildListener(listener);
  +            }
  +            catch(Exception exc) {
  +                throw new BuildException("Unable to instantiate " + className, exc);
  +            }
  +        }
  +    }
  +
  +    /**
  +     *  Creates the default build listener for displaying output to the screen.
  +     */
  +    private BuildListener createDefaultBuildListener() {
  +        return new DefaultLogger(out, msgOutputLevel);
  +    }
  +
       /**
        * Prints the usage of how to use this class to System.out
        */
  @@ -282,6 +331,7 @@
           msg.append("  -quiet                 be extra quiet" + lSep);
           msg.append("  -verbose               be extra verbose" + lSep);
           msg.append("  -logfile <file>        use given file for log" + lSep);
  +        msg.append("  -listener <classname>  add an instance of class as a project listener" + lSep);
           msg.append("  -buildfile <file>      use given buildfile" + lSep);
           msg.append("  -D<property>=<value>   use value for given property" + lSep);
           System.out.println(msg.toString());
  
  
  
  1.21      +122 -22   jakarta-ant/src/main/org/apache/tools/ant/Project.java
  
  Index: Project.java
  ===================================================================
  RCS file: /home/cvs/jakarta-ant/src/main/org/apache/tools/ant/Project.java,v
  retrieving revision 1.20
  retrieving revision 1.21
  diff -u -r1.20 -r1.21
  --- Project.java	2000/05/27 22:21:09	1.20
  +++ Project.java	2000/06/24 10:55:39	1.21
  @@ -93,8 +93,6 @@
       public static final String TOKEN_END = "@";
   
       private String name;
  -    private PrintStream out;
  -    private int msgOutputLevel = MSG_INFO;
   
       private Hashtable properties = new Hashtable();
       private Hashtable userProperties = new Hashtable();
  @@ -105,11 +103,20 @@
       private Hashtable filters = new Hashtable();
       private File baseDir;
   
  -    public Project(PrintStream out, int msgOutputLevel) {
  +    private Vector listeners = new Vector();
  +    protected Target currentTarget = null;
  +    protected Task currentTask = null;
   
  -        this.out = out;
  -        this.msgOutputLevel = msgOutputLevel;
  +    public Project() {
  +    }
   
  +    /**
  +     * Initialise the project.
  +     *
  +     * This involves setting the default task definitions and loading the
  +     * system properties.
  +     */
  +    public void init() {
           detectJavaVersion();
   
           String defs = "/org/apache/tools/ant/taskdefs/defaults.properties";
  @@ -148,16 +155,16 @@
           }
       }
   
  -    public PrintStream getOutput() {
  -        return this.out;
  +    public void addBuildListener(BuildListener listener) {
  +        listeners.addElement(listener);
       }
   
  -    public void setOutput(PrintStream out) {
  -        this.out=out;
  +    public void removeBuildListener(BuildListener listener) {
  +        listeners.removeElement(listener);
       }
   
  -    public int getOutputLevel() {
  -        return this.msgOutputLevel;
  +    public Vector getBuildListeners() {
  +        return listeners;
       }
   
       public void log(String msg) {
  @@ -165,15 +172,11 @@
       }
   
       public void log(String msg, int msgLevel) {
  -        if (msgLevel <= msgOutputLevel) {
  -            out.println(msg);
  -        }
  +        fireMessageLogged(msg, msgLevel);
       }
   
       public void log(String msg, String tag, int msgLevel) {
  -        if (msgLevel <= msgOutputLevel) {
  -            out.println("[" + tag + "] " + msg);
  -        }
  +        fireMessageLogged(msg, msgLevel);
       }
   
       public void setProperty(String name, String value) {
  @@ -403,6 +406,23 @@
           }
       }
   
  +    public void executeTargets(Vector targetNames) throws BuildException {
  +        Throwable error = null;
  +
  +        try {
  +            for (int i = 0; i < targetNames.size(); i++) {
  +                executeTarget((String)targetNames.elementAt(i));
  +            }
  +        }
  +        catch(RuntimeException exc) {
  +            error = exc;
  +            throw exc;
  +        }
  +        finally {
  +            fireBuildFinished(error);
  +        }
  +    }
  +
       public void executeTarget(String targetName) throws BuildException {
   
           // sanity check ourselves, if we've been asked to build nothing
  @@ -432,7 +452,7 @@
       public File resolveFile(String fileName) {
           // deal with absolute files
           if (fileName.startsWith("/")) return new File( fileName );
  -        if (fileName.startsWith(System.getProperty("file.separator"))) 
  +        if (fileName.startsWith(System.getProperty("file.separator")))
               return new File( fileName );
   
           // Eliminate consecutive slashes after the drive spec
  @@ -672,13 +692,25 @@
       // Target and execute it.
       private final void runTarget(String target, Hashtable targets)
           throws BuildException {
  -        Target t = (Target)targets.get(target);
  -        if (t == null) {
  +
  +        currentTarget = (Target)targets.get(target);
  +        if (currentTarget == null) {
               throw new RuntimeException("Unexpected missing target `"+target+
                                          "' in this project.");
  +        }
  +
  +        try {
  +            fireTargetStarted();
  +            currentTarget.execute();
  +            fireTargetFinished(null);
  +        }
  +        catch(RuntimeException exc) {
  +            fireTargetFinished(exc);
  +            throw exc;
           }
  -        log("Executing Target: "+target, MSG_INFO);
  -        t.execute();
  +        finally {
  +            currentTarget = null;
  +        }
       }
   
       /**
  @@ -803,5 +835,73 @@
   
       public Hashtable getReferences() {
           return references;
  +    }
  +
  +    protected void fireBuildStarted() {
  +        BuildEvent event = createBuildEvent();
  +        for (int i = 0; i < listeners.size(); i++) {
  +            BuildListener listener = (BuildListener) listeners.elementAt(i);
  +            listener.buildStarted(event);
  +        }
  +    }
  +
  +    protected void fireBuildFinished(Throwable exception) {
  +        BuildEvent event = createBuildEvent(exception);
  +        for (int i = 0; i < listeners.size(); i++) {
  +            BuildListener listener = (BuildListener) listeners.elementAt(i);
  +            listener.buildFinished(event);
  +        }
  +    }
  +
  +    protected void fireTargetStarted() {
  +        BuildEvent event = createBuildEvent();
  +        for (int i = 0; i < listeners.size(); i++) {
  +            BuildListener listener = (BuildListener) listeners.elementAt(i);
  +            listener.targetStarted(event);
  +        }
  +    }
  +
  +    protected void fireTargetFinished(Throwable exception) {
  +        BuildEvent event = createBuildEvent(exception);
  +        for (int i = 0; i < listeners.size(); i++) {
  +            BuildListener listener = (BuildListener) listeners.elementAt(i);
  +            listener.targetFinished(event);
  +        }
  +    }
  +
  +    protected void fireTaskStarted() {
  +        BuildEvent event = createBuildEvent();
  +        for (int i = 0; i < listeners.size(); i++) {
  +            BuildListener listener = (BuildListener) listeners.elementAt(i);
  +            listener.taskStarted(event);
  +        }
  +    }
  +
  +    protected void fireTaskFinished(Throwable exception) {
  +        BuildEvent event = createBuildEvent(exception);
  +        for (int i = 0; i < listeners.size(); i++) {
  +            BuildListener listener = (BuildListener) listeners.elementAt(i);
  +            listener.taskFinished(event);
  +        }
  +    }
  +
  +    protected void fireMessageLogged(String message, int priority) {
  +        BuildEvent event = createBuildEvent(message, priority);
  +        for (int i = 0; i < listeners.size(); i++) {
  +            BuildListener listener = (BuildListener) listeners.elementAt(i);
  +            listener.messageLogged(event);
  +        }
  +    }
  +
  +    public BuildEvent createBuildEvent() {
  +        return new BuildEvent(this, currentTarget, currentTask, null, MSG_VERBOSE, null);
  +    }
  +
  +    public BuildEvent createBuildEvent(String msg, int priority) {
  +        return new BuildEvent(this, currentTarget, currentTask, msg, priority, null);
  +    }
  +
  +    public BuildEvent createBuildEvent(Throwable exception) {
  +        return new BuildEvent(this, currentTarget, currentTask, null, MSG_VERBOSE, exception);
       }
   }
  
  
  
  1.13      +1 -1      jakarta-ant/src/main/org/apache/tools/ant/ProjectHelper.java
  
  Index: ProjectHelper.java
  ===================================================================
  RCS file: /home/cvs/jakarta-ant/src/main/org/apache/tools/ant/ProjectHelper.java,v
  retrieving revision 1.12
  retrieving revision 1.13
  diff -u -r1.12 -r1.13
  --- ProjectHelper.java	2000/04/26 19:09:17	1.12
  +++ ProjectHelper.java	2000/06/24 10:55:40	1.13
  @@ -299,7 +299,7 @@
               // take care of dependencies
   
               if (depends.length() > 0) {
  -                StringTokenizer tok = 
  +                StringTokenizer tok =
                       new StringTokenizer(depends, ",", false);
                   while (tok.hasMoreTokens()) {
                       target.addDependency(tok.nextToken().trim());
  
  
  
  1.5       +13 -3     jakarta-ant/src/main/org/apache/tools/ant/Target.java
  
  Index: Target.java
  ===================================================================
  RCS file: /home/cvs/jakarta-ant/src/main/org/apache/tools/ant/Target.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- Target.java	2000/04/26 19:09:17	1.4
  +++ Target.java	2000/06/24 10:55:41	1.5
  @@ -119,11 +119,21 @@
                   Task task = (Task) enum.nextElement();
   
                   try {
  +                    project.currentTask = task;
  +                    project.fireTaskStarted();
                  	    task.execute();
  -		} catch(BuildException exc) {
  -		    exc.setLocation(task.getLocation());
  -		    throw exc;
  +                    project.fireTaskFinished(null);
   		}
  +                catch(RuntimeException exc) {
  +                    if (exc instanceof BuildException) {
  +                        ((BuildException)exc).setLocation(task.getLocation());
  +                    }
  +                    project.fireTaskFinished(exc);
  +                    throw exc;
  +                }
  +                finally {
  +                    project.currentTask = null;
  +                }
               }
           } else {
               project.log("Skipped because property '" + this.condition + "' not set.", this.name, Project.MSG_VERBOSE);
  
  
  
  1.1                  jakarta-ant/src/main/org/apache/tools/ant/BuildEvent.java
  
  Index: BuildEvent.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 1999 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  package org.apache.tools.ant;
  
  import java.util.EventObject;
  
  public class BuildEvent extends EventObject {
      private Project project;
      private Target target;
      private Task task;
      private String message;
      private int priority;
      private Throwable exception;
  
      /**
       *  Constructs a new build event. Fields that are not relevant
       *  can be set to null, except for the project field which is
       *  required.
       */
      public BuildEvent(
          Project project,
          Target target,
          Task task,
          String message,
          int priority,
          Throwable exception) {
  
          super(getSource(project, target, task));
  
          this.project = project;
          this.target = target;
          this.task = task;
          this.message = message;
          this.priority = priority;
          this.exception = exception;
      }
  
      /**
       *  Returns the project that fired this event.
       */
      public Project getProject() {
          return project;
      }
  
      /**
       *  Returns the target that fired this event.
       */
      public Target getTarget() {
          return target;
      }
  
      /**
       *  Returns the task that fired this event.
       */
      public Task getTask() {
          return task;
      }
  
      /**
       *  Returns the logging message. This field will only be set
       *  for "messageLogged" events.
       *
       *  @see BuildListener#messageLogged(BuildEvent)
       */
      public String getMessage() {
          return message;
      }
  
      /**
       *  Returns the priority of the logging message. This field will only
       *  be set for "messageLogged" events.
       *
       *  @see BuildListener#messageLogged(BuildEvent)
       */
      public int getPriority(){
          return priority;
      }
  
      /**
       *  Returns the exception that was thrown, if any. This field will only
       *  be set for "taskFinished", "targetFinished", and "buildFinished" events.
       *
       *  @see BuildListener#taskFinished(BuildEvent)
       *  @see BuildListener#targetFinished(BuildEvent)
       *  @see BuildListener#buildFinished(BuildEvent)
       */
      public Throwable getException() {
          return exception;
      }
  
      /**
       *  Returns the object that fired this event.
       */
      private static Object getSource(Project project, Target target, Task task) {
          if (task != null) return task;
          if (target != null) return target;
          if (project != null) return project;
  
          throw new IllegalArgumentException("Project field cannot be null");
      }
  }
  
  
  1.1                  jakarta-ant/src/main/org/apache/tools/ant/BuildListener.java
  
  Index: BuildListener.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 1999 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  package org.apache.tools.ant;
  
  import java.util.EventListener;
  
  /**
   *  Classes that implement this interface will be notified when
   *  things happend during a build.
   *
   *  @see BuildEvent
   *  @see Project#addBuildListener(BuildListener)
   */
  public interface BuildListener extends EventListener {
  
      /**
       *  Fired before any targets are started.
       */
      public void buildStarted(BuildEvent event);
  
      /**
       *  Fired after the last target has finished. This event
       *  will still be thrown if an error occured during the build.
       *
       *  @see BuildEvent.getException()
       */
      public void buildFinished(BuildEvent event);
  
      /**
       *  Fired when a target is started.
       *
       *  @see BuildEvent#getTarget()
       */
      public void targetStarted(BuildEvent event);
  
      /**
       *  Fired when a target has finished. This event will
       *  still be thrown if an error occured during the build.
       *
       *  @see BuildEvent.getException()
       */
      public void targetFinished(BuildEvent event);
  
      /**
       *  Fired when a task is started.
       *
       *  @see BuildEvent#getTask()
       */
      public void taskStarted(BuildEvent event);
  
      /**
       *  Fired when a task has finished. This event will still
       *  be throw if an error occured during the build.
       *
       *  @see BuildEvent#getException()
       */
      public void taskFinished(BuildEvent event);
  
      /**
       *  Fired whenever a message is logged.
       *
       *  @see BuildEvent#getMessage()
       *  @see BuildEvent#getPriority()
       */
      public void messageLogged(BuildEvent event);
  
  }
  
  
  1.1                  jakarta-ant/src/main/org/apache/tools/ant/DefaultLogger.java
  
  Index: DefaultLogger.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 1999 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  package org.apache.tools.ant;
  
  import java.io.*;
  
  /**
   *  Writes build event to a PrintStream. Currently, it
   *  only writes which targets are being executed, and
   *  any messages that get logged.
   */
  public class DefaultLogger implements BuildListener {
      private PrintStream out;
      private int msgOutputLevel;
  
      /**
       *  Constructs a new logger which will write to the specified
       *  PrintStream. Messages with a priority lower (higher?) than
       *  msgOutputLevel will be ignored.
       */
      public DefaultLogger(PrintStream out, int msgOutputLevel) {
          this.out = out;
          this.msgOutputLevel = msgOutputLevel;
      }
  
      public void buildStarted(BuildEvent event) {}
      public void buildFinished(BuildEvent event) {}
  
      public void targetStarted(BuildEvent event) {
          if (msgOutputLevel <= Project.MSG_INFO) {
              out.println("Executing Target: " + event.getTarget().getName());
          }
      }
  
      public void targetFinished(BuildEvent event) {}
  
      public void taskStarted(BuildEvent event) {}
      public void taskFinished(BuildEvent event) {}
  
      public void messageLogged(BuildEvent event) {
  
          // Filter out messages based on priority
          if (event.getPriority() <= msgOutputLevel) {
  
              // Print out the name of the task if we're in one
              if (event.getTask() != null) {
                  String name = event.getTask().getClass().getName();
                  int pos = name.lastIndexOf(".");
                  if (pos != -1) {
                      name = name.substring(pos + 1);
                  }
                  out.print("[" + name + "] ");
              }
  
              // Print the message
              out.println(event.getMessage());
          }
      }
  }
  
  
  1.1                  jakarta-ant/src/main/org/apache/tools/ant/XmlLogger.java
  
  Index: XmlLogger.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 1999 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  package org.apache.tools.ant;
  
  import java.io.*;
  import javax.xml.parsers.*;
  import org.w3c.dom.*;
  
  /**
   *  Generates a "log.xml" file in the current directory with
   *  an XML description of what happened during a build.
   *
   *  @see Project#addBuildListener()
   */
  public class XmlLogger implements BuildListener {
  
      private static final DocumentBuilder builder = getDocumentBuilder();
  
      private static DocumentBuilder getDocumentBuilder() {
          try {
              return DocumentBuilderFactory.newInstance().newDocumentBuilder();
          }
          catch(Exception exc) {
              throw new ExceptionInInitializerError(exc);
          }
      }
  
      // XML constants for tag names and attribute names
      private static final String BUILD_TAG = "build";
      private static final String TARGET_TAG = "target";
      private static final String TASK_TAG = "task";
      private static final String MESSAGE_TAG = "message";
      private static final String NAME_ATTR = "name";
      private static final String TIME_ATTR = "time";
      private static final String PRIORITY_ATTR = "priority";
      private static final String LOCATION_ATTR = "location";
      private static final String ERROR_ATTR = "error";
  
      private Document doc;
      private Element buildElement;
      private Element targetElement;
      private Element taskElement;
  
      private long buildStartTime;
      private long targetStartTime;
      private long taskStartTime;
  
      /**
       *  Constructs a new BuildListener that logs build events to an XML file.
       */
      public XmlLogger() {
      }
  
      public void buildStarted(BuildEvent event) {
          buildStartTime = System.currentTimeMillis();
  
          doc = builder.newDocument();
          buildElement = doc.createElement(BUILD_TAG);
      }
  
      public void buildFinished(BuildEvent event) {
          long totalTime = System.currentTimeMillis() - buildStartTime;
          buildElement.setAttribute(TIME_ATTR, formatTime(totalTime));
  
          if (event.getException() != null) {
              buildElement.setAttribute(ERROR_ATTR, event.getException().toString());
          }
  
          try {
                  Writer out = new FileWriter("log.xml");
                  out.write("<?xml:stylesheet type=\"text/xsl\" href=\"log.xsl\"?>\n\n");
                  write(buildElement, out, 0);
                  out.flush();
                  out.close();
  
          }
          catch(IOException exc) {
              throw new BuildException("Unable to close log file", exc);
          }
      }
  
      public void targetStarted(BuildEvent event) {
          targetStartTime = System.currentTimeMillis();
          targetElement = doc.createElement(TARGET_TAG);
          targetElement.setAttribute(NAME_ATTR, event.getTarget().getName());
      }
  
      public void targetFinished(BuildEvent event) {
          long totalTime = System.currentTimeMillis() - targetStartTime;
          targetElement.setAttribute(TIME_ATTR, formatTime(totalTime));
          buildElement.appendChild(targetElement);
  
          targetElement = null;
      }
  
      public void taskStarted(BuildEvent event) {
          taskStartTime = System.currentTimeMillis();
          taskElement = doc.createElement(TASK_TAG);
  
          String name = event.getTask().getClass().getName();
          int pos = name.lastIndexOf(".");
          if (pos != -1) {
              name = name.substring(pos + 1);
          }
          taskElement.setAttribute(NAME_ATTR, name);
  
          taskElement.setAttribute(LOCATION_ATTR, event.getTask().getLocation().toString());
      }
  
      public void taskFinished(BuildEvent event) {
          long totalTime = System.currentTimeMillis() - taskStartTime;
          taskElement.setAttribute(TIME_ATTR, formatTime(totalTime));
          targetElement.appendChild(taskElement);
  
          taskElement = null;
      }
  
      public void messageLogged(BuildEvent event) {
          Element messageElement = doc.createElement(MESSAGE_TAG);
  
          String name = "debug";
          switch(event.getPriority()) {
              case Project.MSG_ERR: name = "error"; break;
              case Project.MSG_WARN: name = "warn"; break;
              case Project.MSG_INFO: name = "info"; break;
              default: name = "debug"; break;
          }
          messageElement.setAttribute(PRIORITY_ATTR, name);
  
          Text messageText = doc.createTextNode(event.getMessage());
          messageElement.appendChild(messageText);
  
          if (taskElement != null) {
              taskElement.appendChild(messageElement);
          }
          else if (targetElement != null) {
              targetElement.appendChild(messageElement);
          }
          else {
              buildElement.appendChild(messageElement);
          }
      }
  
      /**
       *  Writes a DOM element to a file.
       */
      private static void write(Element element, Writer out, int indent) throws IOException {
  
          // Write indent characters
          for (int i = 0; i < indent; i++) {
              out.write("\t");
          }
  
          // Write element
          out.write("<");
          out.write(element.getTagName());
  
          // Write attributes
          NamedNodeMap attrs = element.getAttributes();
          for (int i = 0; i < attrs.getLength(); i++) {
              Attr attr = (Attr) attrs.item(i);
              out.write(" ");
              out.write(attr.getName());
              out.write("=\"");
              out.write(attr.getValue());
              out.write("\"");
          }
          out.write(">");
  
          // Write child attributes and text
          boolean hasChildren = false;
          NodeList children = element.getChildNodes();
          for (int i = 0; i < children.getLength(); i++) {
              Node child = children.item(i);
  
              if (child.getNodeType() == Node.ELEMENT_NODE) {
                  if (!hasChildren) {
                      out.write("\n");
                      hasChildren = true;
                  }
                  write((Element)child, out, indent + 1);
              }
  
              if (child.getNodeType() == Node.TEXT_NODE) {
                  out.write(((Text)child).getData());
              }
          }
  
          // If we had child elements, we need to indent before we close
          // the element, otherwise we're on the same line and don't need
          // to indent
          if (hasChildren) {
              for (int i = 0; i < indent; i++) {
                  out.write("\t");
              }
          }
  
          // Write element close
          out.write("</");
          out.write(element.getTagName());
          out.write(">\n");
      }
  
      private static String formatTime(long millis) {
          long seconds = millis / 1000;
          long minutes = seconds / 60;
  
  
          if (minutes > 0) {
              return Long.toString(minutes) + " minutes " + Long.toString(seconds%60) + " seconds";
          }
          else {
              return Long.toString(seconds) + " seconds";
          }
  
      }
  }
  
  
  1.7       +26 -19    jakarta-ant/src/main/org/apache/tools/ant/taskdefs/Ant.java
  
  Index: Ant.java
  ===================================================================
  RCS file: /home/cvs/jakarta-ant/src/main/org/apache/tools/ant/taskdefs/Ant.java,v
  retrieving revision 1.6
  retrieving revision 1.7
  diff -u -r1.6 -r1.7
  --- Ant.java	2000/03/28 20:40:18	1.6
  +++ Ant.java	2000/06/24 10:55:45	1.7
  @@ -86,9 +86,25 @@
   
       Vector properties=new Vector();
       Project p1;
  -    
  +
       public void init() {
  -        p1 = new Project(project.getOutput(), project.getOutputLevel());
  +        p1 = new Project();
  +        Vector listeners = project.getBuildListeners();
  +        for (int i = 0; i < listeners.size(); i++) {
  +            p1.addBuildListener((BuildListener)listeners.elementAt(i));
  +        }
  +
  +        if (output != null) {
  +            try {
  +                PrintStream out = new PrintStream(new FileOutputStream(output));
  +                p1.addBuildListener(new DefaultLogger(out, Project.MSG_INFO));
  +            }
  +            catch( IOException ex ) {
  +                project.log( "Ant: Can't set output to " + output );
  +            }
  +        }
  +
  +        p1.init();
   
           // set user-define properties
           Hashtable prop1 = project.getProperties();
  @@ -99,36 +115,27 @@
               p1.setProperty(arg, value);
           }
       }
  -    
  +
       /**
        * Do the execution.
        */
       public void execute() throws BuildException {
           if( dir==null) dir=".";
  -	
  -	if( output != null ) {
  -	    try {
  -		PrintStream out=new PrintStream(new FileOutputStream(output));
  -		p1.setOutput( out );
  -	    } catch( IOException ex ) {
  -		project.log( "Ant: Can't set output to " + output );
  -	    }
  -	}
   
  -	p1.setBasedir(dir);
  +        p1.setBasedir(dir);
           p1.setUserProperty("basedir" , dir);
   
  -	// Override with local-defined properties
  -	Enumeration e = properties.elements();
  +        // Override with local-defined properties
  +        Enumeration e = properties.elements();
           while (e.hasMoreElements()) {
               Property p=(Property) e.nextElement();
  -	    //	    System.out.println("Setting " + p.getName()+ " " + p.getValue());
  -	    p.init();
  +            //	    System.out.println("Setting " + p.getName()+ " " + p.getValue());
  +            p.init();
           }
   
  -	if (antFile == null) antFile = dir + "/build.xml";
  +        if (antFile == null) antFile = dir + "/build.xml";
   
  -	p1.setUserProperty( "ant.file" , antFile );
  +        p1.setUserProperty( "ant.file" , antFile );
           ProjectHelper.configureProject(p1, new File(antFile));
   
           if (target == null) {
  
  
  
  1.13      +13 -8     jakarta-ant/src/main/org/apache/tools/ant/taskdefs/Javac.java
  
  Index: Javac.java
  ===================================================================
  RCS file: /home/cvs/jakarta-ant/src/main/org/apache/tools/ant/taskdefs/Javac.java,v
  retrieving revision 1.12
  retrieving revision 1.13
  diff -u -r1.12 -r1.13
  --- Javac.java	2000/05/23 12:08:17	1.12
  +++ Javac.java	2000/06/24 10:55:45	1.13
  @@ -275,7 +275,7 @@
                                                       + ".class");
   
                       if (srcFile.lastModified() > now) {
  -                        project.log("Warning: file modified in the future: " + 
  +                        project.log("Warning: file modified in the future: " +
                               files[i], project.MSG_WARN);
                       }
   
  @@ -423,14 +423,19 @@
           // XXX
           // provide the compiler a different message sink - namely our own
   
  -        JavacOutputStream jos = new JavacOutputStream(project);
  +        ByteArrayOutputStream out = new ByteArrayOutputStream();
  +        sun.tools.javac.Main compiler = new sun.tools.javac.Main(out, "javac");
   
  -        sun.tools.javac.Main compiler =
  -            new sun.tools.javac.Main(jos, "javac");
  -        compiler.compile(args);
  -        if (jos.getErrorFlag()) {
  -            String msg = "Compile failed, messages should have been provided.";
  -            throw new BuildException(msg);
  +        if (compiler.compile(args)) {
  +            String output = out.toString().trim();
  +            if (output.length() > 0) {
  +                project.log(output, Project.MSG_WARN);
  +            }
  +        }
  +        else {
  +            project.log(out.toString().trim(), Project.MSG_ERR);
  +
  +            throw new BuildException("Compile failed");
           }
       }