diff --git a/src/main/org/apache/tools/ant/DefaultLogger.java b/src/main/org/apache/tools/ant/DefaultLogger.java index bdcb22b1e..f2c8db266 100644 --- a/src/main/org/apache/tools/ant/DefaultLogger.java +++ b/src/main/org/apache/tools/ant/DefaultLogger.java @@ -62,8 +62,11 @@ import java.io.*; * any messages that get logged. */ public class DefaultLogger implements BuildListener { + private static int LEFT_COLUMN_SIZE = 12; + private PrintStream out; private int msgOutputLevel; + private long startTime; /** * Constructs a new logger which will write to the specified @@ -75,16 +78,47 @@ public class DefaultLogger implements BuildListener { this.msgOutputLevel = msgOutputLevel; } - public void buildStarted(BuildEvent event) {} - public void buildFinished(BuildEvent event) {} + public void buildStarted(BuildEvent event) { + startTime = System.currentTimeMillis(); + } + + /** + * Prints whether the build succeeded or failed, and + * any errors the occured during the build. + */ + public void buildFinished(BuildEvent event) { + Throwable error = event.getException(); + + if (error == null) { + out.println("\nBUILD SUCCESSFUL"); + } + else { + out.println("\nBUILD FAILED\n"); + + if (error instanceof BuildException) { + out.println(error.toString()); + + Throwable nested = ((BuildException)error).getException(); + if (nested != null) { + nested.printStackTrace(out); + } + } + else { + error.printStackTrace(out); + } + } + + out.println("\nTotal time: " + formatTime(System.currentTimeMillis() - startTime)); + } public void targetStarted(BuildEvent event) { if (msgOutputLevel <= Project.MSG_INFO) { - out.println("Executing Target: " + event.getTarget().getName()); + out.println("\n" + event.getTarget().getName() + ":"); } } - public void targetFinished(BuildEvent event) {} + public void targetFinished(BuildEvent event) { + } public void taskStarted(BuildEvent event) {} public void taskFinished(BuildEvent event) {} @@ -101,11 +135,31 @@ public class DefaultLogger implements BuildListener { if (pos != -1) { name = name.substring(pos + 1); } - out.print("[" + name + "] "); + + String msg = "[" + name + "] "; + for (int i = 0; i < (LEFT_COLUMN_SIZE - msg.length()); i++) { + out.print(" "); + } + out.print(msg); } // Print the message out.println(event.getMessage()); } } -} \ No newline at end of file + + 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"; + } + + } + +} diff --git a/src/main/org/apache/tools/ant/Main.java b/src/main/org/apache/tools/ant/Main.java index 2eb4b1da4..816b6a2f8 100644 --- a/src/main/org/apache/tools/ant/Main.java +++ b/src/main/org/apache/tools/ant/Main.java @@ -103,7 +103,13 @@ public class Main { * @param args Command line args. */ public static void main(String[] args) { - new Main(args).runBuild(); + try { + new Main(args).runBuild(); + System.exit(0); + } + catch(Throwable exc) { + System.exit(1); + } } protected Main(String[] args) throws BuildException { @@ -194,7 +200,7 @@ public class Main { // if it's no other arg, it may be the target targets.addElement(arg); } - + } // make sure buildfile exists @@ -224,10 +230,9 @@ public class Main { if (!readyToRun) { return; } - + // track when we started - long startTime = System.currentTimeMillis(); if (msgOutputLevel >= Project.MSG_INFO) { System.out.println("Buildfile: " + buildFile); } @@ -235,21 +240,24 @@ public class Main { Project project = new Project(); addBuildListeners(project); project.fireBuildStarted(); - project.init(); - - // set user-define properties - Enumeration e = definedProps.keys(); - while (e.hasMoreElements()) { - String arg = (String)e.nextElement(); - String value = (String)definedProps.get(arg); - project.setUserProperty(arg, value); - } - project.setUserProperty( "ant.file" , buildFile.getAbsolutePath() ); + Throwable error = null; - // first use the ProjectHelper to create the project object - // from the given build file. try { + project.init(); + + // set user-define properties + Enumeration e = definedProps.keys(); + while (e.hasMoreElements()) { + String arg = (String)e.nextElement(); + String value = (String)definedProps.get(arg); + project.setUserProperty(arg, value); + } + + project.setUserProperty( "ant.file" , buildFile.getAbsolutePath() ); + + // first use the ProjectHelper to create the project object + // from the given build file. try { Class.forName("javax.xml.parsers.SAXParserFactory"); ProjectHelper.configureProject(project, buildFile); @@ -260,40 +268,25 @@ public class Main { } catch (NullPointerException npe) { throw new BuildException("No JAXP compliant XML parser found. See http://java.sun.com/xml for the\nreference implementation.", npe); } - } catch (BuildException be) { - System.out.println("\nBUILD CONFIG ERROR\n"); - System.out.println(be.getMessage()); - if (be.getException() == null) { - System.out.println(be.toString()); - } else { - be.getException().printStackTrace(); - } - throw be; - } - // make sure that we have a target to execute - if (targets.size() == 0) { - targets.addElement(project.getDefaultTarget()); - } + // make sure that we have a target to execute + if (targets.size() == 0) { + targets.addElement(project.getDefaultTarget()); + } - // actually do some work - try { + // actually do some work project.executeTargets(targets); - } catch (BuildException be) { - String msg = "\nBUILD FATAL ERROR\n\n"; - System.out.println(msg + be.toString()); - if (msgOutputLevel > Project.MSG_INFO) { - be.printStackTrace(); - } - throw be; } - - // track our stop time and let the user know how long things took. - long finishTime = System.currentTimeMillis(); - long elapsedTime = finishTime - startTime; - if (msgOutputLevel >= Project.MSG_INFO) { - System.out.println("Completed in " + (elapsedTime/1000) - + " seconds"); + catch(RuntimeException exc) { + error = exc; + throw exc; + } + catch(Error err) { + error = err; + throw err; + } + finally { + project.fireBuildFinished(error); } } @@ -344,11 +337,11 @@ public class Main { private static void printVersion() { try { Properties props = new Properties(); - InputStream in = + InputStream in = Main.class.getResourceAsStream("/org/apache/tools/ant/version.txt"); props.load(in); in.close(); - + String lSep = System.getProperty("line.separator"); StringBuffer msg = new StringBuffer(); msg.append("Ant version "); diff --git a/src/main/org/apache/tools/ant/Project.java b/src/main/org/apache/tools/ant/Project.java index a2cac7336..2e2f583db 100644 --- a/src/main/org/apache/tools/ant/Project.java +++ b/src/main/org/apache/tools/ant/Project.java @@ -261,7 +261,7 @@ public class Project { this.baseDir = baseDir; setProperty( "basedir", baseDir.getAbsolutePath()); String msg = "Project base dir set to: " + baseDir; - log(msg, MSG_INFO); + log(msg, MSG_VERBOSE); } public File getBaseDir() { @@ -407,17 +407,8 @@ public class Project { 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); + for (int i = 0; i < targetNames.size(); i++) { + executeTarget((String)targetNames.elementAt(i)); } } diff --git a/src/main/org/apache/tools/ant/TaskOutputStream.java b/src/main/org/apache/tools/ant/TaskOutputStream.java new file mode 100644 index 000000000..fa8f94a76 --- /dev/null +++ b/src/main/org/apache/tools/ant/TaskOutputStream.java @@ -0,0 +1,118 @@ +/* + * 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 + * . + * + */ + +package org.apache.tools.ant.taskdefs; + +import org.apache.tools.ant.*; +import java.io.*; + +/** + * Redirects text written to a stream thru the standard + * ant logging mechanism. This class is useful for integrating + * with tools that write to System.out and System.err. For example, + * the following will cause all text written to System.out to be + * logged with "info" priority: + *
System.setOut(new PrintStream(new TaskOutputStream(project, Project.MSG_INFO)));
+ * + * @author James Duncan Davidson (duncan@x180.com) + */ + +public class TaskOutputStream extends OutputStream { + + private Project project; + private StringBuffer line; + private int msgOutputLevel; + + /** + * Constructs a new JavacOutputStream with the given project + * as the output source for messages. + */ + + TaskOutputStream(Project project, int msgOutputLevel) { + this.project = project; + this.msgOutputLevel = msgOutputLevel; + + line = new StringBuffer(); + } + + /** + * Write a character to the output stream. This method looks + * to make sure that there isn't an error being reported and + * will flush each line of input out to the project's log stream. + */ + + public void write(int c) throws IOException { + char cc = (char)c; + if (cc == '\r' || cc == '\n') { + // line feed + if (line.length() > 0) { + processLine(); + } + } else { + line.append(cc); + } + } + + /** + * Processes a line of input and determines if an error occured. + */ + + private void processLine() { + String s = line.toString(); + project.log(s, msgOutputLevel); + line = new StringBuffer(); + } +} + diff --git a/src/main/org/apache/tools/ant/taskdefs/Javac.java b/src/main/org/apache/tools/ant/taskdefs/Javac.java index 0b63a4535..1890484d0 100644 --- a/src/main/org/apache/tools/ant/taskdefs/Javac.java +++ b/src/main/org/apache/tools/ant/taskdefs/Javac.java @@ -92,7 +92,7 @@ public class Javac extends MatchingTask { * Integer returned by the "Modern" jdk1.3 compiler to indicate success. */ private static final int - MODERN_COMPILER_SUCCESS = 0; + MODERN_COMPILER_SUCCESS = 0; private File srcDir; private File destDir; @@ -237,10 +237,10 @@ public class Javac extends MatchingTask { // copy the support files if (filecopyList.size() > 0) { - project.log("The implicit copying of support files by javac has been deprecated. " + + project.log("The implicit copying of support files by javac has been deprecated. " + "Use the copydir task to copy support files explicitly.", Project.MSG_WARN); - + project.log("Copying " + filecopyList.size() + " support files to " + destDir.getAbsolutePath()); Enumeration enum = filecopyList.keys(); @@ -427,17 +427,10 @@ public class Javac extends MatchingTask { // provide the compiler a different message sink - namely our own ByteArrayOutputStream out = new ByteArrayOutputStream(); - sun.tools.javac.Main compiler = new sun.tools.javac.Main(out, "javac"); - - 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); + sun.tools.javac.Main compiler = + new sun.tools.javac.Main(new TaskOutputStream(project, Project.MSG_WARN), "javac"); + if (!compiler.compile(args)) { throw new BuildException("Compile failed"); } } @@ -505,28 +498,27 @@ public class Javac extends MatchingTask { project.log(niceSourceList.toString(), project.MSG_VERBOSE); - // This won't build under JDK1.2.2 because the new compiler - // doesn't exist there. + // This won't build under JDK1.2.2 because the new compiler + // doesn't exist there. //com.sun.tools.javac.Main compiler = new com.sun.tools.javac.Main(); //if (compiler.compile(args) != 0) { - // Use reflection to be able to build on all JDKs >= 1.1: - try { - Class c = Class.forName ("com.sun.tools.javac.Main"); - Object compiler = c.newInstance (); - Method compile = c.getMethod ("compile", - new Class [] {(new String [] {}).getClass ()}); - int result = ((Integer) compile.invoke - (compiler, new Object [] {args})) .intValue (); - if (result != MODERN_COMPILER_SUCCESS) { - String msg = - "Compile failed, messages should have been provided."; - throw new BuildException(msg); - } - } catch (Exception ex) { - throw new BuildException (ex); + // Use reflection to be able to build on all JDKs >= 1.1: + try { + Class c = Class.forName ("com.sun.tools.javac.Main"); + Object compiler = c.newInstance (); + Method compile = c.getMethod ("compile", + new Class [] {(new String [] {}).getClass ()}); + int result = ((Integer) compile.invoke + (compiler, new Object [] {args})) .intValue (); + if (result != MODERN_COMPILER_SUCCESS) { + String msg = + "Compile failed, messages should have been provided."; + throw new BuildException(msg); + } + } catch (Exception ex) { + throw new BuildException (ex); } - } /**