- Moved the remaining System.out calls to the DefaultLogger - Cleaned up the default output - Added System.exit to main() tools can still invoke the runBuild method without an exit being called. - Changed javac task logging to stream out a line at a time Submitted by: Matt Foemmel <mpfoemme@ThoughtWorks.com> git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@267725 13f79535-47bb-0310-9956-ffa450edef68master
| @@ -62,8 +62,11 @@ import java.io.*; | |||||
| * any messages that get logged. | * any messages that get logged. | ||||
| */ | */ | ||||
| public class DefaultLogger implements BuildListener { | public class DefaultLogger implements BuildListener { | ||||
| private static int LEFT_COLUMN_SIZE = 12; | |||||
| private PrintStream out; | private PrintStream out; | ||||
| private int msgOutputLevel; | private int msgOutputLevel; | ||||
| private long startTime; | |||||
| /** | /** | ||||
| * Constructs a new logger which will write to the specified | * Constructs a new logger which will write to the specified | ||||
| @@ -75,16 +78,47 @@ public class DefaultLogger implements BuildListener { | |||||
| this.msgOutputLevel = msgOutputLevel; | 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) { | public void targetStarted(BuildEvent event) { | ||||
| if (msgOutputLevel <= Project.MSG_INFO) { | 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 taskStarted(BuildEvent event) {} | ||||
| public void taskFinished(BuildEvent event) {} | public void taskFinished(BuildEvent event) {} | ||||
| @@ -101,11 +135,31 @@ public class DefaultLogger implements BuildListener { | |||||
| if (pos != -1) { | if (pos != -1) { | ||||
| name = name.substring(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 | // Print the message | ||||
| out.println(event.getMessage()); | out.println(event.getMessage()); | ||||
| } | } | ||||
| } | } | ||||
| } | |||||
| 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"; | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -103,7 +103,13 @@ public class Main { | |||||
| * @param args Command line args. | * @param args Command line args. | ||||
| */ | */ | ||||
| public static void main(String[] 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 { | protected Main(String[] args) throws BuildException { | ||||
| @@ -194,7 +200,7 @@ public class Main { | |||||
| // if it's no other arg, it may be the target | // if it's no other arg, it may be the target | ||||
| targets.addElement(arg); | targets.addElement(arg); | ||||
| } | } | ||||
| } | } | ||||
| // make sure buildfile exists | // make sure buildfile exists | ||||
| @@ -224,10 +230,9 @@ public class Main { | |||||
| if (!readyToRun) { | if (!readyToRun) { | ||||
| return; | return; | ||||
| } | } | ||||
| // track when we started | // track when we started | ||||
| long startTime = System.currentTimeMillis(); | |||||
| if (msgOutputLevel >= Project.MSG_INFO) { | if (msgOutputLevel >= Project.MSG_INFO) { | ||||
| System.out.println("Buildfile: " + buildFile); | System.out.println("Buildfile: " + buildFile); | ||||
| } | } | ||||
| @@ -235,21 +240,24 @@ public class Main { | |||||
| Project project = new Project(); | Project project = new Project(); | ||||
| addBuildListeners(project); | addBuildListeners(project); | ||||
| project.fireBuildStarted(); | 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 { | 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 { | try { | ||||
| Class.forName("javax.xml.parsers.SAXParserFactory"); | Class.forName("javax.xml.parsers.SAXParserFactory"); | ||||
| ProjectHelper.configureProject(project, buildFile); | ProjectHelper.configureProject(project, buildFile); | ||||
| @@ -260,40 +268,25 @@ public class Main { | |||||
| } catch (NullPointerException npe) { | } catch (NullPointerException npe) { | ||||
| throw new BuildException("No JAXP compliant XML parser found. See http://java.sun.com/xml for the\nreference implementation.", 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); | 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() { | private static void printVersion() { | ||||
| try { | try { | ||||
| Properties props = new Properties(); | Properties props = new Properties(); | ||||
| InputStream in = | |||||
| InputStream in = | |||||
| Main.class.getResourceAsStream("/org/apache/tools/ant/version.txt"); | Main.class.getResourceAsStream("/org/apache/tools/ant/version.txt"); | ||||
| props.load(in); | props.load(in); | ||||
| in.close(); | in.close(); | ||||
| String lSep = System.getProperty("line.separator"); | String lSep = System.getProperty("line.separator"); | ||||
| StringBuffer msg = new StringBuffer(); | StringBuffer msg = new StringBuffer(); | ||||
| msg.append("Ant version "); | msg.append("Ant version "); | ||||
| @@ -261,7 +261,7 @@ public class Project { | |||||
| this.baseDir = baseDir; | this.baseDir = baseDir; | ||||
| setProperty( "basedir", baseDir.getAbsolutePath()); | setProperty( "basedir", baseDir.getAbsolutePath()); | ||||
| String msg = "Project base dir set to: " + baseDir; | String msg = "Project base dir set to: " + baseDir; | ||||
| log(msg, MSG_INFO); | |||||
| log(msg, MSG_VERBOSE); | |||||
| } | } | ||||
| public File getBaseDir() { | public File getBaseDir() { | ||||
| @@ -407,17 +407,8 @@ public class Project { | |||||
| public void executeTargets(Vector targetNames) throws BuildException { | public void executeTargets(Vector targetNames) throws BuildException { | ||||
| Throwable error = null; | 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)); | |||||
| } | } | ||||
| } | } | ||||
| @@ -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 | |||||
| * <http://www.apache.org/>. | |||||
| * | |||||
| */ | |||||
| 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: | |||||
| * <pre>System.setOut(new PrintStream(new TaskOutputStream(project, Project.MSG_INFO)));</pre> | |||||
| * | |||||
| * @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(); | |||||
| } | |||||
| } | |||||
| @@ -92,7 +92,7 @@ public class Javac extends MatchingTask { | |||||
| * Integer returned by the "Modern" jdk1.3 compiler to indicate success. | * Integer returned by the "Modern" jdk1.3 compiler to indicate success. | ||||
| */ | */ | ||||
| private static final int | private static final int | ||||
| MODERN_COMPILER_SUCCESS = 0; | |||||
| MODERN_COMPILER_SUCCESS = 0; | |||||
| private File srcDir; | private File srcDir; | ||||
| private File destDir; | private File destDir; | ||||
| @@ -237,10 +237,10 @@ public class Javac extends MatchingTask { | |||||
| // copy the support files | // copy the support files | ||||
| if (filecopyList.size() > 0) { | 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.", | "Use the copydir task to copy support files explicitly.", | ||||
| Project.MSG_WARN); | Project.MSG_WARN); | ||||
| project.log("Copying " + filecopyList.size() + | project.log("Copying " + filecopyList.size() + | ||||
| " support files to " + destDir.getAbsolutePath()); | " support files to " + destDir.getAbsolutePath()); | ||||
| Enumeration enum = filecopyList.keys(); | Enumeration enum = filecopyList.keys(); | ||||
| @@ -427,17 +427,10 @@ public class Javac extends MatchingTask { | |||||
| // provide the compiler a different message sink - namely our own | // provide the compiler a different message sink - namely our own | ||||
| ByteArrayOutputStream out = new ByteArrayOutputStream(); | 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"); | throw new BuildException("Compile failed"); | ||||
| } | } | ||||
| } | } | ||||
| @@ -505,28 +498,27 @@ public class Javac extends MatchingTask { | |||||
| project.log(niceSourceList.toString(), project.MSG_VERBOSE); | 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(); | //com.sun.tools.javac.Main compiler = new com.sun.tools.javac.Main(); | ||||
| //if (compiler.compile(args) != 0) { | //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); | |||||
| } | } | ||||
| } | } | ||||
| /** | /** | ||||