diff --git a/WHATSNEW b/WHATSNEW
index a542e16f9..f88245a2b 100644
--- a/WHATSNEW
+++ b/WHATSNEW
@@ -148,6 +148,8 @@ Other changes:
+ These are used internally for various recording and housekeeping operations,
+ however new listeners may registered on the command line through the -listener
+ argument.
+
Loggers extend the capabilities of listeners and add the following features:
-logfile
specified file.
org.apache.tools.ant.BigProjectLogger
NOTE: -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.
If the user wishes to override the default colors with custom ones, a file containing zero or more of the @@ -318,7 +328,7 @@ corresponding Log4j level.
-To use Log4j you will need the Log4j jar file and a 'log4j.properties' +
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 -lib option:
@@ -386,6 +396,7 @@ is declared at all.BUILD SUCCESSFUL - at 16/08/05 16:24+
To use this listener, use the command:
@@ -393,6 +404,63 @@ is declared at all.+
+ This logger is designed to make examining the logs of a big build easier, + especially those run under continuous integration tools. It +
++ 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: +
++ +====================================================================== +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" +====================================================================== ++ +
+ 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. +
+ +To use this listener, use the command:
+
+
+ant -logger org.apache.tools.ant.listener.BigProjectLogger
+
+
Notes:
messageLogged() method
;
+ Ant captures these internally and it will trigger an infinite loop.
+ BuildListener.buildStarted(BuildEvent event)
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 Project.getProperty()
for property lookup, or
+ Project.getName()
to get the project name (it will return null).
+ org.apache.tools.ant.SubBuildListener
receive notifications when child projects
+ start and stop.
+ null
.
*/
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();
}
/**
diff --git a/src/main/org/apache/tools/ant/listener/AnsiColorLogger.java b/src/main/org/apache/tools/ant/listener/AnsiColorLogger.java
index b01317b17..39c96cce3 100644
--- a/src/main/org/apache/tools/ant/listener/AnsiColorLogger.java
+++ b/src/main/org/apache/tools/ant/listener/AnsiColorLogger.java
@@ -96,7 +96,7 @@ import org.apache.tools.ant.Project;
* 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;
diff --git a/src/main/org/apache/tools/ant/listener/BigProjectLogger.java b/src/main/org/apache/tools/ant/listener/BigProjectLogger.java
new file mode 100644
index 000000000..c7d45c232
--- /dev/null
+++ b/src/main/org/apache/tools/ant/listener/BigProjectLogger.java
@@ -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.
+ * {@value}
+ */
+ public static final String HEADER="======================================================================";
+ /**
+ * Footer string for the log.
+ * {@value}
+ */
+ 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();
+ }
+
+
+ /**
+ * {@inheritDoc}
+ *
+ * @param event
+ */
+ public void buildStarted(BuildEvent event) {
+ super.buildStarted(event);
+ subBuildStarted(event);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @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;
+ }
+ }
+
+
+ /**
+ * {@inheritDoc}
+ *
+ * @param event An event with any relevant extra information. Must not be null
.
+ */
+ 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;
+ }
+
+ /** {@inheritDoc} */
+ 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;
+ }
+
+}
diff --git a/src/main/org/apache/tools/ant/listener/TimestampedLogger.java b/src/main/org/apache/tools/ant/listener/TimestampedLogger.java
index 33a932a61..eab9a41a5 100644
--- a/src/main/org/apache/tools/ant/listener/TimestampedLogger.java
+++ b/src/main/org/apache/tools/ant/listener/TimestampedLogger.java
@@ -31,14 +31,14 @@ public class TimestampedLogger extends DefaultLogger {
/**
* 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 @@ public class TimestampedLogger extends DefaultLogger {
* 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;
- }
}