Browse Source

add truncate task

git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@513901 13f79535-47bb-0310-9956-ffa450edef68
master
Matthew Jason Benson 18 years ago
parent
commit
fd0bdb2676
6 changed files with 442 additions and 0 deletions
  1. +2
    -0
      WHATSNEW
  2. +106
    -0
      docs/manual/CoreTasks/truncate.html
  3. +1
    -0
      docs/manual/coretasklist.html
  4. +204
    -0
      src/main/org/apache/tools/ant/taskdefs/Truncate.java
  5. +1
    -0
      src/main/org/apache/tools/ant/taskdefs/defaults.properties
  6. +128
    -0
      src/tests/antunit/taskdefs/truncate/truncate-test.xml

+ 2
- 0
WHATSNEW View File

@@ -83,6 +83,8 @@ Other changes:

* Add a <last> resource collection, corresponding to <first>.

* Add new <truncate> task.

Changes from Ant 1.6.5 to Ant 1.7.0
===================================



+ 106
- 0
docs/manual/CoreTasks/truncate.html View File

@@ -0,0 +1,106 @@
<!--
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.
-->
<html>

<head>
<meta http-equiv="Content-Language" content="en-us">
<link rel="stylesheet" type="text/css" href="../stylesheets/style.css">
<title>Truncate Task</title>
</head>

<body>

<h2><a name="touch">Truncate</a></h2>
<h3>Description</h3>

<p>Set the length of one or more files, as the intermittently available
<code>truncate</code> Unix utility/function. In addition to working with
a single file, this Task can also work on
<a href="../CoreTypes/resource.html">resources</a> and resource collections.
<strong>Since Ant 1.7.1</strong>.
</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">file</td>
<td valign="top">The name of the file.</td>
<td valign="top" align="center">Unless a nested resource collection element
has been specified.</td>
</tr>
<tr>
<td valign="top">length</td>
<td valign="top">Specifies the new file length to set. The following
suffixes are supported:
<ul>
<li>K : Kilobytes (1024 bytes)</li>
<li>M : Megabytes (1024 K)</li>
<li>G : Gigabytes (1024 M)</li>
<li>T : Terabytes (1024 G)</li>
<li>P : Petabytes (1024 T)</li>
</ul>
</td>
<td valign="center" align="center" rowspan="2">One of these or neither.
Specifying neither is equivalent to length="0".
</td>
</tr>
<tr>
<td valign="top">adjust</td>
<td valign="top">Specifies the amount (and positive/negative direction)
by which to adjust file lengths.</td>
</tr>
<tr>
<td valign="top">create</td>
<td valign="top">Whether to create nonexistent files.</td>
<td valign="top" align="center">No, default <i>true</i>.</td>
</tr>
<tr>
<td valign="top">mkdirs</td>
<td valign="top">Whether to create nonexistent parent
directories when creating new files.</td>
<td valign="top" align="center">No, default <i>false</i>.</td>
</tr>
</table>
<h3>Parameters specified as nested elements</h3>
<h4>any resource collection</h4>

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

<h3>Examples</h3>

<pre> &lt;truncate file="foo" /&gt;</pre>
<p>Sets the length of file <code>foo</code> to zero.</p>

<pre> &lt;truncate file="foo" length="1K" /&gt;</pre>
<p>Sets the length of file <code>foo</code> to 1 kilobyte (1024 bytes).</p>

<pre> &lt;truncate file="foo" adjust="1K" /&gt;</pre>
<p>Adjusts the length of file <code>foo</code> upward by 1 kilobyte.</p>

<pre> &lt;truncate file="foo" adjust="-1M" /&gt;</pre>
<p>Adjusts the length of file <code>foo</code> downward by 1 megabyte.</p>

</body>
</html>

+ 1
- 0
docs/manual/coretasklist.html View File

@@ -113,6 +113,7 @@
<a href="CoreTasks/taskdef.html">Taskdef</a><br/>
<a href="CoreTasks/tempfile.html">Tempfile</a><br/>
<a href="CoreTasks/touch.html">Touch</a><br/>
<a href="CoreTasks/truncate.html">Truncate</a><br/>
<a href="CoreTasks/tstamp.html">TStamp</a><br/>
<a href="CoreTasks/typedef.html">Typedef</a><br/>
<a href="CoreTasks/unzip.html">Unjar</a><br/>


+ 204
- 0
src/main/org/apache/tools/ant/taskdefs/Truncate.java View File

@@ -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
* <code>truncate</code> 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 <code>true</code>.
*/
public void setCreate(boolean create) {
this.create = create;
}

/**
* Set whether, when creating nonexistent files, nonexistent directories
* should also be created.
* @param mkdirs boolean, default <code>false</code>.
*/
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;
}

}

+ 1
- 0
src/main/org/apache/tools/ant/taskdefs/defaults.properties View File

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


+ 128
- 0
src/tests/antunit/taskdefs/truncate/truncate-test.xml View File

@@ -0,0 +1,128 @@
<project name="truncate-test" default="default"
xmlns:au="antlib:org.apache.ant.antunit">

<target name="default">
<au:antunit>
<file file="${ant.file}" />
</au:antunit>
</target>

<target name="tearDown">
<delete file="foo" />
<delete file="bar" />
<delete dir="baz" />
</target>

<target name="test-basic">
<truncate file="foo" />
<au:assertTrue>
<length file="foo" length="0" />
</au:assertTrue>
</target>

<target name="test-explicit">
<truncate file="foo" length="1034" />
<au:assertTrue>
<length file="foo" length="1034" />
</au:assertTrue>
</target>

<target name="test-extend">
<truncate file="foo" length="5" />
<au:assertTrue>
<length file="foo" length="5" />
</au:assertTrue>
<truncate file="foo" adjust="5" />
<au:assertTrue>
<length file="foo" length="10" />
</au:assertTrue>
</target>

<target name="test-truncate">
<truncate file="foo" length="5" />
<au:assertTrue>
<length file="foo" length="5" />
</au:assertTrue>
<truncate file="foo" adjust="-5" />
<au:assertTrue>
<length file="foo" length="0" />
</au:assertTrue>
</target>

<target name="test-bigger">
<truncate file="foo" length="1K" />
<au:assertTrue>
<and>
<length file="foo" length="1K" />
<length file="foo" length="1024" />
</and>
</au:assertTrue>
</target>

<target name="truncate-bigger">
<truncate file="foo" length="3K" />
<au:assertTrue>
<length file="foo" length="3K" />
</au:assertTrue>
<truncate file="foo" adjust="-2K" />
<au:assertTrue>
<length file="foo" length="1K" />
</au:assertTrue>
</target>

<target name="test-no-create">
<au:assertFileDoesntExist file="foo" />
<truncate file="foo" create="false" length="0" />
<au:assertFileDoesntExist file="foo" />
</target>

<target name="test-mkdirs">
<au:assertFileDoesntExist file="baz" />
<truncate file="baz/foo" mkdirs="true" length="0" />
<au:assertTrue>
<length file="baz/foo" length="0" />
</au:assertTrue>
</target>

<target name="test-rc">
<truncate length="10">
<resources>
<file file="foo" />
<file file="bar" />
</resources>
</truncate>
<au:assertTrue>
<and>
<length file="foo" length="10" />
<length file="bar" length="10" />
</and>
</au:assertTrue>
</target>

<target name="test-bad-resource">
<au:expectfailure>
<truncate length="1P">
<string value="blah" />
</truncate>
</au:expectfailure>
</target>

<target name="test-invalid-attrs">
<au:expectfailure>
<truncate file="foo" length="0" adjust="0" />
</au:expectfailure>
</target>

<target name="test-bad-length">
<au:expectfailure>
<truncate file="foo" length="-1P" />
</au:expectfailure>
</target>

<target name="test-no-files">
<au:expectfailure>
<truncate length="0" />
</au:expectfailure>
</target>

</project>

Loading…
Cancel
Save