ant-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From umag...@apache.org
Subject cvs commit: jakarta-ant/src/main/org/apache/tools/ant/listener AnsiColorLogger.java defaults.properties
Date Thu, 31 Jan 2002 19:56:33 GMT
umagesh     02/01/31 11:56:33

  Modified:    .        WHATSNEW
               docs/manual listeners.html
               src/main/org/apache/tools/ant DefaultLogger.java
  Added:       src/main/org/apache/tools/ant/listener AnsiColorLogger.java
                        defaults.properties
  Log:
  AnsiColorLogger is an extension of DefaultLogger.  It provides colorized
  messages based on the message level.
  
  Revision  Changes    Path
  1.201     +4 -2      jakarta-ant/WHATSNEW
  
  Index: WHATSNEW
  ===================================================================
  RCS file: /home/cvs/jakarta-ant/WHATSNEW,v
  retrieving revision 1.200
  retrieving revision 1.201
  diff -u -r1.200 -r1.201
  --- WHATSNEW	29 Jan 2002 16:35:45 -0000	1.200
  +++ WHATSNEW	31 Jan 2002 19:56:33 -0000	1.201
  @@ -129,8 +129,10 @@
   * <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.
  
  
  
  1.4       +96 -15    jakarta-ant/docs/manual/listeners.html
  
  Index: listeners.html
  ===================================================================
  RCS file: /home/cvs/jakarta-ant/docs/manual/listeners.html,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- listeners.html	10 Jan 2002 08:48:28 -0000	1.3
  +++ listeners.html	31 Jan 2002 19:56:33 -0000	1.4
  @@ -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 @@
   <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 @@
     </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,11 +61,17 @@
     <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>
       <td width="33%">Passes events to Log4j for highly customizable logging.</td>
  @@ -99,8 +105,8 @@
   
   <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 @@
   
   </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.&nbsp; 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.&nbsp; 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 @@
   
   <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 @@
   
   <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 &copy; 2001 Apache Software Foundation. All rights
  +<p align="center">Copyright &copy; 2002 Apache Software Foundation. All rights
   Reserved.</p>
   
   </body>
  
  
  
  1.29      +16 -10    jakarta-ant/src/main/org/apache/tools/ant/DefaultLogger.java
  
  Index: DefaultLogger.java
  ===================================================================
  RCS file: /home/cvs/jakarta-ant/src/main/org/apache/tools/ant/DefaultLogger.java,v
  retrieving revision 1.28
  retrieving revision 1.29
  diff -u -r1.28 -r1.29
  --- DefaultLogger.java	31 Jan 2002 09:24:16 -0000	1.28
  +++ DefaultLogger.java	31 Jan 2002 19:56:33 -0000	1.29
  @@ -164,9 +164,9 @@
   
           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 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 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 @@
   
               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 @@
               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) {}
  -
   }
  
  
  
  1.1                  jakarta-ant/src/main/org/apache/tools/ant/listener/AnsiColorLogger.java
  
  Index: AnsiColorLogger.java
  ===================================================================
  /*
   *  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);
      }
  }
  
  
  
  1.1                  jakarta-ant/src/main/org/apache/tools/ant/listener/defaults.properties
  
  Index: defaults.properties
  ===================================================================
  ####################################################
  #
  #           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
  
  
  

--
To unsubscribe, e-mail:   <mailto:ant-dev-unsubscribe@jakarta.apache.org>
For additional commands, e-mail: <mailto:ant-dev-help@jakarta.apache.org>


Mime
View raw message