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");
}
}