diff --git a/WHATSNEW b/WHATSNEW index 9f7eb7011..e2b026d34 100644 --- a/WHATSNEW +++ b/WHATSNEW @@ -83,6 +83,8 @@ Other changes: * Add a resource collection, corresponding to . +* Add new task. + Changes from Ant 1.6.5 to Ant 1.7.0 =================================== diff --git a/docs/manual/CoreTasks/truncate.html b/docs/manual/CoreTasks/truncate.html new file mode 100644 index 000000000..4c113cf57 --- /dev/null +++ b/docs/manual/CoreTasks/truncate.html @@ -0,0 +1,106 @@ + + + + + + +Truncate Task + + + + +

Truncate

+

Description

+ +

Set the length of one or more files, as the intermittently available +truncate Unix utility/function. In addition to working with +a single file, this Task can also work on +resources and resource collections. +Since Ant 1.7.1. +

+ +

Parameters

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
AttributeDescriptionRequired
fileThe name of the file.Unless a nested resource collection element + has been specified.
lengthSpecifies the new file length to set. The following + suffixes are supported: +
    +
  • K : Kilobytes (1024 bytes)
  • +
  • M : Megabytes (1024 K)
  • +
  • G : Gigabytes (1024 M)
  • +
  • T : Terabytes (1024 G)
  • +
  • P : Petabytes (1024 T)
  • +
+
One of these or neither. + Specifying neither is equivalent to length="0". +
adjustSpecifies the amount (and positive/negative direction) + by which to adjust file lengths.
createWhether to create nonexistent files.No, default true.
mkdirsWhether to create nonexistent parent + directories when creating new files.No, default false.
+

Parameters specified as nested elements

+

any resource collection

+ +

You can use any number of nested resource collection elements to +define the resources for this task and refer to resources defined +elsewhere. Note: resources passed to this task are expected +to be filesystem-based.

+ +

Examples

+ +
  <truncate file="foo" />
+

Sets the length of file foo to zero.

+ +
  <truncate file="foo" length="1K" />
+

Sets the length of file foo to 1 kilobyte (1024 bytes).

+ +
  <truncate file="foo" adjust="1K" />
+

Adjusts the length of file foo upward by 1 kilobyte.

+ +
  <truncate file="foo" adjust="-1M" />
+

Adjusts the length of file foo downward by 1 megabyte.

+ + + diff --git a/docs/manual/coretasklist.html b/docs/manual/coretasklist.html index 6e9f5896d..73ad87931 100644 --- a/docs/manual/coretasklist.html +++ b/docs/manual/coretasklist.html @@ -113,6 +113,7 @@ Taskdef
Tempfile
Touch
+Truncate
TStamp
Typedef
Unjar
diff --git a/src/main/org/apache/tools/ant/taskdefs/Truncate.java b/src/main/org/apache/tools/ant/taskdefs/Truncate.java new file mode 100755 index 000000000..2977a8151 --- /dev/null +++ b/src/main/org/apache/tools/ant/taskdefs/Truncate.java @@ -0,0 +1,204 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.IOException; +import java.io.RandomAccessFile; +import java.util.Iterator; + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.Project; +import org.apache.tools.ant.Task; +import org.apache.tools.ant.types.EnumeratedAttribute; +import org.apache.tools.ant.types.Path; +import org.apache.tools.ant.types.ResourceCollection; +import org.apache.tools.ant.types.resources.FileResource; +import org.apache.tools.ant.util.FileUtils; +import org.apache.tools.ant.util.StringUtils; + +/** + * Set the length of one or more files, as the intermittently available + * truncate Unix utility/function. + * @since Ant 1.7.1 + */ +public class Truncate extends Task { + + private static final Long ZERO = new Long(0L); + + private static final String NO_CHILD = "No files specified."; + + private static final String INVALID_LENGTH = "Cannot truncate to length "; + + private static final String READ_WRITE = "rw"; + + private static final FileUtils FILE_UTILS = FileUtils.getFileUtils(); + + private static final byte[] FILL_BUFFER = new byte[1024]; + + private Path path; + private boolean create = true; + private boolean mkdirs = false; + + private Long length; + private Long adjust; + + /** + * Set a single target File. + * @param f the single File + */ + public void setFile(File f) { + add(new FileResource(f)); + } + + /** + * Add a nested (filesystem-only) ResourceCollection. + * @param rc the ResourceCollection to add. + */ + public void add(ResourceCollection rc) { + getPath().add(rc); + } + + /** + * Set the amount by which files' lengths should be adjusted. + * It is permissible to append K / M / G / T / P. + * @param adjust (positive or negative) adjustment amount. + */ + public void setAdjust(Long adjust) { + this.adjust = adjust; + } + + /** + * Set the length to which files should be set. + * It is permissible to append K / M / G / T / P. + * @param adjust (positive) adjustment amount. + */ + public void setLength(Long length) { + this.length = length; + if (length != null && length.longValue() < 0) { + throw new BuildException(INVALID_LENGTH + length); + } + } + + /** + * Set whether to create nonexistent files. + * @param create boolean, default true. + */ + public void setCreate(boolean create) { + this.create = create; + } + + /** + * Set whether, when creating nonexistent files, nonexistent directories + * should also be created. + * @param mkdirs boolean, default false. + */ + public void setMkdirs(boolean mkdirs) { + this.mkdirs = mkdirs; + } + + /** {@inheritDoc}. */ + public void execute() { + if (length != null && adjust != null) { + throw new BuildException( + "length and adjust are mutually exclusive options"); + } + if (length == null && adjust == null) { + length = ZERO; + } + if (path == null) { + throw new BuildException(NO_CHILD); + } + for (Iterator it = path.iterator(); it.hasNext();) { + File f = ((FileResource) it.next()).getFile(); + if (shouldProcess(f)) { + process(f); + } + } + } + + private boolean shouldProcess(File f) { + if (f.isFile()) { + return true; + } + if (!create) { + return false; + } + Exception exception = null; + try { + if (FILE_UTILS.createNewFile(f, mkdirs)) { + return true; + } + } catch (IOException e) { + exception = e; + } + String msg = "Unable to create " + f; + if (exception == null) { + log(msg, Project.MSG_WARN); + return false; + } + throw new BuildException(msg, exception); + } + + private void process(File f) { + long len = f.length(); + long newLength = length == null + ? len + adjust.longValue() : length.longValue(); + + if (len == newLength) { + //nothing to do! + return; + } + RandomAccessFile raf = null; + try { + raf = new RandomAccessFile(f, READ_WRITE); + } catch (Exception e) { + throw new BuildException("Could not open " + f + " for writing", e); + } + try { + if (newLength > len) { + long pos = len; + raf.seek(pos); + while (pos < newLength) { + long writeCount = Math.min(FILL_BUFFER.length, + newLength - pos); + raf.write(FILL_BUFFER, 0, (int) writeCount); + pos += writeCount; + } + } else { + raf.setLength(newLength); + } + } catch (IOException e) { + throw new BuildException("Exception working with " + raf, e); + } finally { + try { + raf.close(); + } catch (IOException e) { + log("Caught " + e + " closing " + raf, Project.MSG_WARN); + } + } + } + + private synchronized Path getPath() { + if (path == null) { + path = new Path(getProject()); + } + return path; + } + +} diff --git a/src/main/org/apache/tools/ant/taskdefs/defaults.properties b/src/main/org/apache/tools/ant/taskdefs/defaults.properties index 8445b97a8..ba214133a 100644 --- a/src/main/org/apache/tools/ant/taskdefs/defaults.properties +++ b/src/main/org/apache/tools/ant/taskdefs/defaults.properties @@ -71,6 +71,7 @@ taskdef=org.apache.tools.ant.taskdefs.Taskdef tempfile=org.apache.tools.ant.taskdefs.TempFile touch=org.apache.tools.ant.taskdefs.Touch tstamp=org.apache.tools.ant.taskdefs.Tstamp +truncate=org.apache.tools.ant.taskdefs.Truncate typedef=org.apache.tools.ant.taskdefs.Typedef unjar=org.apache.tools.ant.taskdefs.Expand untar=org.apache.tools.ant.taskdefs.Untar diff --git a/src/tests/antunit/taskdefs/truncate/truncate-test.xml b/src/tests/antunit/taskdefs/truncate/truncate-test.xml new file mode 100644 index 000000000..3e56706f6 --- /dev/null +++ b/src/tests/antunit/taskdefs/truncate/truncate-test.xml @@ -0,0 +1,128 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +