Browse Source

Add length task to Ant.

git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@277277 13f79535-47bb-0310-9956-ffa450edef68
master
Matthew Jason Benson 20 years ago
parent
commit
f3af5a6f26
7 changed files with 484 additions and 0 deletions
  1. +2
    -0
      WHATSNEW
  2. +68
    -0
      docs/manual/CoreTasks/length.html
  3. +1
    -0
      docs/manual/coretasklist.html
  4. +103
    -0
      src/etc/testcases/taskdefs/length.xml
  5. +239
    -0
      src/main/org/apache/tools/ant/taskdefs/Length.java
  6. +1
    -0
      src/main/org/apache/tools/ant/taskdefs/defaults.properties
  7. +70
    -0
      src/testcases/org/apache/tools/ant/taskdefs/LengthTest.java

+ 2
- 0
WHATSNEW View File

@@ -110,6 +110,8 @@ Other changes:
* 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
=====================================================



+ 68
- 0
docs/manual/CoreTasks/length.html View File

@@ -0,0 +1,68 @@
<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
- 0
docs/manual/coretasklist.html View File

@@ -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>


+ 103
- 0
src/etc/testcases/taskdefs/length.xml View File

@@ -0,0 +1,103 @@
<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>

+ 239
- 0
src/main/org/apache/tools/ant/taskdefs/Length.java View File

@@ -0,0 +1,239 @@
/*
* 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
- 0
src/main/org/apache/tools/ant/taskdefs/defaults.properties View File

@@ -81,6 +81,7 @@ presetdef=org.apache.tools.ant.taskdefs.PreSetDef
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


+ 70
- 0
src/testcases/org/apache/tools/ant/taskdefs/LengthTest.java View File

@@ -0,0 +1,70 @@
/*
* 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");
}

}

Loading…
Cancel
Save