diff --git a/WHATSNEW b/WHATSNEW index 91fac75c3..f80af061b 100644 --- a/WHATSNEW +++ b/WHATSNEW @@ -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 ===================================================== diff --git a/docs/manual/CoreTasks/length.html b/docs/manual/CoreTasks/length.html new file mode 100755 index 000000000..4717367b3 --- /dev/null +++ b/docs/manual/CoreTasks/length.html @@ -0,0 +1,68 @@ + + + + +Length Task + + + + +

Length

+

Description

+

Display or set a property containing length information for + a string, a file, or one or more nested filesets.

+

Parameters

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
AttributeDescriptionRequired
propertyThe property to set. If omitted + the length is written to the log.No
fileSingle file whose length to report.One of these, + or one or more nested filesets
stringThe string whose length to report.
modeFile length mode; when "all" the resulting + value is the sum of all included files' lengths; when "each" + the task outputs the absolute path and length of each included file, + one per line.No; default is "all"
trimWhether to trim when operating on a string.No; only valid when string is set
+

Parameters specified as nested elements

+

fileset

You can include files via nested + filesets.

+

Examples

+
<length string="foo" property="length.foo" />
+
+

Stores the length of the string "foo" in the property named +length.foo.

+
<length file="bar" property="length.bar" />
+
+

Stores the length of file "bar" in the property named +length.bar.

+
+

Copyright © 2005 The Apache Software Foundation. + All rights Reserved.

+ + + diff --git a/docs/manual/coretasklist.html b/docs/manual/coretasklist.html index de64806dc..dd35a5c6f 100644 --- a/docs/manual/coretasklist.html +++ b/docs/manual/coretasklist.html @@ -59,6 +59,7 @@ Java
Javac
Javadoc/Javadoc2
+Length
LoadFile
LoadProperties
Mail
diff --git a/src/etc/testcases/taskdefs/length.xml b/src/etc/testcases/taskdefs/length.xml new file mode 100644 index 000000000..3439baa5d --- /dev/null +++ b/src/etc/testcases/taskdefs/length.xml @@ -0,0 +1,103 @@ + + + + + + + + + foo + bar + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/org/apache/tools/ant/taskdefs/Length.java b/src/main/org/apache/tools/ant/taskdefs/Length.java new file mode 100755 index 000000000..ceec0f06b --- /dev/null +++ b/src/main/org/apache/tools/ant/taskdefs/Length.java @@ -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 String property key. + */ + public synchronized void setProperty(String property) { + this.property = property; + } + + /** + * Set the single file for this task. + * @param file the File 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 FileSet 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 FileMode to use. + */ + public synchronized void setMode(FileMode m) { + this.mode = m.getValue(); + } + + /** + * Set the string whose length to get. + * @param string String. + */ + public synchronized void setString(String string) { + this.string = string; + this.mode = STRING; + } + + /** + * Set whether to trim in string mode. + * @param trim boolean. + */ + 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 String[]. + */ + 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(); + } + } +} diff --git a/src/main/org/apache/tools/ant/taskdefs/defaults.properties b/src/main/org/apache/tools/ant/taskdefs/defaults.properties index bde9ce30a..55b6c2226 100644 --- a/src/main/org/apache/tools/ant/taskdefs/defaults.properties +++ b/src/main/org/apache/tools/ant/taskdefs/defaults.properties @@ -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 diff --git a/src/testcases/org/apache/tools/ant/taskdefs/LengthTest.java b/src/testcases/org/apache/tools/ant/taskdefs/LengthTest.java new file mode 100755 index 000000000..143cf2788 --- /dev/null +++ b/src/testcases/org/apache/tools/ant/taskdefs/LengthTest.java @@ -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"); + } + +}