Author: stevel Date: Fri May 18 07:20:10 2007 New Revision: 539477 URL: http://svn.apache.org/viewvc?view=rev&rev=539477 Log: Logger work. The main change is the new BigProjectLogger that makes reading the results of very big chained/nested projects manageable.
Some pulling up of helper methods into DefaultLogger, and a bit of cleanup there; plus the appopriate documentation changes Added: ant/core/trunk/src/main/org/apache/tools/ant/listener/BigProjectLogger.java Modified: ant/core/trunk/WHATSNEW ant/core/trunk/docs/manual/listeners.html ant/core/trunk/src/main/org/apache/tools/ant/DefaultLogger.java ant/core/trunk/src/main/org/apache/tools/ant/NoBannerLogger.java ant/core/trunk/src/main/org/apache/tools/ant/listener/AnsiColorLogger.java ant/core/trunk/src/main/org/apache/tools/ant/listener/TimestampedLogger.java Modified: ant/core/trunk/WHATSNEW URL: http://svn.apache.org/viewvc/ant/core/trunk/WHATSNEW?view=diff&rev=539477&r1=539476&r2=539477 ============================================================================== --- ant/core/trunk/WHATSNEW (original) +++ ant/core/trunk/WHATSNEW Fri May 18 07:20:10 2007 @@ -148,6 +148,8 @@ <comment> nested element as nested text instead of using the 'value' attribute. +* A new logger, BigProjectLogger, lists the project name with every target + Changes from Ant 1.6.5 to Ant 1.7.0 =================================== Modified: ant/core/trunk/docs/manual/listeners.html URL: http://svn.apache.org/viewvc/ant/core/trunk/docs/manual/listeners.html?view=diff&rev=539477&r1=539476&r2=539477 ============================================================================== --- ant/core/trunk/docs/manual/listeners.html (original) +++ ant/core/trunk/docs/manual/listeners.html Fri May 18 07:20:10 2007 @@ -44,13 +44,19 @@ <li>message logged</li> </ul> +<p> + These are used internally for various recording and housekeeping operations, + however new listeners may registered on the command line through the <code>-listener</code> + argument. +</p> + <h3><a name="Loggers">Loggers</a></h3> <p>Loggers extend the capabilities of listeners and add the following features:</p> <ul> <li>Receives a handle to the standard output and error print streams and - therefore can log information to the console or the -logfile specified file.</li> + therefore can log information to the console or the <code>-logfile</code> specified file.</li> <li>Logging level (-quiet, -verbose, -debug) aware</li> <li>Emacs-mode aware</li> </ul> @@ -104,7 +110,11 @@ <td width="33%">Prints the time that a build finished</td> <td width="34%">BuildLogger</td> </tr> - + <tr> + <td width="33%"><code><a href="#BigProjectLogger">org.apache.tools.ant.BigProjectLogger</a></code></td> + <td width="33%">Prints the project name every target</td> + <td width="34%">BuildLogger</td> + </tr> </table> <h3><a name="DefaultLogger">DefaultLogger</a></h3> @@ -235,7 +245,7 @@ color codes. It works on XTerm, ETerm, Win9x Console (with ANSI.SYS loaded.), etc.</p> <p><Strong>NOTE:</Strong> -It doesn't work on WinNT even when a COMMAND.COM console loaded with +It doesn't work on WinNT and successors, even when a COMMAND.COM console loaded with ANSI.SYS is used.</p> <p>If the user wishes to override the default colors with custom ones, a file containing zero or more of the @@ -318,7 +328,7 @@ </blockquote> -<p>To use Log4j you will need the Log4j jar file and a 'log4j.properties' +<p>To use Log4j you will need the Log4j JAR file and a 'log4j.properties' configuration file. Both should be placed somewhere in your Ant classpath. If the log4j.properties is in your project root folder you can add this with <i>-lib</i> option:</p> @@ -386,6 +396,7 @@ <pre> BUILD SUCCESSFUL - at 16/08/05 16:24 </pre> +<p>To use this listener, use the command:</p> <blockquote> @@ -393,6 +404,63 @@ </blockquote> +<h3><a name="BigProjectLogger">BigProjectLogger</a></h3> + +<p> + This logger is designed to make examining the logs of a big build easier, + especially those run under continuous integration tools. It +</p> +<ol> + <li>When entering a child project, prints its name and directory</li> + <li>When exiting a child project, prints its name</li> + <li>Includes the name of the project when printing a target</li> + <li>Omits logging the names of all targets that have no direct task output</li> + <li>Includes the build finished timestamp of the TimeStamp logger</li> +</ol> +<p> + This is useful when using <subant> to build a large project + from many smaller projects -the output shows which particular + project is building. Here is an example in which "clean" is being called + on all a number of child projects, only some of which perform work: +</p> +<pre> + +====================================================================== +Entering project "xunit" +In /home/ant/components/xunit +====================================================================== + +xunit.clean: + [delete] Deleting directory /home/ant/components/xunit/build + [delete] Deleting directory /home/ant/components/xunit/dist + +====================================================================== +Exiting project "xunit" +====================================================================== + +====================================================================== +Entering project "junit" +In /home/ant/components/junit +====================================================================== + +====================================================================== +Exiting project "junit" +====================================================================== +</pre> + +<p> + The entry and exit messages are very verbose in this example, but in + a big project compiling or testing many child components, the messages + are reduced to becoming clear delimiters of where different projects + are in charge -or more importantly, which project is failing. +</p> + +<p>To use this listener, use the command:</p> +<blockquote> + +<code>ant -logger org.apache.tools.ant.listener.BigProjectLogger</code> + +</blockquote> <h2><a name="dev">Writing your own</a></h2> @@ -402,8 +470,25 @@ <p>Notes:</p> <ul> - <li>A listener or logger should not write to standard output or error; Ant - captures these internally and may cause an infinite loop.</li> + <li> + A listener or logger should not write to standard output or error in the <code>messageLogged() method</code>; + Ant captures these internally and it will trigger an infinite loop. + </li> + <li> + Logging is synchronous; all listeners and loggers are called one after the other, with the build blocking until + the output is processed. Slow logging means a slow build. + </li> + <li>When a build is started, and <code>BuildListener.buildStarted(BuildEvent event)</code> is called, + the project is not fully functional. The build has started, yes, and the event.getProject() method call + returns the Project instance, but that project is initialized with JVM and ant properties, nor has it + parsed the build file yet. You cannot call <code>Project.getProperty()</code> for property lookup, or + <code>Project.getName()</code> to get the project name (it will return null). + </li> + <li> + Classes that implement <code>org.apache.tools.ant.SubBuildListener</code> receive notifications when child projects + start and stop. + </li> + </ul> Modified: ant/core/trunk/src/main/org/apache/tools/ant/DefaultLogger.java URL: http://svn.apache.org/viewvc/ant/core/trunk/src/main/org/apache/tools/ant/DefaultLogger.java?view=diff&rev=539477&r1=539476&r2=539477 ============================================================================== --- ant/core/trunk/src/main/org/apache/tools/ant/DefaultLogger.java (original) +++ ant/core/trunk/src/main/org/apache/tools/ant/DefaultLogger.java Fri May 18 07:20:10 2007 @@ -22,9 +22,12 @@ import java.io.IOException; import java.io.PrintStream; import java.io.StringReader; +import java.util.Date; +import java.text.DateFormat; import org.apache.tools.ant.util.DateUtils; import org.apache.tools.ant.util.StringUtils; +import org.apache.tools.ant.util.FileUtils; /** * Writes build events to a PrintStream. Currently, it @@ -251,9 +254,9 @@ tmp.append(label); label = tmp.toString(); + BufferedReader r = null; try { - BufferedReader r = - new BufferedReader( + r = new BufferedReader( new StringReader(event.getMessage())); String line = r.readLine(); boolean first = true; @@ -273,8 +276,14 @@ } catch (IOException e) { // shouldn't be possible message.append(label).append(event.getMessage()); + } finally { + if (r != null) { + FileUtils.close(r); + } } + } else { + //emacs mode or there is no task message.append(event.getMessage()); } Throwable ex = event.getException(); @@ -328,5 +337,28 @@ * @param message Message being logged. Should not be <code>null</code>. */ protected void log(String message) { + } + + /** + * Get the current time. + * @return the current time as a formatted string. + * @since Ant1.7.1 + */ + protected String getTimestamp() { + Date date = new Date(System.currentTimeMillis()); + DateFormat formatter = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT); + String finishTime = formatter.format(date); + return finishTime; + } + + /** + * Get the project name or null + * @param event the event + * @return the project that raised this event + * @since Ant1.7.1 + */ + protected String extractProjectName(BuildEvent event) { + Project project = event.getProject(); + return project!=null?project.getName():null; } } Modified: ant/core/trunk/src/main/org/apache/tools/ant/NoBannerLogger.java URL: http://svn.apache.org/viewvc/ant/core/trunk/src/main/org/apache/tools/ant/NoBannerLogger.java?view=diff&rev=539477&r1=539476&r2=539477 ============================================================================== --- ant/core/trunk/src/main/org/apache/tools/ant/NoBannerLogger.java (original) +++ ant/core/trunk/src/main/org/apache/tools/ant/NoBannerLogger.java Fri May 18 07:20:10 2007 @@ -49,7 +49,17 @@ * Must not be <code>null</code>. */ public void targetStarted(BuildEvent event) { - targetName = event.getTarget().getName(); + targetName = extractTargetName(event); + } + + /** + * Override point, extract the target name + * @param event the event to work on + * @return the target name to print + * @since Ant1.7.1 + */ + protected String extractTargetName(BuildEvent event) { + return event.getTarget().getName(); } /** Modified: ant/core/trunk/src/main/org/apache/tools/ant/listener/AnsiColorLogger.java URL: http://svn.apache.org/viewvc/ant/core/trunk/src/main/org/apache/tools/ant/listener/AnsiColorLogger.java?view=diff&rev=539477&r1=539476&r2=539477 ============================================================================== --- ant/core/trunk/src/main/org/apache/tools/ant/listener/AnsiColorLogger.java (original) +++ ant/core/trunk/src/main/org/apache/tools/ant/listener/AnsiColorLogger.java Fri May 18 07:20:10 2007 @@ -96,7 +96,7 @@ * 47 -> White * */ -public final class AnsiColorLogger extends DefaultLogger { +public class AnsiColorLogger extends DefaultLogger { // private static final int ATTR_NORMAL = 0; // private static final int ATTR_BRIGHT = 1; private static final int ATTR_DIM = 2; Added: ant/core/trunk/src/main/org/apache/tools/ant/listener/BigProjectLogger.java URL: http://svn.apache.org/viewvc/ant/core/trunk/src/main/org/apache/tools/ant/listener/BigProjectLogger.java?view=auto&rev=539477 ============================================================================== --- ant/core/trunk/src/main/org/apache/tools/ant/listener/BigProjectLogger.java (added) +++ ant/core/trunk/src/main/org/apache/tools/ant/listener/BigProjectLogger.java Fri May 18 07:20:10 2007 @@ -0,0 +1,171 @@ +/* + * Copyright 2007 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.tools.ant.listener; + +import org.apache.tools.ant.BuildEvent; +import org.apache.tools.ant.NoBannerLogger; +import org.apache.tools.ant.SubBuildListener; +import org.apache.tools.ant.Project; +import org.apache.tools.ant.util.StringUtils; + +import java.io.File; + +/** + * This is a special logger that is designed to make it easier to work with big projects, those that use imports and + * subant to build complex systems. + * + * @since Ant1.7.1 + */ + +public class BigProjectLogger extends NoBannerLogger implements SubBuildListener { + + /** + * Header string for the log. + * [EMAIL PROTECTED] + */ + public static final String HEADER="======================================================================"; + /** + * Footer string for the log. + * [EMAIL PROTECTED] + */ + public static final String FOOTER=HEADER; + + /** + * This is an override point: the message that indicates whether a build failed. Subclasses can change/enhance the + * message. + * + * @return The classic "BUILD FAILED" plus a timestamp + */ + protected String getBuildFailedMessage() { + return super.getBuildFailedMessage() + TimestampedLogger.SPACER + getTimestamp(); + } + + /** + * This is an override point: the message that indicates that a build succeeded. Subclasses can change/enhance the + * message. + * + * @return The classic "BUILD SUCCESSFUL" plus a timestamp + */ + protected String getBuildSuccessfulMessage() { + return super.getBuildSuccessfulMessage() + TimestampedLogger.SPACER + getTimestamp(); + } + + + /** + * [EMAIL PROTECTED] + * + * @param event + */ + public void buildStarted(BuildEvent event) { + super.buildStarted(event); + subBuildStarted(event); + } + + /** + * [EMAIL PROTECTED] + * + * @param event + */ + public void buildFinished(BuildEvent event) { + subBuildFinished(event); + super.buildFinished(event); + } + + /** + * Override point, extract the target name + * + * @param event the event to work on + * @return the target name -including the owning project name (if non-null) + */ + protected String extractTargetName(BuildEvent event) { + String targetName = event.getTarget().getName(); + String projectName = extractProjectName(event); + if (projectName != null && targetName != null) { + return projectName + '.' + targetName; + } else { + return targetName; + } + } + + + /** + * [EMAIL PROTECTED] + * + * @param event An event with any relevant extra information. Must not be <code>null</code>. + */ + public void subBuildStarted(BuildEvent event) { + String name = extractNameOrDefault(event); + Project project = event.getProject(); + + File base = project == null ? null : project.getBaseDir(); + String path = base == null ? + "With no base directory" + : "In " + base.getAbsolutePath(); + printMessage(StringUtils.LINE_SEP + getHeader() + + StringUtils.LINE_SEP +"Entering project " + name + + StringUtils.LINE_SEP + path + +StringUtils.LINE_SEP + getFooter(), + out, + event.getPriority()); + } + + /** + * Get the name of an event + * + * @param event the event name + * @return the name or a default string + */ + protected String extractNameOrDefault(BuildEvent event) { + String name = extractProjectName(event); + if (name == null) { + name = ""; + } else { + name = '"'+name+'"'; + } + return name; + } + + /** [EMAIL PROTECTED] */ + public void subBuildFinished(BuildEvent event) { + String name = extractNameOrDefault(event); + String failed = event.getException() != null ? "failing " : ""; + printMessage(StringUtils.LINE_SEP + getHeader() + + StringUtils.LINE_SEP + "Exiting " + failed + "project " + + name + + StringUtils.LINE_SEP + getFooter(), + out, + event.getPriority()); + } + + /** + * Override point: return the header string for the entry/exit message + * @return the header string + */ + protected String getHeader() { + return HEADER; + } + + /** + * Override point: return the footer string for the entry/exit message + * @return the footer string + */ + protected String getFooter() { + return FOOTER; + } + +} Modified: ant/core/trunk/src/main/org/apache/tools/ant/listener/TimestampedLogger.java URL: http://svn.apache.org/viewvc/ant/core/trunk/src/main/org/apache/tools/ant/listener/TimestampedLogger.java?view=diff&rev=539477&r1=539476&r2=539477 ============================================================================== --- ant/core/trunk/src/main/org/apache/tools/ant/listener/TimestampedLogger.java (original) +++ ant/core/trunk/src/main/org/apache/tools/ant/listener/TimestampedLogger.java Fri May 18 07:20:10 2007 @@ -31,14 +31,14 @@ /** * what appears between the old message and the new */ - private static final String SPACER = " - at "; + public static final String SPACER = " - at "; /** * This is an override point: the message that indicates whether a build failed. * Subclasses can change/enhance the message. * - * @return The classic "BUILD FAILED" + * @return The classic "BUILD FAILED" plus a timestamp */ protected String getBuildFailedMessage() { return super.getBuildFailedMessage() + SPACER + getTimestamp(); @@ -48,20 +48,10 @@ * This is an override point: the message that indicates that a build succeeded. * Subclasses can change/enhance the message. * - * @return The classic "BUILD SUCCESSFUL" + * @return The classic "BUILD SUCCESSFUL" plus a timestamp */ protected String getBuildSuccessfulMessage() { return super.getBuildSuccessfulMessage() + SPACER + getTimestamp(); } - /** - * Get the current time. - * @return the current time as a formatted string. - */ - protected String getTimestamp() { - Date date = new Date(System.currentTimeMillis()); - DateFormat formatter = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT); - String finishTime = formatter.format(date); - return finishTime; - } } --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]