messages based on the message level. git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@271022 13f79535-47bb-0310-9956-ffa450edef68master
@@ -129,8 +129,10 @@ Other changes: | |||
* <fail> no supports builds to fail based on conditions via if and | |||
unless attributes. | |||
* Ant now comes with a BuildLogger implementation that can send emails | |||
containing a log of the build process (MailLogger). | |||
* Ant now comes with two new BuildLogger implementations - one that | |||
can send emails containing a log of the build process (MailLogger); | |||
the other that colorizes the output based on message levels using | |||
ANSI color code escape sequences (AnsiColorLogger). | |||
* A "package" mapper type has been added to allow package directory | |||
names replaced with the dotted form. | |||
@@ -10,7 +10,7 @@ | |||
<h2><a name="Overview">Overview</a></h2> | |||
<p>Ant has two related features to allow the build process to be monitored: | |||
<p>Ant has two related features to allow the build process to be monitored: | |||
listeners and loggers.</p> | |||
<h3><a name="Listeners">Listeners</a></h3> | |||
@@ -32,7 +32,7 @@ listeners and loggers.</p> | |||
<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 | |||
<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> | |||
<li>Logging level (-quiet, -verbose, -debug) aware</li> | |||
<li>Emacs-mode aware</li> | |||
@@ -48,7 +48,7 @@ listeners and loggers.</p> | |||
</tr> | |||
<tr> | |||
<td width="33%"><code><a href="#DefaultLogger">org.apache.tools.ant.DefaultLogger</a></code></td> | |||
<td width="33%">The logger used implicitly unless overridden with the | |||
<td width="33%">The logger used implicitly unless overridden with the | |||
<code>-logger</code> command-line switch.</td> | |||
<td width="34%">BuildLogger</td> | |||
</tr> | |||
@@ -61,10 +61,16 @@ listeners and loggers.</p> | |||
<tr> | |||
<td width="33%"><code><a href="#MailLogger"> | |||
org.apache.tools.ant.listener.MailLogger</a></code></td> | |||
<td width="33%">Extends DefaultLogger such that output is still generated | |||
<td width="33%">Extends DefaultLogger such that output is still generated | |||
the same, and when the build is finished an e-mail can be sent.</td> | |||
<td width="34%">BuildLogger</td> | |||
</tr> | |||
<tr> | |||
<td width="33%"><code><a href="#AnsiColorLogger"> | |||
org.apache.tools.ant.listener.AnsiColorLogger</a></code></td> | |||
<td width="33%">Colorifies the build output.</td> | |||
<td width="34%">BuildLogger</td> | |||
</tr> | |||
<tr> | |||
<td width="33%"><code><a href="#Log4jListener"> | |||
org.apache.tools.ant.listener.Log4jListener</a></code></td> | |||
@@ -99,8 +105,8 @@ listeners and loggers.</p> | |||
<h3><a name="MailLogger">MailLogger</a></h3> | |||
<p>The MailLogger captures all output logged through DefaultLogger (standard Ant | |||
output) and will send success and failure messages to unique e-mail lists, with | |||
<p>The MailLogger captures all output logged through DefaultLogger (standard Ant | |||
output) and will send success and failure messages to unique e-mail lists, with | |||
control for turning off success or failure messages individually.</p> | |||
<p>Properties controlling the operation of MailLogger:</p> | |||
<table border="1" cellspacing="1" width="100%" id="AutoNumber2"> | |||
@@ -161,22 +167,97 @@ control for turning off success or failure messages individually.</p> | |||
</blockquote> | |||
<h3><a name="AnsiColorLogger">AnsiColorLogger</a></h3> | |||
<p>The AnsiColorLogger adds color to the standard Ant output | |||
by prefixing and suffixing ANSI color code escape sequences to | |||
it. It is just an extension of <a href="#DefaultLogger">DefaultLogger</a> | |||
and hence provides all features that DefaultLogger does.</p> | |||
<p>AnsiColorLogger differentiates the output by assigning | |||
different colors depending upon the type of the message.</p> | |||
<p>If used with the -logfile option, the output file | |||
will contain all the necessary escape codes to | |||
display the text in colorized mode when displayed | |||
in the console using applications like cat, more, etc.</p> | |||
<p>This is designed to work on terminals that support ANSI | |||
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 | |||
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 | |||
custom color key-value pairs must be created. The recognized keys | |||
and their default values are shown below:</p><code><pre> | |||
AnsiColorLogger.ERROR_COLOR=2;31 | |||
AnsiColorLogger.WARNING_COLOR=2;35 | |||
AnsiColorLogger.INFO_COLOR=2;36 | |||
AnsiColorLogger.VERBOSE_COLOR=2;32 | |||
AnsiColorLogger.DEBUG_COLOR=2;34</pre></code> | |||
<p>Each key takes as value a color combination defined as | |||
<b>Attribute;Foreground;Background</b>. In the above example, background | |||
value has not been used.</p> | |||
<p>This file must be specfied as the value of a system variable | |||
named ant.logger.defaults and passed as an argument using the -D | |||
option to the <b>java</b> command that invokes the Ant application. | |||
An easy way to achieve this is to add -Dant.logger.defaults= | |||
<i>/path/to/your/file</i> to the ANT_OPTS environment variable. | |||
Ant's launching script recognizes this flag and will pass it to | |||
the java command appropriately.</p> | |||
<p>Format:</p><pre> | |||
AnsiColorLogger.*=Attribute;Foreground;Background | |||
Attribute is one of the following: | |||
0 -> Reset All Attributes (return to normal mode) | |||
1 -> Bright (Usually turns on BOLD) | |||
2 -> Dim | |||
3 -> Underline | |||
5 -> link | |||
7 -> Reverse | |||
8 -> Hidden | |||
Foreground is one of the following: | |||
30 -> Black | |||
31 -> Red | |||
32 -> Green | |||
33 -> Yellow | |||
34 -> Blue | |||
35 -> Magenta | |||
36 -> Cyan | |||
37 -> White | |||
Background is one of the following: | |||
40 -> Black | |||
41 -> Red | |||
42 -> Green | |||
43 -> Yellow | |||
44 -> Blue | |||
45 -> Magenta | |||
46 -> Cyan | |||
47 -> White</pre> | |||
<blockquote> | |||
<p><code>ant -logger org.apache.tools.ant.listener.AnsiColorLogger</code></p> | |||
</blockquote> | |||
<h3><a name="Log4jListener">Log4jListener</a></h3> | |||
<p>Passes build events to Log4j, using the full classname's of the generator of | |||
<p>Passes build events to Log4j, using the full classname's of the generator of | |||
each build event as the category:</p> | |||
<ul> | |||
<li>build started / build finished - org.apache.tools.ant.Project</li> | |||
<li>target started / target finished - org.apache.tools.ant.Target</li> | |||
<li>task started / task finished - the fully qualified classname of the task</li> | |||
<li>message logged - the classname of one of the above, so if a task logs a | |||
<li>message logged - the classname of one of the above, so if a task logs a | |||
message, its classname is the category used, and so on.</li> | |||
</ul> | |||
<p>All start events are logged as INFO. Finish events are either logged as | |||
INFO or ERROR depending on whether the build failed during that stage. Message | |||
events are logged according to their Ant logging level, mapping directly to a | |||
<p>All start events are logged as INFO. Finish events are either logged as | |||
INFO or ERROR depending on whether the build failed during that stage. Message | |||
events are logged according to their Ant logging level, mapping directly to a | |||
corresponding Log4j level.</p> | |||
<blockquote> | |||
@@ -187,7 +268,7 @@ corresponding Log4j level.</p> | |||
<h3><a name="XmlLogger">XmlLogger</a></h3> | |||
<p>Writes all build information out to an XML file named log.xml, or the value | |||
<p>Writes all build information out to an XML file named log.xml, or the value | |||
of the XmlLogger.file property if present.</p> | |||
<blockquote> | |||
@@ -198,18 +279,18 @@ of the XmlLogger.file property if present.</p> | |||
<h2><a name="dev">Writing your own</a></h2> | |||
<p>See the <a href="develop.html#buildevents">Build Events</a> section for | |||
<p>See the <a href="develop.html#buildevents">Build Events</a> section for | |||
developers.</p> | |||
<p>Notes:</p> | |||
<ul> | |||
<li>A listener or logger should not write to standard output or error - Ant | |||
<li>A listener or logger should not write to standard output or error - Ant | |||
captures these internally and may cause an infinite loop.</li> | |||
</ul> | |||
<hr> | |||
<p align="center">Copyright © 2001 Apache Software Foundation. All rights | |||
<p align="center">Copyright © 2002 Apache Software Foundation. All rights | |||
Reserved.</p> | |||
</body> | |||
@@ -164,9 +164,9 @@ public class DefaultLogger implements BuildLogger { | |||
String msg = message.toString(); | |||
if (error == null) { | |||
out.println(msg); | |||
printMessage(msg, out, Project.MSG_VERBOSE); | |||
} else { | |||
err.println(msg); | |||
printMessage(msg, err, Project.MSG_ERR); | |||
} | |||
log(msg); | |||
} | |||
@@ -174,7 +174,7 @@ public class DefaultLogger implements BuildLogger { | |||
public void targetStarted(BuildEvent event) { | |||
if (Project.MSG_INFO <= msgOutputLevel) { | |||
String msg = StringUtils.LINE_SEP + event.getTarget().getName() + ":"; | |||
out.println(msg); | |||
printMessage(msg, out, event.getPriority()); | |||
log(msg); | |||
} | |||
} | |||
@@ -186,8 +186,9 @@ public class DefaultLogger implements BuildLogger { | |||
public void taskFinished(BuildEvent event) {} | |||
public void messageLogged(BuildEvent event) { | |||
int priority = event.getPriority(); | |||
// Filter out messages based on priority | |||
if (event.getPriority() <= msgOutputLevel) { | |||
if (priority <= msgOutputLevel) { | |||
StringBuffer message = new StringBuffer(); | |||
// Print out the name of the task if we're in one | |||
@@ -205,10 +206,10 @@ public class DefaultLogger implements BuildLogger { | |||
message.append(event.getMessage()); | |||
String msg = message.toString(); | |||
if (event.getPriority() != Project.MSG_ERR) { | |||
out.println(msg); | |||
if (priority != Project.MSG_ERR) { | |||
printMessage(msg, out, priority); | |||
} else { | |||
err.println(msg); | |||
printMessage(msg, err, priority); | |||
} | |||
log(msg); | |||
} | |||
@@ -223,19 +224,24 @@ public class DefaultLogger implements BuildLogger { | |||
return Long.toString(minutes) + " minute" | |||
+ (minutes == 1 ? " " : "s ") | |||
+ Long.toString(seconds%60) + " second" | |||
+ (seconds%60 > 1 ? "s" : ""); | |||
+ (seconds%60 == 1 ? "" : "s"); | |||
} | |||
else { | |||
return Long.toString(seconds) + " second" | |||
+ (seconds%60 > 1 ? "s" : ""); | |||
+ (seconds%60 == 1 ? "" : "s"); | |||
} | |||
} | |||
protected void printMessage(final String message, | |||
final PrintStream stream, | |||
final int priority) { | |||
stream.println(message); | |||
} | |||
/** | |||
* Empty implementation which allows subclasses to receive the | |||
* same output that is generated here. | |||
*/ | |||
protected void log(String message) {} | |||
} |
@@ -0,0 +1,265 @@ | |||
/* | |||
* The Apache Software License, Version 1.1 | |||
* | |||
* Copyright (c) 2002 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", "Ant", 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.listener; | |||
import java.io.FileInputStream; | |||
import java.io.InputStream; | |||
import java.io.IOException; | |||
import java.io.PrintStream; | |||
import java.util.Properties; | |||
import org.apache.tools.ant.DefaultLogger; | |||
import org.apache.tools.ant.Project; | |||
/** | |||
* Uses ANSI Color Code Sequences to colorize messages | |||
* sent to the console. | |||
* | |||
* If used with the -logfile option, the output file | |||
* will contain all the necessary escape codes to | |||
* display the text in colorized mode when displayed | |||
* in the console using applications like cat, more, | |||
* etc. | |||
* | |||
* This is designed to work on terminals that support ANSI | |||
* color codes. It works on XTerm, ETerm, Mindterm, etc. | |||
* It also works on Win9x (with ANSI.SYS loaded.) | |||
* | |||
* NOTE: | |||
* It doesn't work on WinNT's COMMAND.COM even with | |||
* ANSI.SYS loaded. | |||
* | |||
* The default colors used for differentiating | |||
* the message levels can be changed by editing the | |||
* /org/apache/tools/ant/listener/defaults.properties | |||
* file. | |||
* This file contains 5 key/value pairs: | |||
* AnsiColorLogger.ERROR_COLOR=2;31 | |||
* AnsiColorLogger.WARNING_COLOR=2;35 | |||
* AnsiColorLogger.INFO_COLOR=2;36 | |||
* AnsiColorLogger.VERBOSE_COLOR=2;32 | |||
* AnsiColorLogger.DEBUG_COLOR=2;34 | |||
* | |||
* Another option is to pass a system variable named | |||
* ant.logger.defaults, with value set to the path of | |||
* the file that contains user defined Ansi Color | |||
* Codes, to the <B>java</B> command using -D option. | |||
* | |||
* To change these colors use the following chart: | |||
* | |||
* <B>ANSI COLOR LOGGER CONFIGURATION</B> | |||
* | |||
* Format for AnsiColorLogger.*= | |||
* Attribute;Foreground;Background | |||
* | |||
* Attribute is one of the following: | |||
* 0 -> Reset All Attributes (return to normal mode) | |||
* 1 -> Bright (Usually turns on BOLD) | |||
* 2 -> Dim | |||
* 3 -> Underline | |||
* 5 -> link | |||
* 7 -> Reverse | |||
* 8 -> Hidden | |||
* | |||
* Foreground is one of the following: | |||
* 30 -> Black | |||
* 31 -> Red | |||
* 32 -> Green | |||
* 33 -> Yellow | |||
* 34 -> Blue | |||
* 35 -> Magenta | |||
* 36 -> Cyan | |||
* 37 -> White | |||
* | |||
* Background is one of the following: | |||
* 40 -> Black | |||
* 41 -> Red | |||
* 42 -> Green | |||
* 43 -> Yellow | |||
* 44 -> Blue | |||
* 45 -> Magenta | |||
* 46 -> Cyan | |||
* 47 -> White | |||
* | |||
* @author <a href="mailto:umagesh@apache.org">Magesh Umasankar</a> | |||
*/ | |||
public final 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; | |||
private static final int ATTR_UNDERLINE = 3; | |||
private static final int ATTR_BLINK = 5; | |||
private static final int ATTR_REVERSE = 7; | |||
private static final int ATTR_HIDDEN = 8; | |||
private static final int FG_BLACK = 30; | |||
private static final int FG_RED = 31; | |||
private static final int FG_GREEN = 32; | |||
private static final int FG_YELLOW = 33; | |||
private static final int FG_BLUE = 34; | |||
private static final int FG_MAGENTA = 35; | |||
private static final int FG_CYAN = 36; | |||
private static final int FG_WHITE = 37; | |||
private static final int BG_BLACK = 40; | |||
private static final int BG_RED = 41; | |||
private static final int BG_GREEN = 42; | |||
private static final int BG_YELLOW = 44; | |||
private static final int BG_BLUE = 44; | |||
private static final int BG_MAGENTA = 45; | |||
private static final int BG_CYAN = 46; | |||
private static final int BG_WHITE = 47; | |||
private static final String PREFIX = "\u001b["; | |||
private static final String SUFFIX = "m"; | |||
private static final char SEPARATOR = ';'; | |||
private static final String END_COLOR = PREFIX + SUFFIX; | |||
private String errColor = PREFIX + ATTR_DIM + SEPARATOR + FG_RED + SUFFIX; | |||
private String warnColor = PREFIX + ATTR_DIM + SEPARATOR + FG_MAGENTA + SUFFIX; | |||
private String infoColor = PREFIX + ATTR_DIM + SEPARATOR + FG_CYAN + SUFFIX; | |||
private String verboseColor = PREFIX + ATTR_DIM + SEPARATOR + FG_GREEN + SUFFIX; | |||
private String debugColor = PREFIX + ATTR_DIM + SEPARATOR + FG_BLUE + SUFFIX; | |||
private boolean colorsSet = false; | |||
private final void setColors() { | |||
String userColorFile = System.getProperty("ant.logger.defaults"); | |||
String systemColorFile = | |||
"/org/apache/tools/ant/listener/defaults.properties"; | |||
InputStream in = null; | |||
try { | |||
Properties prop = new Properties(); | |||
if (userColorFile != null) { | |||
in = new FileInputStream(userColorFile); | |||
} else { | |||
in = getClass().getResourceAsStream(systemColorFile); | |||
} | |||
if (in != null) { | |||
prop.load(in); | |||
} | |||
String err = prop.getProperty("AnsiColorLogger.ERROR_COLOR"); | |||
String warn = prop.getProperty("AnsiColorLogger.WARNING_COLOR"); | |||
String info = prop.getProperty("AnsiColorLogger.INFO_COLOR"); | |||
String verbose = prop.getProperty("AnsiColorLogger.VERBOSE_COLOR"); | |||
String debug = prop.getProperty("AnsiColorLogger.DEBUG_COLOR"); | |||
if (err != null) { | |||
errColor = PREFIX + err + SUFFIX; | |||
} | |||
if (warn != null) { | |||
warnColor = PREFIX + warn + SUFFIX; | |||
} | |||
if (info != null) { | |||
infoColor = PREFIX + info + SUFFIX; | |||
} | |||
if (verbose != null) { | |||
verboseColor = PREFIX + verbose + SUFFIX; | |||
} | |||
if (debug != null) { | |||
debugColor = PREFIX + debug + SUFFIX; | |||
} | |||
} catch (IOException ioe) { | |||
//Ignore - we will use the defaults. | |||
} finally { | |||
if (in != null) { | |||
try { | |||
in.close(); | |||
} catch (IOException e) { | |||
//Ignore - We do not want this to stop the build. | |||
} | |||
} | |||
} | |||
} | |||
protected final void printMessage(final String message, | |||
final PrintStream stream, | |||
final int priority) { | |||
if (!colorsSet) { | |||
setColors(); | |||
colorsSet = true; | |||
} | |||
final StringBuffer msg = new StringBuffer(message); | |||
switch (priority) { | |||
case Project.MSG_ERR: | |||
msg.insert(0, errColor); | |||
msg.append(END_COLOR); | |||
break; | |||
case Project.MSG_WARN: | |||
msg.insert(0, warnColor); | |||
msg.append(END_COLOR); | |||
break; | |||
case Project.MSG_INFO: | |||
msg.insert(0, infoColor); | |||
msg.append(END_COLOR); | |||
break; | |||
case Project.MSG_VERBOSE: | |||
msg.insert(0, verboseColor); | |||
msg.append(END_COLOR); | |||
break; | |||
case Project.MSG_DEBUG: | |||
msg.insert(0, debugColor); | |||
msg.append(END_COLOR); | |||
break; | |||
} | |||
final String strmessage = msg.toString(); | |||
stream.println(strmessage); | |||
} | |||
} |
@@ -0,0 +1,43 @@ | |||
#################################################### | |||
# | |||
# ANSI COLOR LOGGER CONFIGURATION | |||
# | |||
# Format for AnsiColorLogger.*= | |||
# Attribute;Foreground;Background | |||
# | |||
# Attribute is one of the following: | |||
# 0 -> Reset All Attributes (return to normal mode) | |||
# 1 -> Bright (Usually turns on BOLD) | |||
# 2 -> Dim | |||
# 3 -> Underline | |||
# 5 -> link | |||
# 7 -> Reverse | |||
# 8 -> Hidden | |||
# | |||
# Foreground is one of the following: | |||
# 30 -> Black | |||
# 31 -> Red | |||
# 32 -> Green | |||
# 33 -> Yellow | |||
# 34 -> Blue | |||
# 35 -> Magenta | |||
# 36 -> Cyan | |||
# 37 -> White | |||
# | |||
# Background is one of the following: | |||
# 40 -> Black | |||
# 41 -> Red | |||
# 42 -> Green | |||
# 43 -> Yellow | |||
# 44 -> Blue | |||
# 45 -> Magenta | |||
# 46 -> Cyan | |||
# 47 -> White | |||
# | |||
#################################################### | |||
AnsiColorLogger.ERROR_COLOR=2;31 | |||
AnsiColorLogger.WARNING_COLOR=2;35 | |||
AnsiColorLogger.INFO_COLOR=2;36 | |||
AnsiColorLogger.VERBOSE_COLOR=2;32 | |||
AnsiColorLogger.DEBUG_COLOR=2;34 |