On 5/18/07, Steve Loughran <[EMAIL PROTECTED]> wrote:
One question I have here, is : how should I present teh project name.

(a) with a .  for example:  kernel.init and kernel.common.init
   -good for simple things, but imports can confuse it
(b) a /         for example:  kernel/init and kernel/common.init
   -may cause confusion as project names != dir names
(c) colon    for example:  kernel:init and kernel:common.init

(d) brackets       [kernel]:init and [kernel]:common.init
   -makes targets look like task output
(e) XML Qualified names :)  {kernel}#init and {somewith with
spaces}#common.init
   -awful

For NoBannerSubBuildLogger, for reference, I used

target-name:     [main-project-name/level1-subbuild/level2-subsubbuild]

at a fixed offset unless the target name was too long.


import java.util.Stack;

import org.apache.tools.ant.Target;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.BuildEvent;
import org.apache.tools.ant.DefaultLogger;
import org.apache.tools.ant.util.StringUtils;

/**
* Build logger that allows to make sense of the nesting structure
* generated by the use of &lt;ant&gt; and &lt;subant&gt; in Ant build files.
* <p>
* The target banner (the target name followed by a colon, all in its own line)
* will not be printed until that target's tasks output any kind of message.
* This greatly simplifies the build output for all those targets that do not
* execute, either because they are prevented to from their 'if' or 'unless'
* attributes, or because all their input files are up-to-date versus their
* output files.
* <p>
* In addition, the target banner (when output) will be postfixed with the
* project path that lead to its execution, i.e. the list of project names
* that were started using either &lt;ant&gt; and &lt;subant&gt;. Assuming
* one calls the build target of 3 different sub-builds called A, B, and C
* all called from a master build, one could get an output as follows:
* <pre>
* Buildfile: master.xml
*
* build:          [master/A]
* Compiling 19 source file to /acme/A/classes
*
* build:          [master/B]
* Compiling 15 source file to /acme/B/classes
*
* build:          [master/C]
* Compiling 12 source file to /acme/C/classes
*
* BUILD SUCCESSFUL
* Total time: 8 seconds
* </pre>
* <p>
* Inspired from NoBannerLogger by Peter Donald.
*/
public class NoBannerSubBuildLogger
            extends DefaultLogger {

   /** The cached current target name, awaiting to be possibly printed. */
   private String _targetName;

   /** The stack of nesting Ant projects. */
   private Stack _projects = new Stack();

   /** The private buffer of this logger. */
   protected StringBuffer _buffer = new StringBuffer(128);

   /**
    * Gets the target banner for a given target name.
    *
    * @param  targetName the target name to get the banner for.
    * @return the full target banner name.
    */
   protected String getTargetBanner(String targetName) {
       _buffer.setLength(0);

       // Target banner as usual
       _buffer.append(StringUtils.LINE_SEP);
       _buffer.append(targetName);
       _buffer.append(':');

       // Postfix the project path
       fillToIndex(_buffer, 16, ' ', 1);
       _buffer.append('[');
       appendProjectPath(_buffer, '/');
       _buffer.append(']');

       // Return the full target banner (toString() in bugged in JDK 1.4.1)
       return _buffer.substring(0);
   }

   /**
    * Appends the current project path to a given buffer.
    *
    * @param  buffer the string buffer to append to.
    * @param  separator the project path separator to use.
    */
   protected void appendProjectPath(StringBuffer buffer, char separator) {
       final int count = _projects.size();
       for (int i = 0; i < count; ++i) {
           Project project = (Project)_projects.get(i);
           buffer.append(project.getName());
           buffer.append(separator);
       }
       if (count > 0) {
           buffer.setLength(_buffer.length()-1);
       }
   }

   /**
    * Fills a string buffer with a given character to reach a known length.
    *
    * @param  buffer the string buffer to fill (Cannot be <code>null</code>).
    * @param  column the column index to fill up to.
    * @param  c the char to fill up with.
    * @param  minLength the mininum number of character to add in case the
    *         string buffer is already longer than <code>column</code>
    * @return the number of characters actually added.
    */
   protected static int fillToIndex(StringBuffer buffer, int column,
                                    char c, int minLength) {
       final int fillCount = Math.max(column - buffer.length(), minLength);
       for (int i = 0; i < fillCount; ++i) {
           buffer.append(c);
       }
       return fillCount;
   }

   /**
    * Records/caches the target name and its project just started.
    *
    * @param  event the build event to extract the target from.
    */
   public void targetStarted(BuildEvent event) {
       Target target = event.getTarget();
       _targetName = target.getName();
       _projects.push(target.getProject());
   }

   /**
    * Cleans up the record/cache of the target name and its project.
    *
    * @param  event the (ignored here) build event.
    */
   public void targetFinished(BuildEvent event) {
       _targetName = null;
       _projects.pop();
   }

   /**
    * Logs a task message, possibly displaying the target and project path
    * that led to its execution, if they were not displayed earlier.
    *
    * @param  event the build event containing message information.
    *               Must not be <code>null</code>.
    */
   public void messageLogged(BuildEvent event) {
       if (event.getPriority() > msgOutputLevel
           || null == event.getMessage()
           || (_targetName != null && "".equals(event.getMessage().trim()))) {
               return;
       }

       if (_targetName != null) {
           out.println(getTargetBanner(_targetName));
           _targetName = null;
       }

       super.messageLogged(event);
   }

} // END class NoBannerSubBuildLogger

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to