mbenson     2005/01/04 14:20:44

  Modified:    src/main/org/apache/tools/ant/taskdefs defaults.properties
               .        WHATSNEW
               docs/manual coretasklist.html
  Added:       src/main/org/apache/tools/ant/taskdefs Length.java
               docs/manual/CoreTasks length.html
               src/etc/testcases/taskdefs length.xml
               src/testcases/org/apache/tools/ant/taskdefs LengthTest.java
  Log:
  Add length task to Ant.
  
  Revision  Changes    Path
  1.163     +1 -0      
ant/src/main/org/apache/tools/ant/taskdefs/defaults.properties
  
  Index: defaults.properties
  ===================================================================
  RCS file: 
/home/cvs/ant/src/main/org/apache/tools/ant/taskdefs/defaults.properties,v
  retrieving revision 1.162
  retrieving revision 1.163
  diff -u -r1.162 -r1.163
  --- defaults.properties       22 Nov 2004 10:48:57 -0000      1.162
  +++ defaults.properties       4 Jan 2005 22:20:44 -0000       1.163
  @@ -81,6 +81,7 @@
   macrodef=org.apache.tools.ant.taskdefs.MacroDef
   nice=org.apache.tools.ant.taskdefs.Nice
   libraries=org.apache.tools.ant.taskdefs.repository.Libraries
  +length=org.apache.tools.ant.taskdefs.Length
   
   # optional tasks
   image=org.apache.tools.ant.taskdefs.optional.image.Image
  
  
  
  1.1                  ant/src/main/org/apache/tools/ant/taskdefs/Length.java
  
  Index: Length.java
  ===================================================================
  /*
   * Copyright 2005 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.taskdefs;
  
  import java.io.File;
  import java.io.PrintStream;
  import java.io.OutputStream;
  import java.io.ByteArrayOutputStream;
  import java.util.Arrays;
  import java.util.Vector;
  import java.util.HashSet;
  import java.util.Iterator;
  
  import org.apache.tools.ant.Task;
  import org.apache.tools.ant.Project;
  import org.apache.tools.ant.BuildException;
  import org.apache.tools.ant.DirectoryScanner;
  import org.apache.tools.ant.dispatch.Dispatchable;
  import org.apache.tools.ant.types.FileSet;
  import org.apache.tools.ant.types.EnumeratedAttribute;
  import org.apache.tools.ant.util.FileUtils;
  
  /**
   * Gets lengths:  of files, byte size; of strings, length (optionally 
trimmed).
   * The task is overloaded in this way for semantic reasons, much like 
Available.
   * @since Ant 1.7
   */
  public class Length extends Task {
  
      private static final String ALL = "all";
      private static final String EACH = "each";
      private static final String STRING = "string";
      private static final FileUtils FILE_UTILS = FileUtils.getFileUtils();
  
      private String property;
      private String string;
      private Boolean trim;
      private Vector filesets;
      private String mode = ALL;
  
      /**
       * The property in which the length will be stored.
       * @param property the <code>String</code> property key.
       */
      public synchronized void setProperty(String property) {
          this.property = property;
      }
  
      /**
       * Set the single file for this task.
       * @param file the <code>File</code> whose length to retrieve.
       */
      public synchronized void setFile(File file) {
          FileSet fs = new FileSet();
          fs.setFile(file);
          add(fs);
      }
  
      /**
       * Add a FileSet.
       * @param fs the <code>FileSet</code> to add.
       */
      public synchronized void add(FileSet fs) {
          filesets = (filesets == null) ? new Vector() : filesets;
          filesets.add(fs);
      }
  
      /**
       * Set the execution mode for working with files.
       * @param m the <code>FileMode</code> to use.
       */
      public synchronized void setMode(FileMode m) {
          this.mode = m.getValue();
      }
  
      /**
       * Set the string whose length to get.
       * @param string <code>String</code>.
       */
      public synchronized void setString(String string) {
          this.string = string;
          this.mode = STRING;
      }
  
      /**
       * Set whether to trim in string mode.
       * @param trim <code>boolean</code>.
       */
      public synchronized void setTrim(boolean trim) {
          this.trim = trim ? Boolean.TRUE : Boolean.FALSE;
      }
  
      /**
       * Execute the length task.
       */
      public void execute() {
          validate();
          PrintStream ps = new PrintStream((property != null)
              ? (OutputStream) new PropertyOutputStream()
              : (OutputStream) new LogOutputStream(this, Project.MSG_INFO));
  
          if (STRING.equals(mode)) {
              ps.print(((trim != null && trim.booleanValue())
                  ? string.trim() : string).length());
              ps.close();
          } else if (EACH.equals(mode)) {
              handleFilesets(new EachHandler(ps));
          } else if (ALL.equals(mode)) {
              handleFilesets(new AllHandler(ps));
          }
      }
  
      private void validate() {
          if (string != null) {
              if (filesets != null && filesets.size() > 0) {
                  throw new BuildException("the string length function"
                      + " is incompatible with the file length function");
              }
              if (!(STRING.equals(mode))) {
                  throw new BuildException("the mode attribute is for use"
                      + " with the file length function");
              }
          } else if (filesets != null && filesets.size() > 0) {
              if (!(EACH.equals(mode) || ALL.equals(mode))) {
                  throw new BuildException("invalid mode setting for"
                      + " file length function: \"" + mode + "\"");
              } else if (trim != null) {
                  throw new BuildException("the trim attribute is"
                      + " for use with the string length function only");
              }
          } else {
              throw new BuildException("you must set either the string 
attribute"
                  + " or specify one or more files using the file attribute or"
                  + " nested filesets");
          }
      }
  
      private void handleFilesets(Handler h) {
          HashSet included = new HashSet(filesets.size() * 10);
          for (int i = 0; i < filesets.size(); i++) {
              FileSet fs = (FileSet)(filesets.get(i));
              DirectoryScanner ds = fs.getDirectoryScanner(getProject());
              File basedir = fs.getDir(getProject());
              String[] f = ds.getIncludedFiles();
              for (int j = 0; j < f.length; j++) {
                  included.add(FILE_UTILS.resolveFile(basedir, f[j]));
              }
          }
          for (Iterator iter = included.iterator(); iter.hasNext();) {
              h.handle((File)(iter.next()));
          }
          included.clear();
          included = null;
          h.complete();
      }
  
      private static long getLength(File f) {
          //should be an existing file
          if (!(f.isFile())) {
              throw new BuildException("The absolute pathname " + f
                  + " does not denote an existing file.");
          }
          return f.length();
      }
  
      /** EnumeratedAttribute operation mode */
      public static class FileMode extends EnumeratedAttribute {
          static final String[] MODES = new String[] {EACH, ALL};
  
          /**
           * Return the possible values for FileMode.
           * @return <code>String[]</code>.
           */
          public String[] getValues() {
              return MODES;
          }
  
      }
  
      private class PropertyOutputStream extends ByteArrayOutputStream {
          public void close() {
              getProject().setProperty(property, new 
String(toByteArray()).trim());
          }
      }
  
      private abstract class Handler {
          PrintStream ps;
          Handler(PrintStream ps) {
              this.ps = ps;
          }
  
          protected abstract void handle(File f);
  
          void complete() {
              ps.close();
          }
      }
  
      private class EachHandler extends Handler {
          EachHandler(PrintStream ps) {
              super(ps);
          }
          protected void handle(File f) {
              ps.print(f);
              ps.print(" : ");
              //when writing to the log, we'll see what's happening:
              ps.println(getLength(f));
         }
      }
  
      private class AllHandler extends Handler {
          long length = 0L;
          AllHandler(PrintStream ps) {
              super(ps);
          }
          protected synchronized void handle(File f) {
              length += getLength(f);
          }
          void complete() {
              ps.print(length);
              super.complete();
          }
      }
  }
  
  
  
  1.1                  ant/docs/manual/CoreTasks/length.html
  
  Index: length.html
  ===================================================================
  <html>
  
  <head>
  <meta http-equiv="Content-Language" content="en-us">
  <title>Length Task</title>
  </head>
  
  <body>
  
  <h2>Length</h2>
  <h3>Description</h3>
  <p>Display or set a property containing length information for
     a string, a file, or one or more nested filesets.</p>
  <h3>Parameters</h3>
  <table border="1" cellpadding="2" cellspacing="0">
    <tr>
      <td valign="top"><b>Attribute</b></td>
      <td valign="top"><b>Description</b></td>
      <td align="center" valign="top"><b>Required</b></td>
    </tr>
    <tr>
      <td valign="top">property</td>
      <td valign="top">The property to set.  If omitted
        the length is written to the log.</td>
      <td valign="top" align="center">No</td>
    </tr>
    <tr>
      <td valign="top">file</td>
      <td valign="top">Single file whose length to report.</td>
      <td valign="top" align="center" rowspan="2">One of these,
        or one or more nested filesets</td>
    </tr>
    <tr>
      <td valign="top">string</td>
      <td valign="top">The string whose length to report.</td>
    </tr>
    <tr>
      <td valign="top">mode</td>
      <td valign="top">File length mode; when &quot;all&quot; the resulting
        value is the sum of all included files' lengths; when &quot;each&quot;
        the task outputs the absolute path and length of each included file,
        one per line.</td>
      <td valign="top" align="center">No; default is &quot;all&quot;</td>
    </tr>
    <tr>
      <td valign="top">trim</td>
      <td valign="top">Whether to trim when operating on a string.</td>
      <td valign="top" align="center">No; only valid when string is set</td>
    </tr>
  </table>
  <h3>Parameters specified as nested elements</h3>
  <h4>fileset</h4><p>You can include files via nested
    <a href="../CoreTypes/fileset.html">fileset</a>s.</p>
  <h3>Examples</h3>
  <pre>&lt;length string=&quot;foo&quot; property=&quot;length.foo&quot; /&gt;
  </pre>
  <p>Stores the length of the string &quot;foo&quot; in the property named
  <i>length.foo</i>.</p>
  <pre>&lt;length file=&quot;bar&quot; property=&quot;length.bar&quot; /&gt;
  </pre>
  <p>Stores the length of file &quot;bar&quot; in the property named
  <i>length.bar</i>.</p>
  <hr />
  <p align="center">Copyright &copy; 2005 The Apache Software Foundation.
    All rights Reserved.</p>
  </body>
  </html>
  
  
  
  
  1.1                  ant/src/etc/testcases/taskdefs/length.xml
  
  Index: length.xml
  ===================================================================
  <project name="length">
    <property name="dir" location="lengthtestdir" />
    <property name="dir.a" location="${dir}/a" />
    <property name="dir.b" location="${dir}/b" />
  
    <target name="init">
      <mkdir dir="${dir.a}" />
      <mkdir dir="${dir.b}" />
      <concat destfile="${dir.a}/foo">foo</concat>
      <concat destfile="${dir.b}/bar">bar</concat>
    </target>
  
    <target name="testEach" depends="init">
      <length mode="each" property="length.each">
        <fileset id="fs" dir="${dir}" />
      </length>
      <pathconvert property="expected" refid="fs" pathsep="${line.separator}">
        <globmapper from="*" to="* : 3" />
      </pathconvert>
      <fail>
        <condition>
          <not>
            <equals arg1="${expected}" arg2="${length.each}" />
          </not>
        </condition>
      </fail>
    </target>
  
    <target name="testAll" depends="init">
      <length property="length.all">
        <fileset id="foo" file="${dir.a}/foo" />
        <fileset id="bar" file="${dir.b}/bar" />
      </length>
      <fail>
        <condition>
          <not>
            <equals arg1="6" arg2="${length.all}" />
          </not>
        </condition>
      </fail>
    </target>
  
    <target name="testFile" depends="init">
      <length property="length.foo" file="${dir.a}/foo" />
      <fail>
        <condition>
          <not>
            <equals arg1="3" arg2="${length.foo}" />
          </not>
        </condition>
      </fail>
    </target>
  
    <target name="testBoth" depends="init">
      <length property="length.foo" file="${dir.a}/foo">
        <fileset file="${dir.b}/bar" />
      </length>
      <fail>
        <condition>
          <not>
            <equals arg1="6" arg2="${length.foo}" />
          </not>
        </condition>
      </fail>
    </target>
  
    <target name="testDupes" depends="init">
      <length property="length.foo" file="${dir.a}/foo">
        <fileset dir="${dir}" />
      </length>
      <fail>
        <condition>
          <not>
            <equals arg1="6" arg2="${length.foo}" />
          </not>
        </condition>
      </fail>
    </target>
  
    <target name="testString">
      <length string="foo" property="length.string" />
      <fail>
        <condition>
          <not>
            <equals arg1="3" arg2="${length.string}" />
          </not>
        </condition>
      </fail>
    </target>
  
    <target name="testTrimFile" description="should fail">
      <length file="${ant.file}" trim="false" />
    </target>
  
    <target name="testStringFile" description="should fail">
      <length string="foo" file="${ant.file}" />
    </target>
  
    <target name="cleanup">
      <delete dir="${dir}" />
    </target>
  
  </project>
  
  
  
  1.1                  
ant/src/testcases/org/apache/tools/ant/taskdefs/LengthTest.java
  
  Index: LengthTest.java
  ===================================================================
  /*
   * Copyright 2005 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.taskdefs;
  
  import org.apache.tools.ant.BuildFileTest;
  
  public class LengthTest extends BuildFileTest {
  
      public LengthTest(String name) {
          super(name);
      }
  
      public void setUp() {
          configureProject("src/etc/testcases/taskdefs/length.xml");
      }
  
      public void tearDown() {
          executeTarget("cleanup");
      }
  
      public void testEach() {
          executeTarget("testEach");
      }
  
      public void testAll() {
          executeTarget("testAll");
      }
  
      public void testFile() {
          executeTarget("testFile");
      }
  
      public void testBoth() {
          executeTarget("testBoth");
      }
  
      public void testDupes() {
          executeTarget("testDupes");
      }
  
      public void testString() {
          executeTarget("testString");
      }
  
      public void testStringFile() {
          expectBuildExceptionContaining("testStringFile",
              "should fail", "incompatible");
      }
  
      public void testTrimFile() {
          expectBuildExceptionContaining("testTrimFile",
              "should fail", "string length function only");
      }
  
  }
  
  
  
  1.704     +2 -0      ant/WHATSNEW
  
  Index: WHATSNEW
  ===================================================================
  RCS file: /home/cvs/ant/WHATSNEW,v
  retrieving revision 1.703
  retrieving revision 1.704
  diff -u -r1.703 -r1.704
  --- WHATSNEW  27 Dec 2004 10:15:05 -0000      1.703
  +++ WHATSNEW  4 Jan 2005 22:20:44 -0000       1.704
  @@ -110,6 +110,8 @@
   * Added support to the touch task for a verbose attribute to suppress
     logging of new file creation.
   
  +* Added length task to get strings' and files' lengths.
  +
   Changes from Ant 1.6.2 to current Ant 1.6 CVS version
   =====================================================
   
  
  
  
  1.55      +1 -0      ant/docs/manual/coretasklist.html
  
  Index: coretasklist.html
  ===================================================================
  RCS file: /home/cvs/ant/docs/manual/coretasklist.html,v
  retrieving revision 1.54
  retrieving revision 1.55
  diff -u -r1.54 -r1.55
  --- coretasklist.html 12 Oct 2004 20:51:29 -0000      1.54
  +++ coretasklist.html 4 Jan 2005 22:20:44 -0000       1.55
  @@ -59,6 +59,7 @@
   <a href="CoreTasks/java.html">Java</a><br>
   <a href="CoreTasks/javac.html">Javac</a><br>
   <a href="CoreTasks/javadoc.html">Javadoc/<i>Javadoc2</i></a><br>
  +<a href="CoreTasks/length.html">Length</a><br>
   <a href="CoreTasks/loadfile.html">LoadFile</a><br>
   <a href="CoreTasks/loadproperties.html">LoadProperties</a><br>
   <a href="CoreTasks/mail.html">Mail</a><br>
  
  
  

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

Reply via email to