git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@278337 13f79535-47bb-0310-9956-ffa450edef68master
@@ -0,0 +1,600 @@ | |||
<html> | |||
<head> | |||
<meta http-equiv="Content-Language" content="en-us"> | |||
<link rel="stylesheet" type="text/css" href="../stylesheets/style.css"> | |||
<title>Resources and Resource Collections</title> | |||
</head> | |||
<body> | |||
<h2><a name="resource">Resources</a></h2> | |||
<p> | |||
A file-like entity can be abstracted to the concept of a <i>resource</i>. | |||
In addition to providing access to file-like attributes, a resource | |||
implementation should, when possible, provide the means to read content | |||
from and/or write content to the underlying entity. Although the resource | |||
concept was introduced in <i>Ant 1.5.2</i>, resources are available for | |||
explicit use beginning in <b>Ant 1.7</b>. | |||
</p> | |||
<h3>The built-in resource types are:</h3> | |||
<ul> | |||
<li><a href="#basic">resource</a> - a basic resource.</li> | |||
<li><a href="#file">file</a> - a file.</li> | |||
<li><a href="#zipentry">zipentry</a> - an entry in a zip file.</li> | |||
<li><a href="#url">url</a> - a URL.</li> | |||
<li><a href="#string">string</a> - a text string.</li> | |||
<li><a href="#property">property</a> - an Ant property.</li> | |||
</ul> | |||
<h4><a name="basic">resource</a></h4> | |||
<p>A basic resource. Other resource types derive from this basic | |||
type; as such all its attributes are available, though in most cases | |||
irrelevant attributes will be ignored. This and all resource | |||
implementations are also usable as single-element | |||
<a href="#collection">Resource Collections</a>. | |||
</p> | |||
<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">name</td> | |||
<td valign="top">The name of this resource</td> | |||
<td align="center" valign="top">No</td> | |||
</tr> | |||
<tr> | |||
<td valign="top">exists</td> | |||
<td valign="top">Whether this resource exists</td> | |||
<td align="center" valign="top">No, default <i>true</i></td> | |||
</tr> | |||
<tr> | |||
<td valign="top">lastmodified</td> | |||
<td valign="top">The last modification time of this resource</td> | |||
<td align="center" valign="top">No</td> | |||
</tr> | |||
<tr> | |||
<td valign="top">directory</td> | |||
<td valign="top">Whether this resource is directory-like</td> | |||
<td align="center" valign="top">No, default <i>false</i></td> | |||
</tr> | |||
<tr> | |||
<td valign="top">size</td> | |||
<td valign="top">The size of this resource</td> | |||
<td align="center" valign="top">No</td> | |||
</tr> | |||
</table> | |||
<h4><a name="file">file</a></h4> | |||
<p>Represents a file accessible via local filesystem conventions.</p> | |||
<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 file represented by this resource</td> | |||
<td align="center" valign="top">Yes</td> | |||
</tr> | |||
<tr> | |||
<td valign="top">base</td> | |||
<td valign="top">The base directory of this resource. When this | |||
attribute is set, attempts to access the name of the resource | |||
will yield a path relative to this location.</td> | |||
<td align="center" valign="top">No</td> | |||
</tr> | |||
</table> | |||
<h4><a name="zipentry">zipentry</a></h4> | |||
<p>Represents an entry in a ZIP archive.</p> | |||
<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">zipfile</td> | |||
<td valign="top">The zip file containing this resource</td> | |||
<td align="center" valign="top">Yes</td> | |||
</tr> | |||
<tr> | |||
<td valign="top">name</td> | |||
<td valign="top">The name of the archived resource</td> | |||
<td align="center" valign="top">Yes</td> | |||
</tr> | |||
<tr> | |||
<td valign="top">encoding</td> | |||
<td valign="top">The encoding of the zipfile</td> | |||
<td align="center" valign="top">No; | |||
platform default used if unspecified</td> | |||
</tr> | |||
</table> | |||
<h4><a name="url">url</a></h4> | |||
<p>Represents a URL.</p> | |||
<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">url</td> | |||
<td valign="top">The url to expose</td> | |||
<td rowspan="3" align="center" valign="middle">Exactly one of these</td> | |||
</tr> | |||
<tr> | |||
<td valign="top">file</td> | |||
<td valign="top">The file to expose as a file: url</td> | |||
</tr> | |||
<tr> | |||
<td valign="top">javaresource</td> | |||
<td valign="top">The Java resource to expose as a jar: url</td> | |||
</tr> | |||
<tr> | |||
<td valign="top">classpath</td> | |||
<td valign="top">The classpath to use when establishing the URL | |||
for a Java resource</td> | |||
<td align="center" valign="top">No</td> | |||
</tr> | |||
</table> | |||
<p>The classpath along which to search for a Java resource | |||
can also be specified by means of one or more nested | |||
<code><a href="../using.html#path">classpath</a></code> elements. | |||
</p> | |||
<h4><a name="string">string</a></h4> | |||
<p>Represents a Java String. As such a string is readable but not writable.</p> | |||
<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">value</td> | |||
<td valign="top">The value of this resource</td> | |||
<td align="center" valign="top">Yes</td> | |||
</tr> | |||
</table> | |||
<h4><a name="property">property</a></h4> | |||
<p>Represents an Ant property.</p> | |||
<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">name</td> | |||
<td valign="top">The property name</td> | |||
<td align="center" valign="top">Yes</td> | |||
</tr> | |||
</table> | |||
<hr> | |||
<h2><a name="collection">Resource Collections</a></h2> | |||
<p> | |||
A Resource Collection is an abstraction of an entity that groups | |||
together a number of <a href="#resource">resources</a>. Several of | |||
Ant's "legacy" datatypes have been modified to behave as Resource Collections: | |||
<ul> | |||
<li><a href="fileset.html">fileset</a>, | |||
<a href="dirset.html">dirset</a>, | |||
<a href="filelist.html">filelist</a>, and | |||
<a href="../using.html#path">path</a> | |||
(and derivative types) expose <a href="#file">file</a> resources | |||
</li> | |||
<li><a href="zipfileset.html">zipfileset</a> | |||
can expose <a href="#file">file</a> or <a href="#zipentry">zipentry</a> | |||
resources depending on configuration | |||
</li> | |||
<li><a href="propertyset.html">propertyset</a> | |||
exposes <a href="#property">property</a> resources | |||
</li> | |||
</ul> | |||
</p> | |||
<h3>The additional built-in resource collections are:</h3> | |||
<ul> | |||
<li><a href="#resources">resources</a> - generic resource collection</li> | |||
<li><a href="#files">files</a> - collection of files similar to | |||
<a href="fileset.html">fileset</a></li> | |||
<li><a href="#restrict">restrict</a> - restrict a resource collection | |||
to include only resources meeting specified criteria</li> | |||
<li><a href="#sort">sort</a> - sorted resource collection</li> | |||
<li><a href="#union">union</a> - set union of nested resource collections</li> | |||
<li><a href="#intersect">intersect</a> - set intersection | |||
of nested resource collections</li> | |||
<li><a href="#difference">difference</a> - set difference | |||
of nested resource collections</li> | |||
</ul> | |||
<h4><a name="resources">resources</a></h4> | |||
<p>A generic resource collection, designed for use with | |||
<a href="../using.html#references">references</a>. | |||
For example, if a third-party Ant task generates a Resource Collection | |||
of an unknown type, it can still be accessed via a | |||
<code><resources></code> collection. The secondary use of this | |||
collection type is as a container of other resource collections, | |||
preserving the order of nested collections as well as | |||
duplicate resources (contrast with <a href="#union">union</a>). | |||
</p> | |||
<h4><a name="files">files</a></h4> | |||
<p>A group of files. These files are matched by <b>absolute</b> patterns | |||
taken from a number of <a href="patternset.html">PatternSets</a>. | |||
These can be specified as nested <code><patternset></code> | |||
elements. In addition, <code><files></code> holds an implicit | |||
PatternSet and supports the nested <code><include></code>, | |||
<code><includesfile></code>, <code><exclude></code> | |||
and <code><excludesfile></code> elements of PatternSet directly, | |||
as well as PatternSet's attributes. | |||
</p> | |||
<p><a href="selectors.html">File Selectors</a> are available as nested | |||
elements. A file must be selected by all selectors in order to be included; | |||
<code><files></code> is thus equivalent to an | |||
<code><and></code> file selector container. | |||
</p> | |||
<p><b>More simply put</b>, this type is equivalent to a | |||
<a href="fileset.html">fileset</a> with no base directory. | |||
<b>Please note</b> that without a base directory, | |||
filesystem scanning is based entirely on include and exclude patterns. | |||
A <a href="selectors.html#filenameselect">filename</a> (or any) | |||
selector can <i>only</i> influence the scanning process <i>after</i> | |||
the file has been included based on pattern-based selection. | |||
</p> | |||
<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">includes</td> | |||
<td valign="top">comma- or space-separated list of patterns | |||
of files that must be included</td> | |||
<td rowspan="2" valign="middle" align="center">At least one of these</td> | |||
</tr> | |||
<tr> | |||
<td valign="top">includesfile</td> | |||
<td valign="top">the name of a file; each line of this file is | |||
taken to be an include pattern.</td> | |||
</tr> | |||
<tr> | |||
<td valign="top">excludes</td> | |||
<td valign="top">comma- or space-separated list of patterns | |||
of files that must be excluded</td> | |||
<td rowspan="2" valign="top" align="center">No, default none | |||
(except default excludes when true)</td> | |||
</tr> | |||
<tr> | |||
<td valign="top">excludesfile</td> | |||
<td valign="top">the name of a file; each line of this file is | |||
taken to be an exclude pattern.</td> | |||
</tr> | |||
<tr> | |||
<td valign="top">defaultexcludes</td> | |||
<td valign="top">Whether | |||
<a href="../dirtasks.html#defaultexcludes">default excludes</a> | |||
should be used</td> | |||
<td valign="top" align="center">No, default <i>true</i></td> | |||
</tr> | |||
<tr> | |||
<td valign="top">casesensitive</td> | |||
<td valign="top">Whether patterns are case-sensitive</td> | |||
<td valign="top" align="center">No, default <i>true</i></td> | |||
</tr> | |||
<tr> | |||
<td valign="top">followsymlinks</td> | |||
<td valign="top">Whether to follow symbolic links | |||
(see note <a href="#symlink">below</a>)</td> | |||
<td valign="top" align="center">No, default <i>true</i></td> | |||
</tr> | |||
</table> | |||
<p><a name="symlink"><b>Note</b></a>: All files/directories for which | |||
the canonical path is different from its path are considered symbolic | |||
links. On Unix systems this usually means the file really is a | |||
symbolic link but it may lead to false results on other | |||
platforms. | |||
</p> | |||
<h4><a name="restrict">restrict</a></h4> | |||
<p>Restricts another nested resource collection using resource selectors: | |||
<blockquote> | |||
<h4>Parameters specified as nested elements</h4> | |||
<p>A single resource collection is required.</p> | |||
<p>Nested resource selectors are used to "narrow down" the included | |||
resources. These are patterned after <a href="selectors.html">file | |||
selectors</a> but are, unsurprisingly, targeted to resources. | |||
Several built-in resource selectors are available in the internal | |||
<a href="antlib.html">antlib</a> | |||
<code>org.apache.tools.ant.types.resources.selectors</code>: | |||
</p> | |||
<ul> | |||
<li><a href="#rsel.name">name</a> - select resources by name.</li> | |||
<li><a href="#rsel.exists">exists</a> - select existing resources.</li> | |||
<li><a href="#rsel.date">date</a> - select resources by date.</li> | |||
<li><a href="#rsel.type">type</a> - select resources by type.</li> | |||
<li><a href="#rsel.size">size</a> - select resources by size.</li> | |||
<li><a href="#rsel.instanceof">instanceof</a> | |||
- select resources by class or Ant datatype.</li> | |||
<li><a href="#rsel.and">and</a> - "and" nested resource selectors.</li> | |||
<li><a href="#rsel.or">or</a> - "or" nested resource selectors.</li> | |||
<li><a href="#rsel.not">not</a> - "not" a nested resource selector.</li> | |||
<li><a href="#rsel.none">none</a> | |||
- select resources selected by no nested resource selectors.</li> | |||
<li><a href="#rsel.majority">majority</a> - select resources selected | |||
by a majority of nested resource selectors.</li> | |||
</ul> | |||
<h4><a name="rsel.name">name</a></h4> | |||
<p>Selects resources by name.</p> | |||
<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">name</td> | |||
<td valign="top">The name pattern to test</td> | |||
<td align="center" valign="top">Yes</td> | |||
</tr> | |||
<tr> | |||
<td valign="top">casesensitive</td> | |||
<td valign="top">Whether name comparisons are case-sensitive</td> | |||
<td align="center" valign="top">No, default <i>true</i></td> | |||
</tr> | |||
</table> | |||
<h4><a name="rsel.exists">exists</a></h4> | |||
<p>Selects existing resources.</p> | |||
<h4><a name="rsel.date">date</a></h4> | |||
<p>Selects resources by date.</p> | |||
<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">millis</td> | |||
<td valign="top">The comparison date/time in ms since January 1, 1970</td> | |||
<td rowspan="2" align="center" valign="middle">One of these</td> | |||
</tr> | |||
<tr> | |||
<td valign="top">datetime</td> | |||
<td valign="top">The formatted comparison date/time</td> | |||
</tr> | |||
<tr> | |||
<td valign="top">pattern</td> | |||
<td valign="top">SimpleDateFormat-compatible pattern | |||
for use with the <code>datetime</code> attribute</td> | |||
<td align="center" valign="top"> | |||
No, default is "MM/DD/YYYY HH:MM AM_or_PM"</td> | |||
</tr> | |||
<tr> | |||
<td valign="top">granularity</td> | |||
<td valign="top">The number of milliseconds leeway to use when | |||
comparing file modification times. This is needed because not | |||
every file system supports tracking the last modified time to | |||
the millisecond level.</td> | |||
<td align="center" valign="top">No; default varies by platform: | |||
FAT filesystems = 2 sec; Unix = 1 sec; NTFS = 1 ms.</td> | |||
</tr> | |||
<tr> | |||
<td valign="top">when</td> | |||
<td valign="top">One of "before", "after", "equal"</td> | |||
<td align="center" valign="top">No, default "equal"</td> | |||
</tr> | |||
</table> | |||
<h4><a name="rsel.type">type</a></h4> | |||
<p>Selects resources by type (file or directory).</p> | |||
<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">type</td> | |||
<td valign="top">One of "file", "dir"</td> | |||
<td align="center" valign="top">Yes</td> | |||
</tr> | |||
</table> | |||
<h4><a name="rsel.size">size</a></h4> | |||
<p>Selects resources by size.</p> | |||
<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">size</td> | |||
<td valign="top">The size to compare</td> | |||
<td align="center" valign="top">Yes</td> | |||
</tr> | |||
<tr> | |||
<td valign="top">when</td> | |||
<td valign="top">One of "equal", "eq", "greater", "gt", "less", "lt", | |||
"ge" (greater or equal), "ne" (not equal), "le" (less or equal)</td> | |||
<td align="center" valign="top">No, default "equal"</td> | |||
</tr> | |||
</table> | |||
<h4><a name="rsel.instanceof">instanceof</a></h4> | |||
<p>Selects resources by type.</p> | |||
<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">class</td> | |||
<td valign="top">The class of which the resource must be an instance</td> | |||
<td rowspan="2" align="center" valign="middle">One of these</td> | |||
</tr> | |||
<tr> | |||
<td valign="top">type</td> | |||
<td valign="top">The Ant type that must | |||
be assignable from the resource</td> | |||
</tr> | |||
<tr> | |||
<td valign="top">uri</td> | |||
<td valign="top">The uri in which <i>type</i> must be defined</td> | |||
<td valign="top">No</td> | |||
</tr> | |||
</table> | |||
<h4><a name="rsel.and">and</a></h4> | |||
<p>Selects a resource if it is selected by all nested resource selectors.</p> | |||
<h4><a name="rsel.or">or</a></h4> | |||
<p>Selects a resource if it is selected | |||
by at least one nested resource selector.</p> | |||
<h4><a name="rsel.not">not</a></h4> | |||
<p>Negates the selection result of the single | |||
nested resource selector allowed.</p> | |||
<h4><a name="rsel.none">none</a></h4> | |||
<p>Selects a resource if it is selected | |||
by no nested resource selectors.</p> | |||
<h4><a name="rsel.majority">majority</a></h4> | |||
<p>Selects a resource if it is selected | |||
by the majority of nested resource selectors.</p> | |||
<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">allowtie</td> | |||
<td valign="top">Whether a tie (when there is an even number | |||
of nested resource selectors) is considered a majority</td> | |||
<td valign="top">No, default <i>true</i></td> | |||
</tr> | |||
</table> | |||
</blockquote> | |||
<h4><a name="sort">sort</a></h4> | |||
<p>Sorts another nested resource collection according to the resources' | |||
natural order, or by one or more nested resource comparators:</p> | |||
<blockquote> | |||
<h4>Parameters specified as nested elements</h4> | |||
<p>A single resource collection is required.</p> | |||
<p>The sort can be controlled and customized by specifying one or more | |||
resource comparators. Resources can be sorted according to multiple | |||
criteria; the first specified is the "outermost", while the last | |||
specified is the "innermost". Several built-in resource comparators | |||
are available in the internal <a href="antlib.html">antlib</a> | |||
<code>org.apache.tools.ant.types.resources.comparators</code>: | |||
</p> | |||
<ul> | |||
<li><a href="#rcmp.name">name</a> - sort resources by name</li> | |||
<li><a href="#rcmp.exists">exists</a> - sort resources by existence</li> | |||
<li><a href="#rcmp.date">date</a> - sort resources by date</li> | |||
<li><a href="#rcmp.type">type</a> - sort resources by type</li> | |||
<li><a href="#rcmp.size">size</a> - sort resources by size</li> | |||
<li><a href="#rcmp.content">content</a> - sort resources by content</li> | |||
<li><a href="#rcmp.reverse">reverse</a> - reverse the natural sort order, | |||
or a single nested resource comparator</li> | |||
</ul> | |||
<h4><a name="rcmp.name">name</a></h4> | |||
<p>Sort resources by name.</p> | |||
<h4><a name="rcmp.exists">exists</a></h4> | |||
<p>Sort resources by existence. | |||
Not existing is considered "less than" existing.</p> | |||
<h4><a name="rcmp.date">date</a></h4> | |||
<p>Sort resources by date.</p> | |||
<h4><a name="rcmp.type">type</a></h4> | |||
<p>Sort resources by type (file or directory). | |||
Because directories contain files, they are considered "greater".</p> | |||
<h4><a name="rcmp.size">size</a></h4> | |||
<p>Sort resources by size.</p> | |||
<h4><a name="rcmp.content">content</a></h4> | |||
<p>Sort resources by content.</p> | |||
<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">binary</td> | |||
<td valign="top">Whether content should be compared in binary mode. | |||
If <i>false<i>, content will be compared without regard to | |||
platform-specific line-ending conventions.</td> | |||
<td valign="top">No, default <i>true</i></td> | |||
</tr> | |||
</table> | |||
<h4><a name="rcmp.reverse">reverse</a></h4> | |||
<p>Reverse the natural sort order, or a single nested comparator.</p> | |||
</blockquote> | |||
<h4><a name="setlogic">Set operations</a></h4> | |||
<blockquote> | |||
<p>The following resource collections implement set operations:</p> | |||
<ul> | |||
<li><a href="#union">union</a></li> | |||
<li><a href="#intersect">intersect</a></li> | |||
<li><a href="#difference">difference</a></li> | |||
</ul> | |||
<h4><a name="union">union</a></h4> | |||
<p>Union of nested resource collections.</p> | |||
<h4><a name="intersect">intersect</a></h4> | |||
<p>Intersection of nested resource collections.</p> | |||
<h4><a name="difference">difference</a></h4> | |||
<p>Difference of nested resource collections.</p> | |||
</blockquote> | |||
<hr> | |||
<p align="center">Copyright © 2005 The Apache Software Foundation. All rights | |||
Reserved.</p> | |||
</body> | |||
</html> |
@@ -31,6 +31,8 @@ | |||
<a href="CoreTypes/propertyset.html">PropertySet</a><br> | |||
<a href="CoreTypes/redirector.html">I/O Redirectors</a><br> | |||
<a href="CoreTypes/regexp.html">Regexp</a><br> | |||
<a href="CoreTypes/resources.html">Resources</a><br> | |||
<a href="CoreTypes/resources.html#collection">Resource Collections</a><br> | |||
<a href="CoreTypes/selectors.html">Selectors</a><br> | |||
<a href="CoreTypes/xmlcatalog.html">XMLCatalog</a><br> | |||
<a href="CoreTypes/zipfileset.html">ZipFileSet</a><br> | |||
@@ -15,6 +15,7 @@ | |||
<delete file="concat.noeol"/> | |||
<delete file="concat.linecr"/> | |||
<delete file="concat.utf8"/> | |||
<delete file="concat.urls"/> | |||
</target> | |||
<target name="test1"> | |||
@@ -185,4 +186,30 @@ | |||
</concat> | |||
</target> | |||
<target name="testResources" unless="offline"> | |||
<concat destfile="concat.urls" binary="true"> | |||
<url url="http://ant.apache.org" /> | |||
<url url="http://ant.apache.org" /> | |||
</concat> | |||
<length property="expected" includeduplicates="true"> | |||
<resources> | |||
<url url="http://ant.apache.org" /> | |||
<url url="http://ant.apache.org" /> | |||
</resources> | |||
</length> | |||
<length property="actual"> | |||
<fileset file="concat.urls" /> | |||
</length> | |||
<fail> | |||
<condition> | |||
<or> | |||
<equals arg1="${actual}" arg2="0" /> | |||
<not> | |||
<equals arg1="${actual}" arg2="${expected}" /> | |||
</not> | |||
</or> | |||
</condition> | |||
</fail> | |||
</target> | |||
</project> |
@@ -82,6 +82,30 @@ | |||
<classfileset id="result" dir="${classes.dir}" rootclass="B"/> | |||
</target> | |||
<target name="testresourcecollection" depends="testsmallset"> | |||
<fail> | |||
<condition> | |||
<not> | |||
<and> | |||
<resourcecount count="2" refid="result" /> | |||
<resourcecount count="1"> | |||
<intersect> | |||
<resources refid="result" /> | |||
<file file="${classes.dir}/B.class" /> | |||
</intersect> | |||
</resourcecount> | |||
<resourcecount count="1"> | |||
<intersect> | |||
<resources refid="result" /> | |||
<file file="${classes.dir}/C.class" /> | |||
</intersect> | |||
</resourcecount> | |||
</and> | |||
</not> | |||
</condition> | |||
</fail> | |||
</target> | |||
<target name="testcomboset" depends="src1setup, compile"> | |||
<classfileset id="result" dir="${classes.dir}" rootclass="B"> | |||
<include name="**/C.class"/> | |||
@@ -0,0 +1,450 @@ | |||
<project default="all" | |||
xmlns:rsel="antlib:org.apache.tools.ant.types.resources.selectors"> | |||
<property name="dirname" value="work" /> | |||
<property name="dir" location="${dirname}" /> | |||
<property name="zip" location="${dirname}.zip" /> | |||
<property name="jar" location="${dirname}.jar" /> | |||
<property name="file" location="${dirname}/file.txt" /> | |||
<target name="init"> | |||
<touch mkdirs="true"> | |||
<filelist dir="${dir}/foo/a" files="x,y,z" /> | |||
</touch> | |||
<copy todir="${dir}/foo" enablemultiplemappings="true"> | |||
<fileset dir="${dir}/foo" /> | |||
<mapper> | |||
<globmapper handledirsep="true" from="a/*" to="b/*" /> | |||
<globmapper handledirsep="true" from="a/*" to="c/*" /> | |||
</mapper> | |||
</copy> | |||
<copy todir="${dir}/bar"> | |||
<fileset dir="${dir}/foo" /> | |||
</copy> | |||
<property name="foo" location="${dir}/foo" /> | |||
<property name="foo.a" location="${dir}/foo/a" /> | |||
<property name="foo.b" location="${dir}/foo/b" /> | |||
<property name="foo.c" location="${dir}/foo/c" /> | |||
<property name="bar" location="${dir}/bar" /> | |||
<property name="bar.a" location="${dir}/bar/a" /> | |||
<property name="bar.b" location="${dir}/bar/b" /> | |||
<property name="bar.c" location="${dir}/bar/c" /> | |||
</target> | |||
<target name="tearDown"> | |||
<delete dir="${dir}" /> | |||
<delete file="${zip}" /> | |||
<delete file="${jar}" deleteonexit="true" /> | |||
<delete file="${file}" /> | |||
</target> | |||
<target name="testfiles1" depends="init"> | |||
<fail> | |||
<condition> | |||
<not> | |||
<resourcecount count="26"> | |||
<files> | |||
<include name="${dir}/foo/" /> | |||
<include name="${dir}/bar/" /> | |||
</files> | |||
</resourcecount> | |||
</not> | |||
</condition> | |||
</fail> | |||
</target> | |||
<target name="testfiles2" depends="init"> | |||
<fail> | |||
<condition> | |||
<not> | |||
<resourcecount count="8"> | |||
<files> | |||
<include name="${dir}/foo/" /> | |||
<include name="${dir}/bar/" /> | |||
<type type="dir" /> | |||
</files> | |||
</resourcecount> | |||
</not> | |||
</condition> | |||
</fail> | |||
</target> | |||
<target name="testfiles3" depends="init"> | |||
<fail> | |||
<condition> | |||
<not> | |||
<resourcecount count="18"> | |||
<files> | |||
<include name="${dir}/foo/" /> | |||
<include name="${dir}/bar/" /> | |||
<type type="file" /> | |||
</files> | |||
</resourcecount> | |||
</not> | |||
</condition> | |||
</fail> | |||
</target> | |||
<target name="files" depends="testfiles1,testfiles2,testfiles3" /> | |||
<target name="testnestedresources" depends="init"> | |||
<fail> | |||
<condition> | |||
<not> | |||
<resourcecount count="27"><!-- include duplicates! --> | |||
<resources> | |||
<files> | |||
<include name="${dir}/foo/" /> | |||
<include name="${dir}/bar/" /> | |||
<type type="file" /> | |||
</files> | |||
<files> | |||
<include name="${dir}/foo/" /> | |||
<type type="file" /> | |||
</files> | |||
</resources> | |||
</resourcecount> | |||
</not> | |||
</condition> | |||
</fail> | |||
</target> | |||
<target name="testresourcesref" depends="init"> | |||
<files id="files"> | |||
<include name="${dir}/foo/" /> | |||
<include name="${dir}/bar/" /> | |||
<type type="file" /> | |||
</files> | |||
<fail> | |||
<condition> | |||
<not> | |||
<resourcecount count="18"> | |||
<resources refid="files" /> | |||
</resourcecount> | |||
</not> | |||
</condition> | |||
</fail> | |||
</target> | |||
<target name="resources" depends="testnestedresources,testresourcesref" /> | |||
<target name="testfileset" depends="init"> | |||
<fail> | |||
<condition> | |||
<not> | |||
<resourcecount count="9"> | |||
<fileset dir="${dir}/foo" /> | |||
</resourcecount> | |||
</not> | |||
</condition> | |||
</fail> | |||
</target> | |||
<target name="testdirset" depends="init"> | |||
<fail> | |||
<condition> | |||
<not> | |||
<resourcecount count="4"> | |||
<dirset dir="${dir}/foo" /> | |||
</resourcecount> | |||
</not> | |||
</condition> | |||
</fail> | |||
</target> | |||
<target name="testfilelist"> | |||
<fail> | |||
<condition> | |||
<not> | |||
<resourcecount count="5"> | |||
<filelist dir="${dir}/foo" files="1,2,3,4,5" /> | |||
</resourcecount> | |||
</not> | |||
</condition> | |||
</fail> | |||
</target> | |||
<target name="testpath" depends="init"> | |||
<fail> | |||
<condition> | |||
<not> | |||
<resourcecount count="24"> | |||
<path> | |||
<path id="p"> | |||
<fileset id="fs" dir="${foo.a}" /> <!-- 3 --> | |||
<dirset id="ds" dir="${foo}" /> <!-- 4 --> | |||
</path> | |||
<pathelement id="pe" location="${dir}" /> <!-- 1 --> | |||
<filelist id="fl" dir="${bar}" files="1,2,3,a,b,c" /> <!-- 6 --> | |||
<files id="f" includes="${bar}/" /> <!-- 13; 3 overlap fl --> | |||
</path> | |||
</resourcecount> | |||
</not> | |||
</condition> | |||
</fail> | |||
</target> | |||
<target name="createzip" depends="init"> | |||
<zip destfile="${zip}" basedir="${dir}" /> | |||
</target> | |||
<target name="testzipfileset" depends="createzip"> | |||
<fail> | |||
<condition> | |||
<not> | |||
<resourcecount count="9"> | |||
<zipfileset src="${zip}" includes="foo/" /> | |||
</resourcecount> | |||
</not> | |||
</condition> | |||
</fail> | |||
</target> | |||
<target name="testpropertyset"> | |||
<property name="testpropertyset.a" value="a" /> | |||
<property name="testpropertyset.aa" value="aa" /> | |||
<property name="testpropertyset.aaa" value="aaa" /> | |||
<propertyset id="testpropertyset"> | |||
<propertyref prefix="testpropertyset." /> | |||
</propertyset> | |||
<fail> | |||
<condition> | |||
<not> | |||
<and> | |||
<resourcecount refid="testpropertyset" count="3" /> | |||
<length length="12"> | |||
<resources> | |||
<resources refid="testpropertyset" /> | |||
<propertyset refid="testpropertyset" /> | |||
</resources> | |||
</length> | |||
</and> | |||
</not> | |||
</condition> | |||
</fail> | |||
</target> | |||
<target name="legacy" | |||
depends="testfileset,testdirset,testfilelist,testpath,testzipfileset,testpropertyset" /> | |||
<target name="testunion" depends="init"> | |||
<fail> | |||
<condition> | |||
<not> | |||
<resourcecount count="4"> | |||
<union> | |||
<files includes="${foo.a}/w,${foo.a}/x" /> <!-- 1 --> | |||
<fileset dir="${foo.a}" includes="x,y" /> <!-- 2; net 1 --> | |||
<filelist dir="${foo.a}" files="v" /> <!-- 1 --> | |||
<files includes="${foo.a}/y,${foo.a}/z" /> <!-- 2; net 1 --> | |||
</union> | |||
</resourcecount> | |||
</not> | |||
</condition> | |||
</fail> | |||
</target> | |||
<target name="testintersect"> | |||
<fail> | |||
<condition> | |||
<not> | |||
<resourcecount count="3"> | |||
<intersect> | |||
<filelist dir="${dir}" files="1,2,3,4,5" /> | |||
<filelist dir="${dir}" files="2,3,4,5,6" /> | |||
<filelist dir="${dir}" files="3,4,5,6,7" /> | |||
</intersect> | |||
</resourcecount> | |||
</not> | |||
</condition> | |||
</fail> | |||
</target> | |||
<target name="testdifference"> | |||
<fail> | |||
<condition> | |||
<not> | |||
<resourcecount count="2"> | |||
<difference id="diff"> | |||
<filelist dir="${dir}" files="1,2,3,4,5" /> | |||
<filelist dir="${dir}" files="2,3,4,5,6" /> | |||
<filelist dir="${dir}" files="3,4,5,6,7" /> | |||
</difference> | |||
</resourcecount> | |||
</not> | |||
</condition> | |||
</fail> | |||
</target> | |||
<target name="setlogic" depends="testunion,testintersect,testdifference" /> | |||
<target name="testfileurl"> | |||
<condition property="blah"> | |||
<length when="less" length="1"> | |||
<url file="${ant.file}" /> | |||
</length> | |||
</condition> | |||
<fail if="blah" /> | |||
</target> | |||
<target name="testfileurlref"> | |||
<url id="fileurl" file="${ant.file}" /> | |||
<condition property="blah"> | |||
<length when="less" length="1"> | |||
<url refid="fileurl" /> | |||
</length> | |||
</condition> | |||
<fail if="blah" /> | |||
</target> | |||
<target name="testhttpurl1" unless="offline"> | |||
<fail> | |||
<condition> | |||
<length when="less" length="1"> | |||
<url url="http://ant.apache.org/index.html" /> | |||
</length> | |||
</condition> | |||
</fail> | |||
</target> | |||
<target name="testhttpurl2" unless="offline"> | |||
<concat destfile="${file}" force="true" append="false"> | |||
<url id="httpurl" url="http://ant.apache.org/index.html" /> | |||
<url refid="httpurl" /> | |||
</concat> | |||
<length property="httpurl.length"> | |||
<url refid="httpurl" /> | |||
</length> | |||
<fail> | |||
<condition> | |||
<not> | |||
<length file="${file}" when="greater" length="${httpurl.length}" /> | |||
</not> | |||
</condition> | |||
</fail> | |||
</target> | |||
<target name="createjar" depends="init"> | |||
<jar destfile="${jar}" basedir="${dir}" /> | |||
</target> | |||
<target name="testjarurl" depends="createjar"> | |||
<pathconvert property="jarurl"> | |||
<url file="${jar}" /> | |||
</pathconvert> | |||
<fail> | |||
<condition> | |||
<length when="less" length="1"> | |||
<url url="jar:${jarurl}!/META-INF/MANIFEST.MF" /> | |||
</length> | |||
</condition> | |||
</fail> | |||
</target> | |||
<target name="testresourceurl" depends="createjar"> | |||
<!-- test ref while we're at it --> | |||
<url id="resourceurl" | |||
javaresource="foo/c/z" classpath="${jar}" /> | |||
<fail> | |||
<condition> | |||
<resourcecount count="0"> | |||
<restrict> | |||
<url refid="resourceurl" /> | |||
<rsel:exists /> | |||
</restrict> | |||
</resourcecount> | |||
</condition> | |||
</fail> | |||
</target> | |||
<target name="url" | |||
depends="testfileurl,testfileurlref,testhttpurl1,testhttpurl2,testjarurl,testresourceurl" /> | |||
<target name="testfile" depends="init"> | |||
<echo file="${file}">This is a test.</echo> | |||
<fail> | |||
<condition> | |||
<not> | |||
<length length="15"> | |||
<file file="${file}" /> | |||
</length> | |||
</not> | |||
</condition> | |||
</fail> | |||
</target> | |||
<target name="testzipentry" depends="createjar"> | |||
<fail> | |||
<condition> | |||
<not> | |||
<length when="greater" length="0"> | |||
<zipentry zipfile="${jar}" name="META-INF/MANIFEST.MF" /> | |||
</length> | |||
</not> | |||
</condition> | |||
</fail> | |||
</target> | |||
<target name="teststring1"> | |||
<fail> | |||
<condition> | |||
<not> | |||
<length length="15"> | |||
<string value="This is a test." /> | |||
</length> | |||
</not> | |||
</condition> | |||
</fail> | |||
</target> | |||
<target name="teststring2"> | |||
<property name="test" value="foo" /> | |||
<fail> | |||
<condition> | |||
<not> | |||
<length length="14"> | |||
<string value="This is a ${test}." /> | |||
</length> | |||
</not> | |||
</condition> | |||
</fail> | |||
</target> | |||
<target name="string" depends="teststring1,teststring2" /> | |||
<target name="testresource"> | |||
<fail> | |||
<condition> | |||
<not> | |||
<length length="4096"> | |||
<resource size="4096" /> | |||
</length> | |||
</not> | |||
</condition> | |||
</fail> | |||
</target> | |||
<target name="testproperty"> | |||
<property name="testproperty" value="abcdefghij" /> | |||
<fail> | |||
<condition> | |||
<not> | |||
<length length="10"> | |||
<propertyresource name="testproperty" /> | |||
</length> | |||
</not> | |||
</condition> | |||
</fail> | |||
</target> | |||
<target name="single" | |||
depends="testresource,url,testfile,string,testzipentry,testproperty" /> | |||
<target name="all" depends="legacy,files,resources,setlogic,single" /> | |||
</project> |
@@ -0,0 +1,326 @@ | |||
<project default="sort" | |||
xmlns:rcmp="antlib:org.apache.tools.ant.types.resources.comparators"> | |||
<property name="dirname" value="work" /> | |||
<property name="dir" location="${dirname}" /> | |||
<target name="tearDown"> | |||
<delete dir="${dir}" /> | |||
<delete file="${zip}" /> | |||
<delete file="${jar}" deleteonexit="true" /> | |||
<delete file="${file}" /> | |||
</target> | |||
<target name="sortsetup" unless="sortsetup.done"> | |||
<mkdir dir="${dir}" /> | |||
<echo file="${dir}/b" message="yyy" /> | |||
<echo file="${dir}/e" message="aaa" /> | |||
<sleep seconds="2" /> | |||
<echo file="${dir}/c" message="x" /> | |||
<echo file="${dir}/d" message="x" /> | |||
<sleep seconds="2" /> | |||
<echo file="${dir}/a" message="zz" /> | |||
<echo file="${dir}/f" message="zz" /> | |||
<mkdir dir="${dir}/a.dir" /> | |||
<mkdir dir="${dir}/b.dir" /> | |||
<mkdir dir="${dir}/c.dir" /> | |||
<macrodef name="mysort"> | |||
<attribute name="property" /> | |||
<attribute name="separator" default="," /> | |||
<element name="cmp" optional="true" implicit="true" /> | |||
<sequential> | |||
<pathconvert property="@{property}" pathsep="@{separator}"> | |||
<sort> | |||
<fileset dir="${dir}" includes="a,b,c" /> | |||
<cmp /> | |||
</sort> | |||
<flattenmapper /> | |||
</pathconvert> | |||
</sequential> | |||
</macrodef> | |||
<property name="sortsetup.done" value="true" /> | |||
</target> | |||
<target name="testsortdefault" depends="sortsetup"> | |||
<mysort property="sortdf" /> | |||
<fail> | |||
<condition> | |||
<not> | |||
<equals arg1="${sortdf}" arg2="a,b,c" /> | |||
</not> | |||
</condition> | |||
</fail> | |||
</target> | |||
<target name="testrvdefault" depends="sortsetup"> | |||
<mysort property="sortdf-rev"> | |||
<rcmp:reverse /> | |||
</mysort> | |||
<fail> | |||
<condition> | |||
<not> | |||
<equals arg1="${sortdf-rev}" arg2="c,b,a" /> | |||
</not> | |||
</condition> | |||
</fail> | |||
</target> | |||
<target name="testname" depends="sortsetup"> | |||
<mysort property="sortnm"> | |||
<rcmp:name /> | |||
</mysort> | |||
<fail> | |||
<condition> | |||
<not> | |||
<equals arg1="${sortnm}" arg2="a,b,c" /> | |||
</not> | |||
</condition> | |||
</fail> | |||
</target> | |||
<target name="testrvname" depends="sortsetup"> | |||
<mysort property="sortnm-rev"> | |||
<rcmp:reverse> | |||
<rcmp:name /> | |||
</rcmp:reverse> | |||
</mysort> | |||
<fail> | |||
<condition> | |||
<not> | |||
<equals arg1="${sortnm-rev}" arg2="c,b,a" /> | |||
</not> | |||
</condition> | |||
</fail> | |||
</target> | |||
<target name="testdate" depends="sortsetup"> | |||
<mysort property="sortlm"> | |||
<rcmp:date /> | |||
</mysort> | |||
<fail> | |||
<condition> | |||
<not> | |||
<equals arg1="${sortlm}" arg2="b,c,a" /> | |||
</not> | |||
</condition> | |||
</fail> | |||
</target> | |||
<target name="testrvdate" depends="sortsetup"> | |||
<mysort property="sortlm-rev"> | |||
<rcmp:reverse> | |||
<rcmp:date /> | |||
</rcmp:reverse> | |||
</mysort> | |||
<fail> | |||
<condition> | |||
<not> | |||
<equals arg1="${sortlm-rev}" arg2="a,c,b" /> | |||
</not> | |||
</condition> | |||
</fail> | |||
</target> | |||
<target name="testsize" depends="sortsetup"> | |||
<mysort property="sortsz"> | |||
<rcmp:size /> | |||
</mysort> | |||
<fail> | |||
<condition> | |||
<not> | |||
<equals arg1="${sortsz}" arg2="c,a,b" /> | |||
</not> | |||
</condition> | |||
</fail> | |||
</target> | |||
<target name="testrvsize" depends="sortsetup"> | |||
<mysort property="sortsz-rev"> | |||
<rcmp:reverse> | |||
<rcmp:size /> | |||
</rcmp:reverse> | |||
</mysort> | |||
<fail> | |||
<condition> | |||
<not> | |||
<equals arg1="${sortsz-rev}" arg2="b,a,c" /> | |||
</not> | |||
</condition> | |||
</fail> | |||
</target> | |||
<target name="testcontent" depends="sortsetup"> | |||
<mysort property="sortct"> | |||
<rcmp:content /> | |||
</mysort> | |||
<fail> | |||
<condition> | |||
<not> | |||
<equals arg1="${sortct}" arg2="c,b,a" /> | |||
</not> | |||
</condition> | |||
</fail> | |||
</target> | |||
<target name="testrvcontent" depends="sortsetup"> | |||
<mysort property="sortct-rev"> | |||
<rcmp:reverse> | |||
<rcmp:content /> | |||
</rcmp:reverse> | |||
</mysort> | |||
<fail> | |||
<condition> | |||
<not> | |||
<equals arg1="${sortct-rev}" arg2="a,b,c" /> | |||
</not> | |||
</condition> | |||
</fail> | |||
</target> | |||
<target name="testexists" depends="sortsetup"> | |||
<pathconvert property="sortex" pathsep=","> | |||
<sort> | |||
<resources> | |||
<file file="${dir}/a" /> | |||
<resource name="redherring" exists="false" /> | |||
</resources> | |||
<rcmp:exists /> | |||
</sort> | |||
<flattenmapper /> | |||
</pathconvert> | |||
<fail> | |||
<condition> | |||
<not> | |||
<equals arg1="${sortex}" arg2="redherring,a" /> | |||
</not> | |||
</condition> | |||
</fail> | |||
</target> | |||
<target name="testrvexists" depends="sortsetup"> | |||
<pathconvert property="sortex-rev" pathsep=","> | |||
<sort> | |||
<resources> | |||
<file file="${dir}/a" /> | |||
<resource name="redherring" exists="false" /> | |||
</resources> | |||
<rcmp:reverse> | |||
<rcmp:exists /> | |||
</rcmp:reverse> | |||
</sort> | |||
<flattenmapper /> | |||
</pathconvert> | |||
<fail> | |||
<condition> | |||
<not> | |||
<equals arg1="${sortex-rev}" arg2="a,redherring" /> | |||
</not> | |||
</condition> | |||
</fail> | |||
</target> | |||
<target name="testtype" depends="sortsetup"> | |||
<pathconvert property="sorttp" pathsep=","> | |||
<sort> | |||
<resources> | |||
<file file="${dir}/a" /> | |||
<file file="${dir}/a.dir" /> | |||
</resources> | |||
<rcmp:type /> | |||
</sort> | |||
<flattenmapper /> | |||
</pathconvert> | |||
<fail> | |||
<condition> | |||
<not> | |||
<equals arg1="${sorttp}" arg2="a,a.dir" /> | |||
</not> | |||
</condition> | |||
</fail> | |||
</target> | |||
<target name="testrvtype" depends="sortsetup"> | |||
<pathconvert property="sorttp-rev" pathsep=","> | |||
<sort> | |||
<resources> | |||
<file file="${dir}/a" /> | |||
<file file="${dir}/a.dir" /> | |||
</resources> | |||
<rcmp:reverse> | |||
<rcmp:type /> | |||
</rcmp:reverse> | |||
</sort> | |||
<flattenmapper /> | |||
</pathconvert> | |||
<fail> | |||
<condition> | |||
<not> | |||
<equals arg1="${sorttp-rev}" arg2="a.dir,a" /> | |||
</not> | |||
</condition> | |||
</fail> | |||
</target> | |||
<target name="forwardsort" | |||
depends="testsortdefault,testname,testdate,testsize,testcontent,testexists,testtype" /> | |||
<target name="reversesort" | |||
depends="testrvdefault,testrvname,testrvdate,testrvsize,testrvcontent,testrvexists,testrvtype" /> | |||
<target name="testcompoundsort1" depends="sortsetup"> | |||
<pathconvert property="sortcmp1" pathsep=","> | |||
<sort> | |||
<resources> | |||
<file file="${dir}/c" /> | |||
<file file="${dir}/b.dir" /> | |||
<file file="${dir}/a" /> | |||
<file file="${dir}/c.dir" /> | |||
<file file="${dir}/b" /> | |||
<file file="${dir}/a.dir" /> | |||
</resources> | |||
<rcmp:reverse> | |||
<rcmp:type /> | |||
</rcmp:reverse> | |||
<rcmp:name /> | |||
</sort> | |||
<flattenmapper /> | |||
</pathconvert> | |||
<fail> | |||
<condition> | |||
<not> | |||
<equals arg1="${sortcmp1}" arg2="a.dir,b.dir,c.dir,a,b,c" /> | |||
</not> | |||
</condition> | |||
</fail> | |||
</target> | |||
<target name="testcompoundsort2" depends="sortsetup"> | |||
<pathconvert property="sortcmp2" pathsep=","> | |||
<sort> | |||
<files includes="${dir}/?" /> | |||
<rcmp:size /> | |||
<rcmp:content /> | |||
<rcmp:reverse> | |||
<rcmp:name /> | |||
</rcmp:reverse> | |||
</sort> | |||
<flattenmapper /> | |||
</pathconvert> | |||
<fail> | |||
<condition> | |||
<not> | |||
<equals arg1="${sortcmp2}" arg2="d,c,f,a,e,b" /> | |||
</not> | |||
</condition> | |||
</fail> | |||
</target> | |||
<target name="compoundsort" depends="testcompoundsort1,testcompoundsort2" /> | |||
<target name="sort" depends="forwardsort,reversesort,compoundsort" /> | |||
</project> |
@@ -0,0 +1,410 @@ | |||
<project default="all" | |||
xmlns:rsel="antlib:org.apache.tools.ant.types.resources.selectors"> | |||
<target name="testname1"> | |||
<fail> | |||
<condition> | |||
<not> | |||
<resourcecount when="equal" count="2"> | |||
<restrict> | |||
<resources> | |||
<resource name="foo" /> | |||
<resource name="bar" /> | |||
<resource name="baz" /> | |||
<resource name="boo" /> | |||
<resource name="bang" /> | |||
</resources> | |||
<rsel:name name="ba?" /> | |||
</restrict> | |||
</resourcecount> | |||
</not> | |||
</condition> | |||
</fail> | |||
</target> | |||
<target name="testname2"> | |||
<fail> | |||
<condition> | |||
<not> | |||
<resourcecount when="equal" count="2"> | |||
<restrict> | |||
<resources> | |||
<file file="foo" /> | |||
<resource name="foo" /> | |||
<file file="foo" base="${basedir}" /> | |||
</resources> | |||
<rsel:name name="foo" /> | |||
</restrict> | |||
</resourcecount> | |||
</not> | |||
</condition> | |||
</fail> | |||
</target> | |||
<target name="name" depends="testname1,testname2" /> | |||
<target name="testexists"> | |||
<fail> | |||
<condition> | |||
<not> | |||
<resourcecount when="equal" count="1"> | |||
<restrict> | |||
<resources> | |||
<file file="idonotexist" /> | |||
<resource name="foo" /> | |||
<resource name="foo" exists="false" /> | |||
</resources> | |||
<rsel:exists /> | |||
</restrict> | |||
</resourcecount> | |||
</not> | |||
</condition> | |||
</fail> | |||
</target> | |||
<target name="testinstanceoftype1"> | |||
<fail> | |||
<condition> | |||
<not> | |||
<resourcecount when="equal" count="2"> | |||
<restrict> | |||
<resources> | |||
<file file="foo" /> | |||
<url url="http://ant.apache.org/index.html" /> | |||
<resource name="foo" /> | |||
<string value="foo" /> | |||
<file file="bar" /> | |||
</resources> | |||
<rsel:instanceof type="file" /> | |||
</restrict> | |||
</resourcecount> | |||
</not> | |||
</condition> | |||
</fail> | |||
</target> | |||
<target name="testinstanceoftype2"> | |||
<typedef name="file" uri="test" | |||
classname="org.apache.tools.ant.types.resources.FileResource" /> | |||
<fail> | |||
<condition> | |||
<not> | |||
<resourcecount when="equal" count="1"> | |||
<restrict> | |||
<resources> | |||
<url file="foo" /> | |||
<file file="bar" xmlns="test" /> | |||
</resources> | |||
<rsel:instanceof type="test:file" /> | |||
</restrict> | |||
</resourcecount> | |||
</not> | |||
</condition> | |||
</fail> | |||
</target> | |||
<target name="testinstanceoftype3"> | |||
<typedef name="file" uri="test" | |||
classname="org.apache.tools.ant.types.resources.FileResource" /> | |||
<fail> | |||
<condition> | |||
<not> | |||
<resourcecount when="equal" count="1"> | |||
<restrict> | |||
<resources> | |||
<url file="foo" /> | |||
<file file="bar" xmlns="test" /> | |||
</resources> | |||
<rsel:instanceof type="file" uri="test" /> | |||
</restrict> | |||
</resourcecount> | |||
</not> | |||
</condition> | |||
</fail> | |||
</target> | |||
<target name="testinstanceoftype" | |||
depends="testinstanceoftype1,testinstanceoftype2,testinstanceoftype3" /> | |||
<target name="testinstanceofclass"> | |||
<fail> | |||
<condition> | |||
<not> | |||
<resourcecount when="equal" count="7"> | |||
<restrict> | |||
<resources> | |||
<filelist dir="${basedir}" files="a,b,c,d,e,f,g" /> | |||
</resources> | |||
<rsel:instanceof class="org.apache.tools.ant.types.Resource" /> | |||
</restrict> | |||
</resourcecount> | |||
</not> | |||
</condition> | |||
</fail> | |||
</target> | |||
<target name="instanceof" depends="testinstanceoftype,testinstanceofclass" /> | |||
<target name="testtype"> | |||
<fail> | |||
<condition> | |||
<not> | |||
<resourcecount when="equal" count="2"> | |||
<restrict> | |||
<resources> | |||
<file file="${basedir}" /> | |||
<file file="${ant.file}" /> | |||
<resource directory="true" /> | |||
<resource directory="false" /> | |||
</resources> | |||
<rsel:type type="dir" /> | |||
</restrict> | |||
</resourcecount> | |||
</not> | |||
</condition> | |||
</fail> | |||
</target> | |||
<target name="testdate"> | |||
<fail> | |||
<condition> | |||
<not> | |||
<resourcecount when="equal" count="3"> | |||
<restrict> | |||
<resources> | |||
<resource lastmodified="4" /> | |||
<resource lastmodified="5" /> | |||
<resource lastmodified="6" /> | |||
<resource lastmodified="7" /> | |||
<resource lastmodified="8" /> | |||
</resources> | |||
<rsel:date when="after" millis="5" granularity="0" /> | |||
</restrict> | |||
</resourcecount> | |||
</not> | |||
</condition> | |||
</fail> | |||
</target> | |||
<target name="testsize"> | |||
<fail> | |||
<condition> | |||
<not> | |||
<resourcecount when="equal" count="4"> | |||
<restrict> | |||
<resources> | |||
<resource size="4" /> | |||
<resource size="5" /> | |||
<resource size="6" /> | |||
<resource size="7" /> | |||
<resource size="8" /> | |||
</resources> | |||
<rsel:size when="le" size="7" /> | |||
</restrict> | |||
</resourcecount> | |||
</not> | |||
</condition> | |||
</fail> | |||
</target> | |||
<target name="testand"> | |||
<fail> | |||
<condition> | |||
<not> | |||
<resourcecount when="equal" count="1"> | |||
<restrict> | |||
<resources> | |||
<string value="fee" /> | |||
<resource name="fi" size="3" /> | |||
<resource name="fo" /> | |||
<resource name="fum" /> | |||
</resources> | |||
<and xmlns="antlib:org.apache.tools.ant.types.resources.selectors"> | |||
<name name="f?" /> | |||
<size size="3" /> | |||
</and> | |||
</restrict> | |||
</resourcecount> | |||
</not> | |||
</condition> | |||
</fail> | |||
</target> | |||
<target name="testor"> | |||
<fail> | |||
<condition> | |||
<not> | |||
<resourcecount when="equal" count="3"> | |||
<restrict> | |||
<resources> | |||
<string value="fee" /> | |||
<resource name="fi" size="3" /> | |||
<resource name="fo" /> | |||
<resource name="fum" /> | |||
</resources> | |||
<or xmlns="antlib:org.apache.tools.ant.types.resources.selectors"> | |||
<name name="f?" /> | |||
<size size="3" /> | |||
</or> | |||
</restrict> | |||
</resourcecount> | |||
</not> | |||
</condition> | |||
</fail> | |||
</target> | |||
<target name="testnot"> | |||
<fail> | |||
<condition> | |||
<not> | |||
<resourcecount when="equal" count="2"> | |||
<restrict> | |||
<resources> | |||
<string value="fee" /> | |||
<resource name="fi" size="3" /> | |||
<resource name="fo" /> | |||
<resource name="fum" /> | |||
</resources> | |||
<not xmlns="antlib:org.apache.tools.ant.types.resources.selectors"> | |||
<size size="3" /> | |||
</not> | |||
</restrict> | |||
</resourcecount> | |||
</not> | |||
</condition> | |||
</fail> | |||
</target> | |||
<target name="testnone"> | |||
<fail> | |||
<condition> | |||
<not> | |||
<resourcecount when="equal" count="1"> | |||
<restrict> | |||
<resources> | |||
<string value="fee" /> | |||
<resource name="fi" size="3" /> | |||
<resource name="fo" /> | |||
<resource name="fum" /> | |||
</resources> | |||
<none xmlns="antlib:org.apache.tools.ant.types.resources.selectors"> | |||
<name name="f?" /> | |||
<size size="3" /> | |||
</none> | |||
</restrict> | |||
</resourcecount> | |||
</not> | |||
</condition> | |||
</fail> | |||
</target> | |||
<target name="testmajority1"> | |||
<fail> | |||
<condition> | |||
<not> | |||
<resourcecount when="equal" count="2"> | |||
<restrict> | |||
<resources> | |||
<string value="fee" /> | |||
<resource name="fi" size="3" /> | |||
<resource name="fo" /> | |||
<resource name="fum" /> | |||
</resources> | |||
<majority xmlns="antlib:org.apache.tools.ant.types.resources.selectors"> | |||
<name name="f?" /> | |||
<size size="3" /> | |||
<instanceof type="string" /> | |||
</majority> | |||
</restrict> | |||
</resourcecount> | |||
</not> | |||
</condition> | |||
</fail> | |||
</target> | |||
<target name="testmajority2"> | |||
<fail> | |||
<condition> | |||
<not> | |||
<resourcecount when="equal" count="3"> | |||
<restrict> | |||
<resources> | |||
<string value="fee" /> | |||
<resource name="fi" size="3" /> | |||
<resource name="fo" /> | |||
<resource name="fum" /> | |||
</resources> | |||
<majority xmlns="antlib:org.apache.tools.ant.types.resources.selectors"> | |||
<name name="f?" /> | |||
<size size="3" /> | |||
<instanceof type="resource" /> | |||
</majority> | |||
</restrict> | |||
</resourcecount> | |||
</not> | |||
</condition> | |||
</fail> | |||
</target> | |||
<target name="testmajority3"> | |||
<fail> | |||
<condition> | |||
<not> | |||
<resourcecount when="equal" count="3"> | |||
<restrict> | |||
<resources> | |||
<string value="fee" /> | |||
<resource name="fi" size="3" /> | |||
<resource name="fo" /> | |||
<resource name="fum" /> | |||
</resources> | |||
<majority allowtie="true" | |||
xmlns="antlib:org.apache.tools.ant.types.resources.selectors"> | |||
<name name="f?" /> | |||
<size size="3" /> | |||
<instanceof type="string" /> | |||
<exists /> | |||
</majority> | |||
</restrict> | |||
</resourcecount> | |||
</not> | |||
</condition> | |||
</fail> | |||
</target> | |||
<target name="testmajority4"> | |||
<fail> | |||
<condition> | |||
<not> | |||
<resourcecount when="equal" count="2"> | |||
<restrict> | |||
<resources> | |||
<string value="fee" /> | |||
<resource name="fi" size="3" /> | |||
<resource name="fo" /> | |||
<resource name="fum" /> | |||
</resources> | |||
<majority allowtie="false" | |||
xmlns="antlib:org.apache.tools.ant.types.resources.selectors"> | |||
<name name="f?" /> | |||
<size size="3" /> | |||
<instanceof type="string" /> | |||
<exists /> | |||
</majority> | |||
</restrict> | |||
</resourcecount> | |||
</not> | |||
</condition> | |||
</fail> | |||
</target> | |||
<target name="majority" | |||
depends="testmajority1,testmajority2,testmajority3,testmajority4" /> | |||
<target name="logical" | |||
depends="testand,testor,testnone,testnot,majority" /> | |||
<target name="all" | |||
depends="name,testexists,instanceof,testtype,testdate,testsize,logical" /> | |||
</project> |
@@ -17,34 +17,46 @@ | |||
package org.apache.tools.ant.taskdefs; | |||
import java.io.File; | |||
import java.io.Reader; | |||
import java.io.Writer; | |||
import java.io.FileReader; | |||
import java.io.InputStream; | |||
import java.io.IOException; | |||
import java.io.PrintWriter; | |||
import java.io.OutputStream; | |||
import java.io.StringReader; | |||
import java.io.BufferedReader; | |||
import java.io.BufferedWriter; | |||
import java.io.File; | |||
import java.io.FileInputStream; | |||
import java.io.FileOutputStream; | |||
import java.io.FileReader; | |||
import java.io.IOException; | |||
import java.io.InputStreamReader; | |||
import java.io.OutputStream; | |||
import java.io.OutputStreamWriter; | |||
import java.io.PrintWriter; | |||
import java.io.Reader; | |||
import java.io.StringReader; | |||
import java.io.Writer; | |||
import java.util.Enumeration; | |||
import java.util.Iterator; | |||
import java.util.Arrays; | |||
import java.util.Vector; | |||
import java.util.Iterator; | |||
import java.util.Enumeration; | |||
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.Project; | |||
import org.apache.tools.ant.ProjectComponent; | |||
import org.apache.tools.ant.Task; | |||
import org.apache.tools.ant.filters.util.ChainReaderHelper; | |||
import org.apache.tools.ant.types.FileList; | |||
import org.apache.tools.ant.types.Path; | |||
import org.apache.tools.ant.types.FileSet; | |||
import org.apache.tools.ant.types.FileList; | |||
import org.apache.tools.ant.types.FilterChain; | |||
import org.apache.tools.ant.types.Path; | |||
import org.apache.tools.ant.types.Resource; | |||
import org.apache.tools.ant.types.ResourceCollection; | |||
import org.apache.tools.ant.types.resources.Restrict; | |||
import org.apache.tools.ant.types.resources.Resources; | |||
import org.apache.tools.ant.types.resources.FileResource; | |||
import org.apache.tools.ant.types.resources.StringResource; | |||
import org.apache.tools.ant.types.resources.selectors.Not; | |||
import org.apache.tools.ant.types.resources.selectors.Exists; | |||
import org.apache.tools.ant.types.resources.selectors.ResourceSelector; | |||
import org.apache.tools.ant.util.FileUtils; | |||
import org.apache.tools.ant.util.ConcatResourceInputStream; | |||
/** | |||
* This class contains the 'concat' task, used to concatenate a series | |||
@@ -68,32 +80,36 @@ public class Concat extends Task { | |||
// The size of buffers to be used | |||
private static final int BUFFER_SIZE = 8192; | |||
private static final FileUtils FILE_UTILS = FileUtils.getFileUtils(); | |||
private static final FileUtils FILE_UTILS = FileUtils.getFileUtils(); | |||
private static final ResourceSelector EXISTS = new Exists(); | |||
private static final ResourceSelector NOT_EXISTS = new Not(EXISTS); | |||
// Attributes. | |||
/** | |||
* The destination of the stream. If <code>null</code>, the system | |||
* console is used. | |||
*/ | |||
private File destinationFile = null; | |||
private File destinationFile; | |||
/** | |||
* Whether or not the stream should be appended if the destination file | |||
* exists. | |||
* Defaults to <code>false</code>. | |||
*/ | |||
private boolean append = false; | |||
private boolean append; | |||
/** | |||
* Stores the input file encoding. | |||
*/ | |||
private String encoding = null; | |||
private String encoding; | |||
/** Stores the output file encoding. */ | |||
private String outputEncoding = null; | |||
private String outputEncoding; | |||
/** Stores the binary attribute */ | |||
private boolean binary = false; | |||
private boolean binary; | |||
// Child elements. | |||
@@ -106,25 +122,49 @@ public class Concat extends Task { | |||
* Stores a collection of file sets and/or file lists, used to | |||
* select multiple files for concatenation. | |||
*/ | |||
private Vector sources = new Vector(); | |||
private Resources rc; | |||
/** for filtering the concatenated */ | |||
private Vector filterChains = null; | |||
private Vector filterChains; | |||
/** ignore dates on input files */ | |||
private boolean forceOverwrite = true; | |||
private boolean forceOverwrite = true; | |||
/** String to place at the start of the concatented stream */ | |||
private TextElement footer; | |||
private TextElement footer; | |||
/** String to place at the end of the concatented stream */ | |||
private TextElement header; | |||
private TextElement header; | |||
/** add missing line.separator to files **/ | |||
private boolean fixLastLine = false; | |||
private boolean fixLastLine = false; | |||
/** endofline for fixlast line */ | |||
private String eolString = System.getProperty("line.separator"); | |||
private String eolString; | |||
/** outputwriter */ | |||
private Writer outputWriter = null; | |||
private Writer outputWriter = null; | |||
/** internal variable - used to collect the source files from sources */ | |||
private Vector sourceFiles = new Vector(); | |||
/** | |||
* Construct a new Concat task. | |||
*/ | |||
public Concat() { | |||
reset(); | |||
} | |||
/** | |||
* Reset state to default. | |||
*/ | |||
public void reset() { | |||
append = false; | |||
forceOverwrite = true; | |||
destinationFile = null; | |||
encoding = null; | |||
outputEncoding = null; | |||
fixLastLine = false; | |||
filterChains = null; | |||
footer = null; | |||
header = null; | |||
binary = false; | |||
outputWriter = null; | |||
textBuffer = null; | |||
eolString = System.getProperty("line.separator"); | |||
rc = null; | |||
} | |||
// Attribute setters. | |||
@@ -187,7 +227,7 @@ public class Concat extends Task { | |||
*/ | |||
public Path createPath() { | |||
Path path = new Path(getProject()); | |||
sources.addElement(path); | |||
add(path); | |||
return path; | |||
} | |||
@@ -196,7 +236,7 @@ public class Concat extends Task { | |||
* @param set the set of files | |||
*/ | |||
public void addFileset(FileSet set) { | |||
sources.addElement(set); | |||
add(set); | |||
} | |||
/** | |||
@@ -204,7 +244,17 @@ public class Concat extends Task { | |||
* @param list the list of files | |||
*/ | |||
public void addFilelist(FileList list) { | |||
sources.addElement(list); | |||
add(list); | |||
} | |||
/** | |||
* Add an arbitrary ResourceCollection. | |||
* @param c the ResourceCollection to add. | |||
* @since Ant 1.7 | |||
*/ | |||
public void add(ResourceCollection c) { | |||
rc = (rc == null) ? new Resources() : rc; | |||
rc.add(c); | |||
} | |||
/** | |||
@@ -284,9 +334,9 @@ public class Concat extends Task { | |||
} | |||
/** | |||
* set the output writer, this is to allow | |||
* concat to be used as a nested element | |||
* @param outputWriter the output writer | |||
* Set the output writer. This is to allow | |||
* concat to be used as a nested element. | |||
* @param outputWriter the output writer. | |||
* @since Ant 1.6 | |||
*/ | |||
public void setWriter(Writer outputWriter) { | |||
@@ -294,23 +344,20 @@ public class Concat extends Task { | |||
} | |||
/** | |||
* set the binary attribute. | |||
* if true, concat will concatenate the files | |||
* byte for byte. This mode does not allow | |||
* any filtering, or other modifications | |||
* to the input streams. | |||
* The default value is false. | |||
* @since ant 1.6.2 | |||
* @param binary if true, enable binary mode | |||
* Set the binary attribute. If true, concat will concatenate the files | |||
* byte for byte. This mode does not allow any filtering or other | |||
* modifications to the input streams. The default value is false. | |||
* @since Ant 1.6.2 | |||
* @param binary if true, enable binary mode. | |||
*/ | |||
public void setBinary(boolean binary) { | |||
this.binary = binary; | |||
} | |||
/** | |||
* This method checks the attributes and performs the concatenation. | |||
* Validate configuration options. | |||
*/ | |||
private void checkAndExecute() { | |||
private ResourceCollection validate() { | |||
// treat empty nested text as no text | |||
sanitizeText(); | |||
@@ -319,9 +366,8 @@ public class Concat extends Task { | |||
if (binary) { | |||
if (destinationFile == null) { | |||
throw new BuildException( | |||
"DestFile attribute is required for binary concatenation"); | |||
"destfile attribute is required for binary concatenation"); | |||
} | |||
if (textBuffer != null) { | |||
throw new BuildException( | |||
"Nested text is incompatible with binary concatenation"); | |||
@@ -344,187 +390,117 @@ public class Concat extends Task { | |||
"Nested header or footer is incompatible with binary concatenation"); | |||
} | |||
} | |||
if (destinationFile != null && outputWriter != null) { | |||
throw new BuildException( | |||
"Cannot specify both a destination file and an output writer"); | |||
} | |||
// Sanity check our inputs. | |||
if (sources.size() == 0 && textBuffer == null) { | |||
if (rc == null && textBuffer == null) { | |||
// Nothing to concatenate! | |||
throw new BuildException( | |||
"At least one file must be provided, or some text."); | |||
"At least one resource must be provided, or some text."); | |||
} | |||
// If using filesets, disallow inline text. This is similar to | |||
// using GNU 'cat' with file arguments -- stdin is simply | |||
// ignored. | |||
if (sources.size() > 0 && textBuffer != null) { | |||
throw new BuildException( | |||
"Cannot include inline text when using filesets."); | |||
} | |||
// Iterate thru the sources - paths, filesets and filelists | |||
for (Enumeration e = sources.elements(); e.hasMoreElements();) { | |||
Object o = e.nextElement(); | |||
if (o instanceof Path) { | |||
Path path = (Path) o; | |||
checkAddFiles(null, path.list()); | |||
} else if (o instanceof FileSet) { | |||
FileSet fileSet = (FileSet) o; | |||
DirectoryScanner scanner = | |||
fileSet.getDirectoryScanner(getProject()); | |||
checkAddFiles(fileSet.getDir(getProject()), | |||
scanner.getIncludedFiles()); | |||
} else if (o instanceof FileList) { | |||
FileList fileList = (FileList) o; | |||
checkAddFiles(fileList.getDir(getProject()), | |||
fileList.getFiles(getProject())); | |||
} | |||
} | |||
// check if the files are outofdate | |||
if (destinationFile != null && !forceOverwrite | |||
&& (sourceFiles.size() > 0) && destinationFile.exists()) { | |||
boolean outofdate = false; | |||
for (int i = 0; i < sourceFiles.size(); ++i) { | |||
File file = (File) sourceFiles.elementAt(i); | |||
if (file.lastModified() > destinationFile.lastModified()) { | |||
outofdate = true; | |||
break; | |||
if (rc != null) { | |||
// If using resources, disallow inline text. This is similar to | |||
// using GNU 'cat' with file arguments -- stdin is simply | |||
// ignored. | |||
if (textBuffer != null) { | |||
throw new BuildException( | |||
"Cannot include inline text when using resources."); | |||
} | |||
Restrict noexistRc = new Restrict(); | |||
noexistRc.add(NOT_EXISTS); | |||
noexistRc.add(rc); | |||
for (Iterator i = noexistRc.iterator(); i.hasNext();) { | |||
log(i.next() + " does not exist.", Project.MSG_ERR); | |||
} | |||
if (destinationFile != null) { | |||
for (Iterator i = rc.iterator(); i.hasNext();) { | |||
Object o = i.next(); | |||
if (o instanceof FileResource) { | |||
File f = ((FileResource) o).getFile(); | |||
if (FILE_UTILS.fileNameEquals(f, destinationFile)) { | |||
throw new BuildException("Input file \"" | |||
+ f + "\" is the same as the output file."); | |||
} | |||
} | |||
} | |||
} | |||
Restrict existRc = new Restrict(); | |||
existRc.add(EXISTS); | |||
existRc.add(rc); | |||
boolean outofdate = destinationFile == null || forceOverwrite; | |||
if (!outofdate) { | |||
for (Iterator i = existRc.iterator(); !outofdate && i.hasNext();) { | |||
Resource r = (Resource) i.next(); | |||
} | |||
} | |||
if (!outofdate) { | |||
log(destinationFile + " is up-to-date.", Project.MSG_VERBOSE); | |||
return; // no need to do anything | |||
return null; // no need to do anything | |||
} | |||
} | |||
// Do nothing if all the sources are not present | |||
// And textBuffer is null | |||
if (textBuffer == null && sourceFiles.size() == 0 | |||
&& header == null && footer == null) { | |||
log("No existing files and no nested text, doing nothing", | |||
Project.MSG_INFO); | |||
return; | |||
} | |||
if (binary) { | |||
binaryCat(); | |||
return existRc; | |||
} else { | |||
cat(); | |||
StringResource s = new StringResource(); | |||
s.setProject(getProject()); | |||
s.setValue(textBuffer.toString()); | |||
return s; | |||
} | |||
} | |||
/** | |||
* execute the concat task. | |||
* Execute the concat task. | |||
*/ | |||
public void execute() { | |||
try { | |||
checkAndExecute(); | |||
} finally { | |||
resetTask(); | |||
ResourceCollection c = validate(); | |||
if (c == null) { | |||
return; | |||
} | |||
} | |||
/** | |||
* Reset state to default. | |||
*/ | |||
public void reset() { | |||
append = false; | |||
forceOverwrite = true; | |||
destinationFile = null; | |||
encoding = null; | |||
outputEncoding = null; | |||
fixLastLine = false; | |||
sources.removeAllElements(); | |||
sourceFiles.removeAllElements(); | |||
filterChains = null; | |||
footer = null; | |||
header = null; | |||
} | |||
/** | |||
* reset the used variables to allow the same task | |||
* instance to be used again. | |||
*/ | |||
private void resetTask() { | |||
sourceFiles.clear(); | |||
} | |||
private void checkAddFiles(File base, String[] filenames) { | |||
for (int i = 0; i < filenames.length; ++i) { | |||
File file = new File(base, filenames[i]); | |||
if (!file.exists()) { | |||
log("File " + file + " does not exist.", Project.MSG_ERR); | |||
continue; | |||
} | |||
if (destinationFile != null | |||
&& FILE_UTILS.fileNameEquals(destinationFile, file)) { | |||
throw new BuildException("Input file \"" | |||
+ file + "\" " | |||
+ "is the same as the output file."); | |||
} | |||
sourceFiles.addElement(file); | |||
// Do nothing if no resources (including nested text) | |||
if (c.size() < 1 && header == null && footer == null) { | |||
log("No existing resources and no nested text, doing nothing", | |||
Project.MSG_INFO); | |||
return; | |||
} | |||
if (binary) { | |||
binaryCat(c); | |||
} else { | |||
cat(c); | |||
} | |||
} | |||
/** perform the binary concatenation */ | |||
private void binaryCat() { | |||
log("Binary concatenation of " + sourceFiles.size() | |||
+ " files to " + destinationFile); | |||
private void binaryCat(ResourceCollection c) { | |||
log("Binary concatenation of " + c.size() | |||
+ " resources to " + destinationFile); | |||
FileOutputStream out = null; | |||
FileInputStream in = null; | |||
InputStream in = null; | |||
byte[] buffer = new byte[BUFFER_SIZE]; | |||
try { | |||
try { | |||
out = new FileOutputStream(destinationFile); | |||
} catch (Exception t) { | |||
throw new BuildException( | |||
"Unable to open " + destinationFile | |||
+ " for writing", t); | |||
throw new BuildException("Unable to open " | |||
+ destinationFile + " for writing", t); | |||
} | |||
for (Iterator i = sourceFiles.iterator(); i.hasNext();) { | |||
File sourceFile = (File) i.next(); | |||
try { | |||
in = new FileInputStream(sourceFile); | |||
} catch (Exception t) { | |||
throw new BuildException( | |||
"Unable to open input file " + sourceFile, | |||
t); | |||
} | |||
int count = 0; | |||
do { | |||
try { | |||
count = in.read(buffer, 0, buffer.length); | |||
} catch (Exception t) { | |||
throw new BuildException( | |||
"Unable to read from " + sourceFile, t); | |||
} | |||
try { | |||
if (count > 0) { | |||
out.write(buffer, 0, count); | |||
} | |||
} catch (Exception t) { | |||
throw new BuildException( | |||
"Unable to write to " + destinationFile, t); | |||
} | |||
} while (count > 0); | |||
try { | |||
in = new ConcatResourceInputStream(c); | |||
((ConcatResourceInputStream) in).setManagingComponent(this); | |||
} catch (IOException e) { | |||
throw new BuildException(e); | |||
} | |||
Thread t = new Thread(new StreamPumper(in, out)); | |||
t.start(); | |||
try { | |||
t.join(); | |||
} catch (InterruptedException e) { | |||
try { | |||
in.close(); | |||
} catch (Exception t) { | |||
throw new BuildException( | |||
"Unable to close " + sourceFile, t); | |||
t.join(); | |||
} catch (InterruptedException ee) { | |||
} | |||
in = null; | |||
} | |||
} finally { | |||
FileUtils.close(in); | |||
if (out != null) { | |||
try { | |||
out.close(); | |||
@@ -537,13 +513,11 @@ public class Concat extends Task { | |||
} | |||
/** perform the concatenation */ | |||
private void cat() { | |||
private void cat(ResourceCollection c) { | |||
OutputStream os = null; | |||
Reader reader = null; | |||
char[] buffer = new char[BUFFER_SIZE]; | |||
char[] buffer = new char[BUFFER_SIZE]; | |||
try { | |||
PrintWriter writer = null; | |||
if (outputWriter != null) { | |||
@@ -558,11 +532,9 @@ public class Concat extends Task { | |||
if (!parent.exists()) { | |||
parent.mkdirs(); | |||
} | |||
os = new FileOutputStream(destinationFile.getAbsolutePath(), | |||
append); | |||
} | |||
if (outputEncoding == null) { | |||
writer = new PrintWriter( | |||
new BufferedWriter( | |||
@@ -573,7 +545,6 @@ public class Concat extends Task { | |||
new OutputStreamWriter(os, outputEncoding))); | |||
} | |||
} | |||
if (header != null) { | |||
if (header.getFiltering()) { | |||
concatenate( | |||
@@ -582,16 +553,9 @@ public class Concat extends Task { | |||
writer.print(header.getValue()); | |||
} | |||
} | |||
if (textBuffer != null) { | |||
reader = new StringReader( | |||
getProject().replaceProperties(textBuffer.substring(0))); | |||
} else { | |||
reader = new MultiReader(); | |||
if (c.size() > 0) { | |||
concatenate(buffer, writer, new MultiReader(c)); | |||
} | |||
concatenate(buffer, writer, reader); | |||
if (footer != null) { | |||
if (footer.getFiltering()) { | |||
concatenate( | |||
@@ -600,34 +564,18 @@ public class Concat extends Task { | |||
writer.print(footer.getValue()); | |||
} | |||
} | |||
writer.flush(); | |||
if (os != null) { | |||
os.flush(); | |||
} | |||
} catch (IOException ioex) { | |||
throw new BuildException("Error while concatenating: " | |||
+ ioex.getMessage(), ioex); | |||
} finally { | |||
if (reader != null) { | |||
try { | |||
reader.close(); | |||
} catch (IOException ignore) { | |||
// ignore | |||
} | |||
} | |||
if (os != null) { | |||
try { | |||
os.close(); | |||
} catch (IOException ignore) { | |||
// ignore | |||
} | |||
} | |||
FILE_UTILS.close(os); | |||
} | |||
} | |||
/** Concatenate a single reader to the writer using buffer */ | |||
private void concatenate(char[] buffer, Writer writer, Reader in) | |||
throws IOException { | |||
@@ -639,7 +587,6 @@ public class Concat extends Task { | |||
helper.setProject(getProject()); | |||
in = new BufferedReader(helper.getAssembledReader()); | |||
} | |||
while (true) { | |||
int nRead = in.read(buffer, 0, buffer.length); | |||
if (nRead == -1) { | |||
@@ -647,7 +594,6 @@ public class Concat extends Task { | |||
} | |||
writer.write(buffer, 0, nRead); | |||
} | |||
writer.flush(); | |||
} | |||
@@ -796,34 +742,34 @@ public class Concat extends Task { | |||
* a single stream. | |||
*/ | |||
private class MultiReader extends Reader { | |||
private int pos = 0; | |||
private Reader reader = null; | |||
private int lastPos = 0; | |||
private char[] lastChars = new char[eolString.length()]; | |||
private boolean needAddSeparator = false; | |||
private Iterator i; | |||
private MultiReader(ResourceCollection c) { | |||
i = c.iterator(); | |||
} | |||
private Reader getReader() throws IOException { | |||
if (reader == null) { | |||
log("Concating file " + sourceFiles.elementAt(pos), | |||
Project.MSG_VERBOSE); | |||
if (encoding == null) { | |||
reader = new BufferedReader( | |||
new FileReader((File) sourceFiles.elementAt(pos))); | |||
} else { | |||
// invoke the zoo of io readers | |||
reader = new BufferedReader( | |||
new InputStreamReader( | |||
new FileInputStream( | |||
(File) sourceFiles.elementAt(pos)), | |||
encoding)); | |||
} | |||
for (int i = 0; i < lastChars.length; ++i) { | |||
lastChars[i] = 0; | |||
} | |||
if (reader == null && i.hasNext()) { | |||
Resource r = (Resource) i.next(); | |||
log("Concating " + r.toLongString(), Project.MSG_VERBOSE); | |||
InputStream is = r.getInputStream(); | |||
reader = new BufferedReader(encoding == null | |||
? new InputStreamReader(is) | |||
: new InputStreamReader(is, encoding)); | |||
Arrays.fill(lastChars, (char) 0); | |||
} | |||
return reader; | |||
} | |||
private void nextReader() throws IOException { | |||
close(); | |||
reader = null; | |||
} | |||
/** | |||
* Read a character from the current reader object. Advance | |||
* to the next if the reader is finished. | |||
@@ -840,12 +786,10 @@ public class Concat extends Task { | |||
} | |||
return ret; | |||
} | |||
while (pos < sourceFiles.size()) { | |||
while (getReader() != null) { | |||
int ch = getReader().read(); | |||
if (ch == -1) { | |||
reader.close(); | |||
reader = null; | |||
nextReader(); | |||
if (fixLastLine && isMissingEndOfLine()) { | |||
needAddSeparator = true; | |||
lastPos = 0; | |||
@@ -854,7 +798,6 @@ public class Concat extends Task { | |||
addLastChar((char) ch); | |||
return ch; | |||
} | |||
pos++; | |||
} | |||
return -1; | |||
} | |||
@@ -871,13 +814,12 @@ public class Concat extends Task { | |||
throws IOException { | |||
int amountRead = 0; | |||
while (pos < sourceFiles.size() || (needAddSeparator)) { | |||
while (getReader() != null || needAddSeparator) { | |||
if (needAddSeparator) { | |||
cbuf[off] = eolString.charAt(lastPos++); | |||
if (lastPos >= eolString.length()) { | |||
lastPos = 0; | |||
needAddSeparator = false; | |||
pos++; | |||
} | |||
len--; | |||
off++; | |||
@@ -889,13 +831,10 @@ public class Concat extends Task { | |||
} | |||
int nRead = getReader().read(cbuf, off, len); | |||
if (nRead == -1 || nRead == 0) { | |||
reader.close(); | |||
reader = null; | |||
nextReader(); | |||
if (fixLastLine && isMissingEndOfLine()) { | |||
needAddSeparator = true; | |||
lastPos = 0; | |||
} else { | |||
pos++; | |||
} | |||
} else { | |||
if (fixLastLine) { | |||
@@ -931,6 +870,7 @@ public class Concat extends Task { | |||
reader.close(); | |||
} | |||
} | |||
/** | |||
* if checking for end of line at end of file | |||
* add a character to the lastchars buffer | |||
@@ -21,18 +21,21 @@ import java.io.File; | |||
import java.io.PrintStream; | |||
import java.io.OutputStream; | |||
import java.io.ByteArrayOutputStream; | |||
import java.util.Vector; | |||
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.taskdefs.condition.Condition; | |||
import org.apache.tools.ant.types.FileSet; | |||
import org.apache.tools.ant.types.Resource; | |||
import org.apache.tools.ant.types.Comparison; | |||
import org.apache.tools.ant.types.ResourceCollection; | |||
import org.apache.tools.ant.types.EnumeratedAttribute; | |||
import org.apache.tools.ant.types.resources.Resources; | |||
import org.apache.tools.ant.types.resources.FileResource; | |||
import org.apache.tools.ant.util.FileUtils; | |||
import org.apache.tools.ant.util.PropertyOutputStream; | |||
/** | |||
* Gets lengths: of files/resources, byte size; of strings, length (optionally trimmed). | |||
@@ -52,9 +55,9 @@ public class Length extends Task implements Condition { | |||
private String string; | |||
private Boolean trim; | |||
private String mode = ALL; | |||
private When when = When.EQUAL; | |||
private Comparison when = Comparison.EQUAL; | |||
private Long length; | |||
private Vector filesets; | |||
private Resources resources; | |||
/** | |||
* The property in which the length will be stored. | |||
@@ -69,9 +72,7 @@ public class Length extends Task implements Condition { | |||
* @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(new FileResource(file)); | |||
} | |||
/** | |||
@@ -79,11 +80,20 @@ public class Length extends Task implements Condition { | |||
* @param fs the <code>FileSet</code> to add. | |||
*/ | |||
public synchronized void add(FileSet fs) { | |||
if (fs == null) { | |||
add((ResourceCollection) fs); | |||
} | |||
/** | |||
* Add a ResourceCollection. | |||
* @param c the <code>ResourceCollection</code> to add. | |||
* @since Ant 1.7 | |||
*/ | |||
public synchronized void add(ResourceCollection c) { | |||
if (c == null) { | |||
return; | |||
} | |||
filesets = (filesets == null) ? new Vector() : filesets; | |||
filesets.add(fs); | |||
resources = (resources == null) ? new Resources() : resources; | |||
resources.add(c); | |||
} | |||
/** | |||
@@ -95,12 +105,22 @@ public class Length extends Task implements Condition { | |||
} | |||
/** | |||
* Set the comparison criteria for use as a Condition: | |||
* "equal", "greater", "less". Default is "equal". | |||
* Set the comparison for use as a Condition. | |||
* @param w EnumeratedAttribute When. | |||
* @see org.apache.tools.ant.types.Comparison | |||
*/ | |||
public synchronized void setWhen(When w) { | |||
when = w; | |||
setWhen((Comparison) w); | |||
} | |||
/** | |||
* Set the comparison for use as a Condition. | |||
* @param c Comparison. | |||
* @see org.apache.tools.ant.types.Comparison | |||
* @since Ant 1.7 | |||
*/ | |||
public synchronized void setWhen(Comparison c) { | |||
when = c; | |||
} | |||
/** | |||
@@ -142,7 +162,7 @@ public class Length extends Task implements Condition { | |||
public void execute() { | |||
validate(); | |||
PrintStream ps = new PrintStream((property != null) | |||
? (OutputStream) new PropertyOutputStream() | |||
? (OutputStream) new PropertyOutputStream(getProject(), property) | |||
: (OutputStream) new LogOutputStream(this, Project.MSG_INFO)); | |||
if (STRING.equals(mode)) { | |||
@@ -173,27 +193,23 @@ public class Length extends Task implements Condition { | |||
handleResources(h); | |||
ell = new Long(h.getLength()); | |||
} | |||
int w = when.getIndex(); | |||
int comp = ell.compareTo(length); | |||
return (w == 0 && comp == 0) | |||
|| (w == 1 && comp > 0) | |||
|| (w == 2 && comp < 0); | |||
return when.evaluate(ell.compareTo(length)); | |||
} | |||
private void validate() { | |||
if (string != null) { | |||
if (filesets != null && filesets.size() > 0) { | |||
if (resources != null) { | |||
throw new BuildException("the string length function" | |||
+ " is incompatible with the file length function"); | |||
+ " is incompatible with the file/resource length function"); | |||
} | |||
if (!(STRING.equals(mode))) { | |||
throw new BuildException("the mode attribute is for use" | |||
+ " with the file/resource length function"); | |||
} | |||
} else if (filesets != null) { | |||
} else if (resources != null) { | |||
if (!(EACH.equals(mode) || ALL.equals(mode))) { | |||
throw new BuildException("invalid mode setting for" | |||
+ " file length function: \"" + mode + "\""); | |||
+ " file/resource length function: \"" + mode + "\""); | |||
} else if (trim != null) { | |||
throw new BuildException("the trim attribute is" | |||
+ " for use with the string length function only"); | |||
@@ -201,30 +217,20 @@ public class Length extends Task implements Condition { | |||
} else { | |||
throw new BuildException("you must set either the string attribute" | |||
+ " or specify one or more files using the file attribute or" | |||
+ " nested filesets"); | |||
+ " nested resource collections"); | |||
} | |||
} | |||
private void handleResources(Handler h) { | |||
for (Iterator i = filesets.iterator(); i.hasNext();) { | |||
FileSet fs = (FileSet) i.next(); | |||
DirectoryScanner ds = fs.getDirectoryScanner(getProject()); | |||
String[] f = ds.getIncludedFiles(); | |||
for (int j = 0; j < f.length; j++) { | |||
Resource r = ds.getResource(f[j]); | |||
if (!r.isExists()) { | |||
log(r.getName() + " does not exist", Project.MSG_ERR); | |||
} else if (r.isDirectory()) { | |||
log(r.getName() + " is a directory; length unspecified", | |||
Project.MSG_ERR); | |||
} else { | |||
//force a full path: | |||
File basedir = ds.getBasedir(); | |||
String s = FileUtils.getFileUtils().resolveFile( | |||
basedir, r.getName()).getAbsolutePath(); | |||
h.handle(new Resource(s, true, | |||
r.getLastModified(), false, r.getSize())); | |||
} | |||
for (Iterator i = resources.iterator(); i.hasNext();) { | |||
Resource r = (Resource) i.next(); | |||
if (!r.isExists()) { | |||
log(r + " does not exist", Project.MSG_ERR); | |||
} else if (r.isDirectory()) { | |||
log(r + " is a directory; length unspecified", | |||
Project.MSG_ERR); | |||
} else { | |||
h.handle(r); | |||
} | |||
} | |||
h.complete(); | |||
@@ -251,27 +257,8 @@ public class Length extends Task implements Condition { | |||
/** | |||
* EnumeratedAttribute for the when attribute. | |||
*/ | |||
public static class When extends EnumeratedAttribute { | |||
private static final String[] VALUES | |||
= new String[] {"equal", "greater", "less"}; | |||
private static final When EQUAL = new When("equal"); | |||
public When() { | |||
} | |||
public When(String value) { | |||
setValue(value); | |||
} | |||
public String[] getValues() { | |||
return VALUES; | |||
} | |||
} | |||
private class PropertyOutputStream extends ByteArrayOutputStream { | |||
public void close() { | |||
getProject().setNewProperty( | |||
property, new String(toByteArray()).trim()); | |||
} | |||
public static class When extends Comparison { | |||
//extend Comparison; retain for BC only | |||
} | |||
private abstract class Handler { | |||
@@ -292,7 +279,7 @@ public class Length extends Task implements Condition { | |||
super(ps); | |||
} | |||
protected void handle(Resource r) { | |||
ps.print(r.getName()); | |||
ps.print(r.toString()); | |||
ps.print(" : "); | |||
//when writing to the log, we'll see what's happening: | |||
long size = r.getSize(); | |||
@@ -312,7 +299,7 @@ public class Length extends Task implements Condition { | |||
protected synchronized void handle(Resource r) { | |||
long size = r.getSize(); | |||
if (size == Resource.UNKNOWN_SIZE) { | |||
log("Size unknown for " + r.getName(), Project.MSG_WARN); | |||
log("Size unknown for " + r.toString(), Project.MSG_WARN); | |||
} else { | |||
accum += size; | |||
} | |||
@@ -17,21 +17,23 @@ | |||
package org.apache.tools.ant.taskdefs; | |||
import java.io.File; | |||
import java.util.StringTokenizer; | |||
import java.util.Vector; | |||
import java.util.List; | |||
import java.util.Vector; | |||
import java.util.ArrayList; | |||
import org.apache.tools.ant.BuildException; | |||
import org.apache.tools.ant.Project; | |||
import java.util.StringTokenizer; | |||
import org.apache.tools.ant.Task; | |||
import org.apache.tools.ant.Project; | |||
import org.apache.tools.ant.BuildException; | |||
import org.apache.tools.ant.taskdefs.condition.Os; | |||
import org.apache.tools.ant.types.Path; | |||
import org.apache.tools.ant.types.DirSet; | |||
import org.apache.tools.ant.types.EnumeratedAttribute; | |||
import org.apache.tools.ant.types.FileList; | |||
import org.apache.tools.ant.types.Mapper; | |||
import org.apache.tools.ant.types.FileSet; | |||
import org.apache.tools.ant.types.Path; | |||
import org.apache.tools.ant.types.FileList; | |||
import org.apache.tools.ant.types.Reference; | |||
import org.apache.tools.ant.types.Mapper; | |||
import org.apache.tools.ant.types.ResourceCollection; | |||
import org.apache.tools.ant.types.EnumeratedAttribute; | |||
import org.apache.tools.ant.types.resources.Union; | |||
import org.apache.tools.ant.util.FileNameMapper; | |||
/** | |||
@@ -43,11 +45,16 @@ import org.apache.tools.ant.util.FileNameMapper; | |||
*/ | |||
public class PathConvert extends Task { | |||
/** | |||
* Set if we're running on windows | |||
*/ | |||
private static boolean onWindows = Os.isFamily("dos"); | |||
// Members | |||
/** | |||
* Path to be converted | |||
*/ | |||
private Path path = null; | |||
private Union path = null; | |||
/** | |||
* Reference to path/fileset to convert | |||
*/ | |||
@@ -60,10 +67,6 @@ public class PathConvert extends Task { | |||
* Set when targetOS is set to windows | |||
*/ | |||
private boolean targetWindows = false; | |||
/** | |||
* Set if we're running on windows | |||
*/ | |||
private boolean onWindows = false; | |||
/** | |||
* Set if we should create a new property even if the result is empty | |||
*/ | |||
@@ -92,7 +95,6 @@ public class PathConvert extends Task { | |||
* Construct a new instance of the PathConvert task. | |||
*/ | |||
public PathConvert() { | |||
onWindows = Os.isFamily("dos"); | |||
} | |||
/** | |||
@@ -164,17 +166,36 @@ public class PathConvert extends Task { | |||
} | |||
/** | |||
* Create a nested PATH element. | |||
* Create a nested path element. | |||
* @return a Path to be used by Ant reflection. | |||
*/ | |||
public Path createPath() { | |||
if (isReference()) { | |||
throw noChildrenAllowed(); | |||
} | |||
Path result = new Path(getProject()); | |||
add(result); | |||
return result; | |||
} | |||
/** | |||
* Add an arbitrary ResourceCollection. | |||
* @param rc the ResourceCollection to add. | |||
* @since Ant 1.7 | |||
*/ | |||
public void add(ResourceCollection rc) { | |||
if (isReference()) { | |||
throw noChildrenAllowed(); | |||
} | |||
getPath().add(rc); | |||
} | |||
private synchronized Union getPath() { | |||
if (path == null) { | |||
path = new Path(getProject()); | |||
path = new Union(); | |||
path.setProject(getProject()); | |||
} | |||
return path.createPath(); | |||
return path; | |||
} | |||
/** | |||
@@ -283,28 +304,19 @@ public class PathConvert extends Task { | |||
* @throws BuildException if something is invalid. | |||
*/ | |||
public void execute() throws BuildException { | |||
Path savedPath = path; | |||
Union savedPath = path; | |||
String savedPathSep = pathSep; // may be altered in validateSetup | |||
String savedDirSep = dirSep; // may be altered in validateSetup | |||
try { | |||
// If we are a reference, create a Path from the reference | |||
if (isReference()) { | |||
path = new Path(getProject()).createPath(); | |||
Object obj = refid.getReferencedObject(getProject()); | |||
if (obj instanceof Path) { | |||
path.setRefid(refid); | |||
} else if (obj instanceof FileSet) { | |||
path.addFileset((FileSet) obj); | |||
} else if (obj instanceof DirSet) { | |||
path.addDirset((DirSet) obj); | |||
} else if (obj instanceof FileList) { | |||
path.addFilelist((FileList) obj); | |||
} else { | |||
throw new BuildException("'refid' does not refer to a " | |||
+ "path, fileset, dirset, or filelist."); | |||
Object o = refid.getReferencedObject(getProject()); | |||
if (!(o instanceof ResourceCollection)) { | |||
throw new BuildException("refid '" + refid.getRefId() | |||
+ "' does not refer to a resource collection."); | |||
} | |||
getPath().add((ResourceCollection) o); | |||
} | |||
validateSetup(); // validate our setup | |||
@@ -355,9 +367,13 @@ public class PathConvert extends Task { | |||
// unless setonempty == false | |||
if (setonempty || rslt.length() > 0) { | |||
String value = rslt.toString(); | |||
log("Set property " + property + " = " + value, | |||
Project.MSG_VERBOSE); | |||
getProject().setNewProperty(property, value); | |||
if (property == null) { | |||
log(value); | |||
} else { | |||
log("Set property " + property + " = " + value, | |||
Project.MSG_VERBOSE); | |||
getProject().setNewProperty(property, value); | |||
} | |||
} | |||
} finally { | |||
path = savedPath; | |||
@@ -423,7 +439,6 @@ public class PathConvert extends Task { | |||
addMapper(m); | |||
} | |||
/** | |||
* Validate that all our parameters have been properly initialized. | |||
* | |||
@@ -434,9 +449,6 @@ public class PathConvert extends Task { | |||
if (path == null) { | |||
throw new BuildException("You must specify a path to convert"); | |||
} | |||
if (property == null) { | |||
throw new BuildException("You must specify a property"); | |||
} | |||
// Determine the separator strings. The dirsep and pathsep attributes | |||
// override the targetOS settings. | |||
String dsep = File.separator; | |||
@@ -464,7 +476,7 @@ public class PathConvert extends Task { | |||
* @return BuildException. | |||
*/ | |||
private BuildException noChildrenAllowed() { | |||
return new BuildException("You must not specify nested <path> " | |||
return new BuildException("You must not specify nested " | |||
+ "elements when using the refid attribute."); | |||
} | |||
@@ -0,0 +1,124 @@ | |||
/* | |||
* 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.Task; | |||
import org.apache.tools.ant.Project; | |||
import org.apache.tools.ant.BuildException; | |||
import org.apache.tools.ant.taskdefs.condition.Condition; | |||
import org.apache.tools.ant.types.Reference; | |||
import org.apache.tools.ant.types.Comparison; | |||
import org.apache.tools.ant.types.ResourceCollection; | |||
/** | |||
* Count resources from a ResourceCollection, storing to a property or | |||
* writing to the log. Can also be used as a Condition. | |||
* @since Ant 1.7 | |||
*/ | |||
public class ResourceCount extends Task implements Condition { | |||
private static final String ONE_NESTED_MESSAGE | |||
= "ResourceCount can count resources from exactly one nested ResourceCollection."; | |||
private static final String COUNT_REQUIRED | |||
= "Use of the ResourceCount condition requires that the count attribute be set."; | |||
private ResourceCollection rc; | |||
private Comparison when = Comparison.EQUAL; | |||
private Integer count; | |||
private String property; | |||
/** | |||
* Add the ResourceCollection to count. | |||
* @param r the ResourceCollection to count. | |||
* @throws BuildException if already set. | |||
*/ | |||
public void add(ResourceCollection r) { | |||
if (rc != null) { | |||
throw new BuildException(ONE_NESTED_MESSAGE); | |||
} | |||
rc = r; | |||
} | |||
/** | |||
* Set the ResourceCollection reference. | |||
* @param r the Reference. | |||
*/ | |||
public void setRefid(Reference r) { | |||
Object o = r.getReferencedObject(); | |||
if (!(o instanceof ResourceCollection)) { | |||
throw new BuildException(r.getRefId() | |||
+ " doesn\'t denote a ResourceCollection"); | |||
} | |||
add((ResourceCollection) o); | |||
} | |||
/** | |||
* Execute as a Task. | |||
*/ | |||
public void execute() { | |||
if (rc == null) { | |||
throw new BuildException(ONE_NESTED_MESSAGE); | |||
} | |||
if (property == null) { | |||
log("resource count = " + rc.size()); | |||
} else { | |||
getProject().setNewProperty(property, Integer.toString(rc.size())); | |||
} | |||
} | |||
/** | |||
* Fulfill the condition contract. | |||
* @return true if the specified ResourceCollection satisfies the set criteria. | |||
* @throws BuildException if an error occurs. | |||
*/ | |||
public boolean eval() { | |||
if (rc == null) { | |||
throw new BuildException(ONE_NESTED_MESSAGE); | |||
} | |||
if (count == null) { | |||
throw new BuildException(COUNT_REQUIRED); | |||
} | |||
return when.evaluate(new Integer(rc.size()).compareTo(count)); | |||
} | |||
/** | |||
* Set the target count number for use as a Condition. | |||
* @param c number of Resources as int. | |||
*/ | |||
public void setCount(int c) { | |||
count = new Integer(c); | |||
} | |||
/** | |||
* Set the comparison for use as a Condition. | |||
* @param w EnumeratedAttribute When. | |||
* @see org.apache.tools.ant.types.Comparison | |||
*/ | |||
public void setWhen(Comparison c) { | |||
when = c; | |||
} | |||
/** | |||
* Set the name of the property to set in task mode. | |||
* @param p the property name to set. | |||
*/ | |||
public void setProperty(String p) { | |||
property = p; | |||
} | |||
} |
@@ -207,6 +207,7 @@ ildasm=org.apache.tools.ant.taskdefs.optional.dotnet.Ildasm | |||
apt=org.apache.tools.ant.taskdefs.Apt | |||
schemavalidate=org.apache.tools.ant.taskdefs.optional.SchemaValidate | |||
verifyjar=org.apache.tools.ant.taskdefs.VerifyJar | |||
resourcecount=org.apache.tools.ant.taskdefs.ResourceCount | |||
# deprecated ant tasks (kept for back compatibility) | |||
starteam=org.apache.tools.ant.taskdefs.optional.scm.AntStarTeamCheckOut | |||
@@ -0,0 +1,93 @@ | |||
/* | |||
* 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.types; | |||
import java.util.Arrays; | |||
import org.apache.tools.ant.BuildException; | |||
/** | |||
* EnumeratedAttribute for generic comparisons. Accepts values | |||
* "equal", "greater", "less", "ne" (not equal), "ge" (greater or equal), | |||
* "le" (less or equal), "eq" (equal), "gt" (greater), "lt" (less). | |||
* @since Ant 1.7 | |||
*/ | |||
public class Comparison extends EnumeratedAttribute { | |||
private static final String[] VALUES | |||
= new String[] {"equal", "greater", "less", | |||
"ne", "ge", "le", "eq", "gt", "lt"}; | |||
/** Equal Comparison. */ | |||
public static final Comparison EQUAL = new Comparison("equal"); | |||
/** Not-Equal Comparison. */ | |||
public static final Comparison NOT_EQUAL = new Comparison("ne"); | |||
/** Greater Comparison. */ | |||
public static final Comparison GREATER = new Comparison("greater"); | |||
/** Less Comparison. */ | |||
public static final Comparison LESS = new Comparison("less"); | |||
/** Greater-or-Equal Comparison. */ | |||
public static final Comparison GREATER_EQUAL = new Comparison("ge"); | |||
/** Less-or-Equal Comparison. */ | |||
public static final Comparison LESS_EQUAL = new Comparison("le"); | |||
private static final int[] EQUAL_INDEX = {0, 4, 5, 6}; | |||
private static final int[] LESS_INDEX = {2, 3, 5, 8}; | |||
private static final int[] GREATER_INDEX = {1, 3, 4, 7}; | |||
/** | |||
* Default constructor. | |||
*/ | |||
public Comparison() { | |||
} | |||
/** | |||
* Construct a new Comparison with the specified value. | |||
* @param value the EnumeratedAttribute value. | |||
*/ | |||
public Comparison(String value) { | |||
setValue(value); | |||
} | |||
/** | |||
* Return the possible values. | |||
* @return String[] of EnumeratedAttribute values. | |||
*/ | |||
public String[] getValues() { | |||
return VALUES; | |||
} | |||
/** | |||
* Evaluate a comparison result as from Comparator.compare() or Comparable.compareTo(). | |||
* @param comparisonResult the result to evaluate. | |||
* @return true if the comparison result fell within the parameters of this Comparison. | |||
*/ | |||
public boolean evaluate(int comparisonResult) { | |||
if (getIndex() == -1) { | |||
throw new BuildException("Comparison value not set."); | |||
} | |||
int[] i = comparisonResult < 0 ? LESS_INDEX | |||
: comparisonResult > 0 ? GREATER_INDEX : EQUAL_INDEX; | |||
return Arrays.binarySearch(i, getIndex()) >= 0; | |||
} | |||
} | |||
@@ -17,13 +17,17 @@ | |||
package org.apache.tools.ant.types; | |||
import java.util.Iterator; | |||
import org.apache.tools.ant.types.resources.FileResourceIterator; | |||
/** | |||
* Subclass as hint for supporting tasks that the included directories | |||
* instead of files should be used. | |||
* | |||
* @since Ant 1.5 | |||
*/ | |||
public class DirSet extends AbstractFileSet { | |||
public class DirSet extends AbstractFileSet implements ResourceCollection { | |||
/** | |||
* Constructor for DirSet. | |||
@@ -53,4 +57,38 @@ public class DirSet extends AbstractFileSet { | |||
} | |||
} | |||
/** | |||
* Fulfill the ResourceCollection contract. | |||
* @return an Iterator of Resources. | |||
* @since Ant 1.7 | |||
*/ | |||
public Iterator iterator() { | |||
if (isReference()) { | |||
return ((DirSet) getRef(getProject())).iterator(); | |||
} | |||
return new FileResourceIterator(getDir(getProject()), | |||
getDirectoryScanner(getProject()).getIncludedDirectories()); | |||
} | |||
/** | |||
* Fulfill the ResourceCollection contract. | |||
* @return number of elements as int. | |||
* @since Ant 1.7 | |||
*/ | |||
public int size() { | |||
if (isReference()) { | |||
return ((DirSet) getRef(getProject())).size(); | |||
} | |||
return getDirectoryScanner(getProject()).getIncludedDirsCount(); | |||
} | |||
/** | |||
* Always returns true. | |||
* @return true indicating that all elements will be FileResources. | |||
* @since Ant 1.7 | |||
*/ | |||
public boolean isFilesystemOnly() { | |||
return true; | |||
} | |||
} |
@@ -1,5 +1,5 @@ | |||
/* | |||
* Copyright 2001-2002,2004 The Apache Software Foundation | |||
* Copyright 2001-2002,2004-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. | |||
@@ -21,8 +21,11 @@ import java.io.File; | |||
import java.util.Stack; | |||
import java.util.StringTokenizer; | |||
import java.util.Vector; | |||
import org.apache.tools.ant.BuildException; | |||
import java.util.Iterator; | |||
import org.apache.tools.ant.Project; | |||
import org.apache.tools.ant.BuildException; | |||
import org.apache.tools.ant.types.resources.FileResourceIterator; | |||
/** | |||
* FileList represents an explicitly named list of files. FileLists | |||
@@ -31,7 +34,7 @@ import org.apache.tools.ant.Project; | |||
* filter, only returning the name of a matched file if it currently | |||
* exists in the file system. | |||
*/ | |||
public class FileList extends DataType { | |||
public class FileList extends DataType implements ResourceCollection { | |||
private Vector filenames = new Vector(); | |||
private File dir; | |||
@@ -78,9 +81,7 @@ public class FileList extends DataType { | |||
* @exception BuildException if an error occurs | |||
*/ | |||
public void setDir(File dir) throws BuildException { | |||
if (isReference()) { | |||
throw tooManyAttributes(); | |||
} | |||
checkAttributesAllowed(); | |||
this.dir = dir; | |||
} | |||
@@ -102,9 +103,7 @@ public class FileList extends DataType { | |||
* by whitespace. | |||
*/ | |||
public void setFiles(String filenames) { | |||
if (isReference()) { | |||
throw tooManyAttributes(); | |||
} | |||
checkAttributesAllowed(); | |||
if (filenames != null && filenames.length() > 0) { | |||
StringTokenizer tok = new StringTokenizer( | |||
filenames, ", \t\n\r\f", false); | |||
@@ -144,19 +143,7 @@ public class FileList extends DataType { | |||
* @return the FileList represented by a referenced filelist. | |||
*/ | |||
protected FileList getRef(Project p) { | |||
if (!isChecked()) { | |||
Stack stk = new Stack(); | |||
stk.push(this); | |||
dieOnCircularReference(stk, p); | |||
} | |||
Object o = getRefid().getReferencedObject(p); | |||
if (!(o instanceof FileList)) { | |||
String msg = getRefid().getRefId() + " doesn\'t denote a filelist"; | |||
throw new BuildException(msg); | |||
} else { | |||
return (FileList) o; | |||
} | |||
return (FileList) getCheckedRef(p); | |||
} | |||
/** | |||
@@ -194,4 +181,39 @@ public class FileList extends DataType { | |||
} | |||
filenames.addElement(name.getName()); | |||
} | |||
/** | |||
* Fulfill the ResourceCollection contract. | |||
* @return an Iterator of Resources. | |||
* @since Ant 1.7 | |||
*/ | |||
public Iterator iterator() { | |||
if (isReference()) { | |||
return ((FileList) getRef(getProject())).iterator(); | |||
} | |||
return new FileResourceIterator(dir, | |||
(String[]) (filenames.toArray(new String[filenames.size()]))); | |||
} | |||
/** | |||
* Fulfill the ResourceCollection contract. | |||
* @return number of elements as int. | |||
* @since Ant 1.7 | |||
*/ | |||
public int size() { | |||
if (isReference()) { | |||
return ((FileList) getRef(getProject())).size(); | |||
} | |||
return filenames.size(); | |||
} | |||
/** | |||
* Always returns true. | |||
* @return true indicating that all elements will be FileResources. | |||
* @since Ant 1.7 | |||
*/ | |||
public boolean isFilesystemOnly() { | |||
return true; | |||
} | |||
} |
@@ -17,12 +17,16 @@ | |||
package org.apache.tools.ant.types; | |||
import java.util.Iterator; | |||
import org.apache.tools.ant.types.resources.FileResourceIterator; | |||
/** | |||
* Moved out of MatchingTask to make it a standalone object that could | |||
* be referenced (by scripts for example). | |||
* | |||
*/ | |||
public class FileSet extends AbstractFileSet { | |||
public class FileSet extends AbstractFileSet implements ResourceCollection { | |||
/** | |||
* Constructor for FileSet. | |||
@@ -52,4 +56,38 @@ public class FileSet extends AbstractFileSet { | |||
} | |||
} | |||
/** | |||
* Fulfill the ResourceCollection contract. | |||
* @return an Iterator of Resources. | |||
* @since Ant 1.7 | |||
*/ | |||
public Iterator iterator() { | |||
if (isReference()) { | |||
return ((FileSet) getRef(getProject())).iterator(); | |||
} | |||
return new FileResourceIterator(getDir(getProject()), | |||
getDirectoryScanner(getProject()).getIncludedFiles()); | |||
} | |||
/** | |||
* Fulfill the ResourceCollection contract. | |||
* @return number of elements as int. | |||
* @since Ant 1.7 | |||
*/ | |||
public int size() { | |||
if (isReference()) { | |||
return ((FileSet) getRef(getProject())).size(); | |||
} | |||
return getDirectoryScanner(getProject()).getIncludedFilesCount(); | |||
} | |||
/** | |||
* Always returns true. | |||
* @return true indicating that all elements will be FileResources. | |||
* @since Ant 1.7 | |||
*/ | |||
public boolean isFilesystemOnly() { | |||
return true; | |||
} | |||
} |
@@ -18,17 +18,22 @@ | |||
package org.apache.tools.ant.types; | |||
import java.io.File; | |||
import java.util.Enumeration; | |||
import java.util.Locale; | |||
import java.util.Set; | |||
import java.util.Stack; | |||
import java.util.Locale; | |||
import java.util.Vector; | |||
import java.util.HashSet; | |||
import java.util.Iterator; | |||
import java.util.Collection; | |||
import java.util.Enumeration; | |||
import org.apache.tools.ant.BuildException; | |||
import org.apache.tools.ant.PathTokenizer; | |||
import org.apache.tools.ant.Project; | |||
import org.apache.tools.ant.types.resources.Union; | |||
import org.apache.tools.ant.types.resources.FileResourceIterator; | |||
import org.apache.tools.ant.util.FileUtils; | |||
import org.apache.tools.ant.util.JavaEnvUtils; | |||
/** | |||
* This object represents a path as used by CLASSPATH or PATH | |||
* environment variable. | |||
@@ -56,28 +61,25 @@ import org.apache.tools.ant.util.JavaEnvUtils; | |||
* | |||
*/ | |||
public class Path extends DataType implements Cloneable { | |||
private Vector elements; | |||
public class Path extends Union { | |||
/** The system classspath as a Path object */ | |||
/** The system classpath as a Path object */ | |||
public static Path systemClasspath = | |||
new Path(null, System.getProperty("java.class.path")); | |||
/** | |||
* The system bootclassspath as a Path object. | |||
* The system bootclasspath as a Path object. | |||
* | |||
* @since Ant 1.6.2 | |||
*/ | |||
public static Path systemBootClasspath = | |||
new Path(null, System.getProperty("sun.boot.class.path")); | |||
/** | |||
* Helper class, holds the nested <code><pathelement></code> values. | |||
*/ | |||
public class PathElement { | |||
public class PathElement implements ResourceCollection { | |||
private String[] parts; | |||
/** | |||
@@ -106,6 +108,19 @@ public class Path extends DataType implements Cloneable { | |||
public String[] getParts() { | |||
return parts; | |||
} | |||
public Iterator iterator() { | |||
return new FileResourceIterator(null, parts); | |||
} | |||
public boolean isFilesystemOnly() { | |||
return true; | |||
} | |||
public int size() { | |||
return parts == null ? 0 : parts.length; | |||
} | |||
} | |||
/** | |||
@@ -125,7 +140,6 @@ public class Path extends DataType implements Cloneable { | |||
*/ | |||
public Path(Project project) { | |||
setProject(project); | |||
elements = new Vector(); | |||
} | |||
/** | |||
@@ -135,22 +149,17 @@ public class Path extends DataType implements Cloneable { | |||
* @throws BuildException on error | |||
*/ | |||
public void setLocation(File location) throws BuildException { | |||
if (isReference()) { | |||
throw tooManyAttributes(); | |||
} | |||
checkAttributesAllowed(); | |||
createPathElement().setLocation(location); | |||
} | |||
/** | |||
* Parses a path definition and creates single PathElements. | |||
* @param path the <code>String</code> path definition. | |||
* @throws BuildException on error | |||
*/ | |||
public void setPath(String path) throws BuildException { | |||
if (isReference()) { | |||
throw tooManyAttributes(); | |||
} | |||
checkAttributesAllowed(); | |||
createPathElement().setPath(path); | |||
} | |||
@@ -163,10 +172,9 @@ public class Path extends DataType implements Cloneable { | |||
* @throws BuildException on error | |||
*/ | |||
public void setRefid(Reference r) throws BuildException { | |||
if (!elements.isEmpty()) { | |||
if (!getResourceCollections().isEmpty()) { | |||
throw tooManyAttributes(); | |||
} | |||
elements.addElement(r); | |||
super.setRefid(r); | |||
} | |||
@@ -180,7 +188,7 @@ public class Path extends DataType implements Cloneable { | |||
throw noChildrenAllowed(); | |||
} | |||
PathElement pe = new PathElement(); | |||
elements.addElement(pe); | |||
add(pe); | |||
return pe; | |||
} | |||
@@ -190,11 +198,7 @@ public class Path extends DataType implements Cloneable { | |||
* @throws BuildException on error | |||
*/ | |||
public void addFileset(FileSet fs) throws BuildException { | |||
if (isReference()) { | |||
throw noChildrenAllowed(); | |||
} | |||
elements.addElement(fs); | |||
setChecked(false); | |||
add(fs); | |||
} | |||
/** | |||
@@ -203,11 +207,7 @@ public class Path extends DataType implements Cloneable { | |||
* @throws BuildException on error | |||
*/ | |||
public void addFilelist(FileList fl) throws BuildException { | |||
if (isReference()) { | |||
throw noChildrenAllowed(); | |||
} | |||
elements.addElement(fl); | |||
setChecked(false); | |||
add(fl); | |||
} | |||
/** | |||
@@ -216,11 +216,7 @@ public class Path extends DataType implements Cloneable { | |||
* @throws BuildException on error | |||
*/ | |||
public void addDirset(DirSet dset) throws BuildException { | |||
if (isReference()) { | |||
throw noChildrenAllowed(); | |||
} | |||
elements.addElement(dset); | |||
setChecked(false); | |||
add(dset); | |||
} | |||
/** | |||
@@ -230,12 +226,7 @@ public class Path extends DataType implements Cloneable { | |||
* @since Ant 1.6 | |||
*/ | |||
public void add(Path path) throws BuildException { | |||
if (isReference()) { | |||
throw noChildrenAllowed(); | |||
} | |||
elements.addElement(path); | |||
setChecked(false); | |||
add((ResourceCollection) path); | |||
} | |||
/** | |||
@@ -244,12 +235,8 @@ public class Path extends DataType implements Cloneable { | |||
* @throws BuildException on error | |||
*/ | |||
public Path createPath() throws BuildException { | |||
if (isReference()) { | |||
throw noChildrenAllowed(); | |||
} | |||
Path p = new Path(getProject()); | |||
elements.addElement(p); | |||
setChecked(false); | |||
add(p); | |||
return p; | |||
} | |||
@@ -261,17 +248,12 @@ public class Path extends DataType implements Cloneable { | |||
if (other == null) { | |||
return; | |||
} | |||
String[] l = other.list(); | |||
for (int i = 0; i < l.length; i++) { | |||
if (elements.indexOf(l[i]) == -1) { | |||
elements.addElement(l[i]); | |||
} | |||
} | |||
add(other); | |||
} | |||
/** | |||
/** | |||
* Adds the components on the given path which exist to this | |||
* Path. Components that don't exist, aren't added. | |||
* Path. Components that don't exist aren't added. | |||
* | |||
* @param source - source path whose components are examined for existence | |||
*/ | |||
@@ -309,92 +291,29 @@ public class Path extends DataType implements Cloneable { | |||
} | |||
/** | |||
* Returns all path elements defined by this and nested path objects. | |||
* @return list of path elements. | |||
*/ | |||
public String[] list() { | |||
if (!isChecked()) { | |||
// make sure we don't have a circular reference here | |||
Stack stk = new Stack(); | |||
stk.push(this); | |||
dieOnCircularReference(stk, getProject()); | |||
} | |||
Vector result = new Vector(2 * elements.size()); | |||
for (int i = 0; i < elements.size(); i++) { | |||
Object o = elements.elementAt(i); | |||
if (o instanceof Reference) { | |||
Reference r = (Reference) o; | |||
o = r.getReferencedObject(getProject()); | |||
// we only support references to paths right now | |||
if (!(o instanceof Path)) { | |||
String msg = r.getRefId() + " doesn\'t denote a path " + o; | |||
throw new BuildException(msg); | |||
} | |||
* Override <code>Union.getCollection()</code> | |||
* so we can check our children first. | |||
* @return a Collection. | |||
*/ | |||
protected Collection getCollection() { | |||
for (Iterator i = getResourceCollections().iterator(); i.hasNext();) { | |||
ResourceCollection rc = (ResourceCollection) i.next(); | |||
if (!(rc.isFilesystemOnly())) { | |||
throw new BuildException(getDataTypeName() | |||
+ " allows only filesystem resources."); | |||
} | |||
if (o instanceof String) { | |||
// obtained via append | |||
addUnlessPresent(result, (String) o); | |||
} else if (o instanceof PathElement) { | |||
String[] parts = ((PathElement) o).getParts(); | |||
if (parts == null) { | |||
throw new BuildException("You must either set location or" | |||
+ " path on <pathelement>"); | |||
} | |||
for (int j = 0; j < parts.length; j++) { | |||
addUnlessPresent(result, parts[j]); | |||
} | |||
} else if (o instanceof Path) { | |||
Path p = (Path) o; | |||
if (rc instanceof PathElement | |||
&& ((PathElement) rc).getParts() == null) { | |||
throw new BuildException( | |||
"Either location or path must be set on a pathelement."); | |||
} else if (rc instanceof Path) { | |||
Path p = (Path) rc; | |||
if (p.getProject() == null) { | |||
p.setProject(getProject()); | |||
} | |||
String[] parts = p.list(); | |||
for (int j = 0; j < parts.length; j++) { | |||
addUnlessPresent(result, parts[j]); | |||
} | |||
} else if (o instanceof DirSet) { | |||
DirSet dset = (DirSet) o; | |||
addUnlessPresent(result, dset.getDir(getProject()), | |||
dset.getDirectoryScanner(getProject()).getIncludedDirectories()); | |||
} else if (o instanceof FileSet) { | |||
FileSet fs = (FileSet) o; | |||
addUnlessPresent(result, fs.getDir(getProject()), | |||
fs.getDirectoryScanner(getProject()).getIncludedFiles()); | |||
} else if (o instanceof FileList) { | |||
FileList fl = (FileList) o; | |||
addUnlessPresent(result, | |||
fl.getDir(getProject()), fl.getFiles(getProject())); | |||
} | |||
} | |||
String[] res = new String[result.size()]; | |||
result.copyInto(res); | |||
return res; | |||
} | |||
/** | |||
* Returns a textual representation of the path, which can be used as | |||
* CLASSPATH or PATH environment variable definition. | |||
* @return a textual representation of the path. | |||
*/ | |||
public String toString() { | |||
final String[] list = list(); | |||
// empty path return empty string | |||
if (list.length == 0) { | |||
return ""; | |||
} | |||
// path containing one or more elements | |||
final StringBuffer result = new StringBuffer(list[0].toString()); | |||
for (int i = 1; i < list.length; i++) { | |||
result.append(File.pathSeparatorChar); | |||
result.append(list[i]); | |||
} | |||
return result.toString(); | |||
return super.getCollection(); | |||
} | |||
/** | |||
@@ -466,62 +385,6 @@ public class Path extends DataType implements Cloneable { | |||
return false; | |||
} | |||
/** | |||
* How many parts does this Path instance consist of. | |||
* @return the number of parts | |||
*/ | |||
public int size() { | |||
return list().length; | |||
} | |||
/** | |||
* Return a Path that holds the same elements as this instance. | |||
* @return a copy of the path | |||
*/ | |||
public Object clone() { | |||
try { | |||
Path p = (Path) super.clone(); | |||
p.elements = (Vector) elements.clone(); | |||
return p; | |||
} catch (CloneNotSupportedException e) { | |||
throw new BuildException(e); | |||
} | |||
} | |||
/** | |||
* Overrides the version of DataType to recurse on all DataType | |||
* child elements that may have been added. | |||
* @param stk the stack of data types to use (recursively) | |||
* @param p the project to use to dereference the references | |||
* @throws BuildException on error | |||
*/ | |||
protected void dieOnCircularReference(Stack stk, Project p) | |||
throws BuildException { | |||
if (isChecked()) { | |||
return; | |||
} | |||
Enumeration e = elements.elements(); | |||
while (e.hasMoreElements()) { | |||
Object o = e.nextElement(); | |||
if (o instanceof Reference) { | |||
o = ((Reference) o).getReferencedObject(p); | |||
} | |||
if (o instanceof DataType) { | |||
if (stk.contains(o)) { | |||
throw circularReference(); | |||
} else { | |||
stk.push(o); | |||
((DataType) o).dieOnCircularReference(stk, p); | |||
stk.pop(); | |||
} | |||
} | |||
} | |||
setChecked(true); | |||
} | |||
/** | |||
* Resolve a filename with Project's help - if we know one that is. | |||
*/ | |||
@@ -530,27 +393,6 @@ public class Path extends DataType implements Cloneable { | |||
(project == null) ? null : project.getBaseDir(), relativeName); | |||
} | |||
/** | |||
* Adds a String to the Vector if it isn't already included. | |||
*/ | |||
private static void addUnlessPresent(Vector v, String s) { | |||
if (v.indexOf(s) == -1) { | |||
v.addElement(s); | |||
} | |||
} | |||
/** | |||
* Adds absolute path names of listed files in the given directory | |||
* to the Vector if they are not already included. | |||
*/ | |||
private static void addUnlessPresent(Vector v, File dir, String[] s) { | |||
for (int j = 0; j < s.length; j++) { | |||
File d = new File(dir, s[j]); | |||
String absolutePath = d.getAbsolutePath(); | |||
addUnlessPresent(v, translateFile(absolutePath)); | |||
} | |||
} | |||
/** | |||
* Concatenates the system class path in the order specified by | |||
* the ${build.sysclasspath} property - using "last" as | |||
@@ -737,4 +579,5 @@ public class Path extends DataType implements Cloneable { | |||
} | |||
} | |||
} | |||
} |
@@ -30,6 +30,8 @@ import java.util.Vector; | |||
import org.apache.tools.ant.BuildException; | |||
import org.apache.tools.ant.Project; | |||
import org.apache.tools.ant.types.ResourceCollection; | |||
import org.apache.tools.ant.types.resources.PropertyResource; | |||
import org.apache.tools.ant.util.FileNameMapper; | |||
import org.apache.tools.ant.util.regexp.RegexpMatcher; | |||
import org.apache.tools.ant.util.regexp.RegexpMatcherFactory; | |||
@@ -39,7 +41,7 @@ import org.apache.tools.ant.util.regexp.RegexpMatcherFactory; | |||
* | |||
* @since Ant 1.6 | |||
*/ | |||
public class PropertySet extends DataType { | |||
public class PropertySet extends DataType implements ResourceCollection { | |||
private boolean dynamic = true; | |||
private boolean negate = false; | |||
@@ -463,4 +465,40 @@ public class PropertySet extends DataType { | |||
return b.toString(); | |||
} | |||
/** | |||
* Fulfill the ResourceCollection interface. | |||
* @return an Iterator of Resources. | |||
* @since Ant 1.7 | |||
*/ | |||
public Iterator iterator() { | |||
final Enumeration e = getProperties().propertyNames(); | |||
return new Iterator() { | |||
public boolean hasNext() { | |||
return e.hasMoreElements(); | |||
} | |||
public Object next() { | |||
return new PropertyResource(getProject(), (String) e.nextElement()); | |||
} | |||
public void remove() { | |||
throw new UnsupportedOperationException(); | |||
} | |||
}; | |||
} | |||
/** | |||
* Fulfill the ResourceCollection contract. | |||
* @return the size of this ResourceCollection. | |||
*/ | |||
public int size() { | |||
return isReference() ? getRef().size() : getProperties().size(); | |||
} | |||
/** | |||
* Fulfill the ResourceCollection contract. | |||
* @return whether this is a filesystem-only resource collection. | |||
*/ | |||
public boolean isFilesystemOnly() { | |||
return isReference() && getRef().isFilesystemOnly(); | |||
} | |||
} |
@@ -16,24 +16,51 @@ | |||
*/ | |||
package org.apache.tools.ant.types; | |||
import java.io.InputStream; | |||
import java.io.IOException; | |||
import java.io.OutputStream; | |||
import java.math.BigInteger; | |||
import java.util.Stack; | |||
import java.util.Iterator; | |||
import java.util.NoSuchElementException; | |||
import org.apache.tools.ant.BuildException; | |||
/** | |||
* Describes a File or a ZipEntry. | |||
* Describes a "File-like" resource (File, ZipEntry, etc.). | |||
* | |||
* This class is meant to be used by classes needing to record path | |||
* and date/time information about a file, a zip entry or some similar | |||
* resource (URL, archive in a version control repository, ...). | |||
* | |||
* @since Ant 1.5.2 | |||
* @see org.apache.tools.ant.types.resources.Touchable | |||
*/ | |||
public class Resource implements Cloneable, Comparable { | |||
public class Resource extends DataType | |||
implements Cloneable, Comparable, ResourceCollection { | |||
/** Constant unknown size */ | |||
public static final long UNKNOWN_SIZE = -1; | |||
/** Magic number */ | |||
protected static final int MAGIC = getMagicNumber("Resource".getBytes()); | |||
private static final int NULL_NAME = getMagicNumber("null name".getBytes()); | |||
/** | |||
* Create a "magic number" for use in hashCode calculations. | |||
* @param seed byte[] to seed with. | |||
* @return a magic number as int. | |||
*/ | |||
protected static int getMagicNumber(byte[] seed) { | |||
return new BigInteger(seed).intValue(); | |||
} | |||
private String name = null; | |||
private boolean exists = true; | |||
private long lastmodified = 0; | |||
private boolean directory = false; | |||
private long size = UNKNOWN_SIZE; | |||
private Boolean exists = null; | |||
private Long lastmodified = null; | |||
private Boolean directory = null; | |||
private Long size = null; | |||
/** | |||
* Default constructor. | |||
@@ -112,7 +139,7 @@ public class Resource implements Cloneable, Comparable { | |||
* @return the name of this resource. | |||
*/ | |||
public String getName() { | |||
return name; | |||
return isReference() ? ((Resource) getCheckedRef()).getName() : name; | |||
} | |||
/** | |||
@@ -121,6 +148,7 @@ public class Resource implements Cloneable, Comparable { | |||
* "/" to be used as the directory separator. | |||
*/ | |||
public void setName(String name) { | |||
checkAttributesAllowed(); | |||
this.name = name; | |||
} | |||
@@ -129,7 +157,11 @@ public class Resource implements Cloneable, Comparable { | |||
* @return true if this resource exists. | |||
*/ | |||
public boolean isExists() { | |||
return exists; | |||
if (isReference()) { | |||
return ((Resource) getCheckedRef()).isExists(); | |||
} | |||
//default true: | |||
return exists == null || exists.booleanValue(); | |||
} | |||
/** | |||
@@ -137,7 +169,8 @@ public class Resource implements Cloneable, Comparable { | |||
* @param exists if true, this resource exists. | |||
*/ | |||
public void setExists(boolean exists) { | |||
this.exists = exists; | |||
checkAttributesAllowed(); | |||
this.exists = exists ? Boolean.TRUE : Boolean.FALSE; | |||
} | |||
/** | |||
@@ -147,7 +180,14 @@ public class Resource implements Cloneable, Comparable { | |||
* of {@link java.io.File File}. | |||
*/ | |||
public long getLastModified() { | |||
return !exists || lastmodified < 0 ? 0L : lastmodified; | |||
if (isReference()) { | |||
return ((Resource) getCheckedRef()).getLastModified(); | |||
} | |||
if (!isExists() || lastmodified == null) { | |||
return 0L; | |||
} | |||
long result = lastmodified.longValue(); | |||
return result < 0L ? 0L : result; | |||
} | |||
/** | |||
@@ -155,7 +195,8 @@ public class Resource implements Cloneable, Comparable { | |||
* @param lastmodified the modification time in milliseconds since 01.01.1970. | |||
*/ | |||
public void setLastModified(long lastmodified) { | |||
this.lastmodified = lastmodified; | |||
checkAttributesAllowed(); | |||
this.lastmodified = new Long(lastmodified); | |||
} | |||
/** | |||
@@ -163,7 +204,11 @@ public class Resource implements Cloneable, Comparable { | |||
* @return boolean flag indicating if the resource is a directory. | |||
*/ | |||
public boolean isDirectory() { | |||
return directory; | |||
if (isReference()) { | |||
return ((Resource) getCheckedRef()).isDirectory(); | |||
} | |||
//default false: | |||
return directory != null && directory.booleanValue(); | |||
} | |||
/** | |||
@@ -171,26 +216,31 @@ public class Resource implements Cloneable, Comparable { | |||
* @param directory if true, this resource is a directory. | |||
*/ | |||
public void setDirectory(boolean directory) { | |||
this.directory = directory; | |||
checkAttributesAllowed(); | |||
this.directory = directory ? Boolean.TRUE : Boolean.FALSE; | |||
} | |||
/** | |||
* Set the size of this Resource. | |||
* @param size the size, as a long. | |||
* @since Ant 1.7 | |||
* @since Ant 1.6.3 | |||
*/ | |||
public void setSize(long size) { | |||
this.size = (size > UNKNOWN_SIZE) ? size : UNKNOWN_SIZE; | |||
checkAttributesAllowed(); | |||
this.size = new Long(size > UNKNOWN_SIZE ? size : UNKNOWN_SIZE); | |||
} | |||
/** | |||
* Get the size of this Resource. | |||
* @return the size, as a long, 0 if the Resource does not exist (for | |||
* compatibility with java.io.File), or UNKNOWN_SIZE if not known. | |||
* @since Ant 1.7 | |||
* @since Ant 1.6.3 | |||
*/ | |||
public long getSize() { | |||
return (exists) ? size : 0L; | |||
if (isReference()) { | |||
return ((Resource) getCheckedRef()).getSize(); | |||
} | |||
return isExists() && size != null ? size.longValue() : 0L; | |||
} | |||
/** | |||
@@ -215,12 +265,168 @@ public class Resource implements Cloneable, Comparable { | |||
* @since Ant 1.6 | |||
*/ | |||
public int compareTo(Object other) { | |||
if (isReference()) { | |||
return ((Comparable) getCheckedRef()).compareTo(other); | |||
} | |||
if (!(other instanceof Resource)) { | |||
throw new IllegalArgumentException("Can only be compared with " | |||
+ "Resources"); | |||
throw new IllegalArgumentException( | |||
"Can only be compared with Resources"); | |||
} | |||
Resource r = (Resource) other; | |||
return getName().compareTo(r.getName()); | |||
String name = getName(); | |||
String oname = r.getName(); | |||
if (name == null && oname == null) { | |||
return 0; | |||
} | |||
if (name == null) { | |||
return -1; | |||
} | |||
return oname == null ? 1 : name.compareTo(oname); | |||
} | |||
/** | |||
* Implement basic Resource equality. | |||
* @return true if the specified Object is equal to this Resource. | |||
* @since Ant 1.7 | |||
*/ | |||
public boolean equals(Object other) { | |||
if (isReference()) { | |||
return getCheckedRef().equals(other); | |||
} | |||
return other.getClass().equals(getClass()) && compareTo(other) == 0; | |||
} | |||
/** | |||
* Get the hash code for this Resource. | |||
* @return hash code as int. | |||
* @since Ant 1.7 | |||
*/ | |||
public int hashCode() { | |||
if (isReference()) { | |||
return getCheckedRef().hashCode(); | |||
} | |||
String name = getName(); | |||
return MAGIC * (name == null ? name.hashCode() : NULL_NAME); | |||
} | |||
/** | |||
* Get an InputStream for the Resource. | |||
* @return an InputStream containing this Resource's content. | |||
* @throws IOException if unable to provide the content of this | |||
* Resource as a stream. | |||
* @throws UnsupportedOperationException if InputStreams are not | |||
* supported for this Resource type. | |||
* @since Ant 1.7 | |||
*/ | |||
public InputStream getInputStream() throws IOException { | |||
if (isReference()) { | |||
return ((Resource) getCheckedRef()).getInputStream(); | |||
} | |||
throw new UnsupportedOperationException(); | |||
} | |||
/** | |||
* Get an OutputStream for the Resource. | |||
* @return an OutputStream to which content can be written. | |||
* @throws IOException if unable to provide the content of this | |||
* Resource as a stream. | |||
* @throws UnsupportedOperationException if OutputStreams are not | |||
* supported for this Resource type. | |||
* @since Ant 1.7 | |||
*/ | |||
public OutputStream getOutputStream() throws IOException { | |||
if (isReference()) { | |||
return ((Resource) getCheckedRef()).getOutputStream(); | |||
} | |||
throw new UnsupportedOperationException(); | |||
} | |||
/** | |||
* Fulfill the ResourceCollection contract. | |||
* @return an Iterator of Resources. | |||
* @since Ant 1.7 | |||
*/ | |||
public Iterator iterator() { | |||
return isReference() ? ((Resource) getCheckedRef()).iterator() | |||
: new Iterator() { | |||
boolean done = false; | |||
public boolean hasNext() { | |||
return !done; | |||
} | |||
public Object next() { | |||
if (done) { | |||
throw new NoSuchElementException(); | |||
} | |||
done = true; | |||
return Resource.this; | |||
} | |||
public void remove() { | |||
throw new UnsupportedOperationException(); | |||
} | |||
}; | |||
} | |||
/** | |||
* Fulfill the ResourceCollection contract. | |||
* @return the size of this ResourceCollection. | |||
* @since Ant 1.7 | |||
*/ | |||
public int size() { | |||
return isReference() ? ((Resource) getCheckedRef()).size() : 1; | |||
} | |||
/** | |||
* Fulfill the ResourceCollection contract. | |||
* @return whether this Resource is a FileResource. | |||
* @since Ant 1.7 | |||
*/ | |||
public boolean isFilesystemOnly() { | |||
//default false: | |||
return isReference() && ((Resource) getCheckedRef()).isFilesystemOnly(); | |||
} | |||
/** | |||
* Get the string representation of this Resource. | |||
* @return this Resource formatted as a String. | |||
* @since Ant 1.7 | |||
*/ | |||
public String toString() { | |||
if (isReference()) { | |||
return getCheckedRef().toString(); | |||
} | |||
String n = getName(); | |||
if (n != null) { | |||
return n; | |||
} | |||
String classname = getClass().getName(); | |||
return "anonymous " + classname.substring(classname.lastIndexOf('.') + 1); | |||
} | |||
/** | |||
* Get a long String representation of this Resource. | |||
* This typically should be the value of <code>toString()</code> | |||
* prefixed by a type description. | |||
* @return this Resource formatted as a long String. | |||
* @since Ant 1.7 | |||
*/ | |||
public final String toLongString() { | |||
return isReference() ? ((Resource) getCheckedRef()).toLongString() | |||
: getDataTypeName() + " \"" + toString() + '"'; | |||
} | |||
/** | |||
* Overrides the base version. | |||
* @param r the Reference to set. | |||
*/ | |||
public void setRefid(Reference r) { | |||
if (name != null | |||
|| exists != null | |||
|| lastmodified != null | |||
|| directory != null | |||
|| size != null) { | |||
throw tooManyAttributes(); | |||
} | |||
super.setRefid(r); | |||
} | |||
} |
@@ -0,0 +1,49 @@ | |||
/* | |||
* 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.types; | |||
import java.util.Iterator; | |||
/** | |||
* Interface describing a collection of Resources. | |||
* @since Ant 1.7 | |||
*/ | |||
public interface ResourceCollection { | |||
/** | |||
* Get an Iterator over the contents of this ResourceCollection, whose elements | |||
* are <code>org.apache.tools.ant.types.Resource</code> instances. | |||
* @return an Iterator of Resources. | |||
*/ | |||
public Iterator iterator(); | |||
/** | |||
* Learn the number of contained Resources. | |||
* @return number of elements as int. | |||
*/ | |||
public int size(); | |||
/** | |||
* Indicate whether this ResourceCollection is composed entirely of | |||
* Resources accessible via local filesystem conventions. If true, | |||
* all Resources returned from this ResourceCollection should be | |||
* instances of FileResource. | |||
* @return whether this is a filesystem-only resource collection. | |||
*/ | |||
public boolean isFilesystemOnly(); | |||
} |
@@ -18,6 +18,7 @@ package org.apache.tools.ant.types; | |||
import java.io.File; | |||
import java.util.Stack; | |||
import java.util.Iterator; | |||
import org.apache.tools.ant.BuildException; | |||
import org.apache.tools.ant.DirectoryScanner; | |||
import org.apache.tools.ant.Project; | |||
@@ -62,6 +63,8 @@ public class ZipFileSet extends FileSet { | |||
private boolean fileModeHasBeenSet = false; | |||
private boolean dirModeHasBeenSet = false; | |||
private String encoding = null; | |||
/** Constructor for ZipFileSet */ | |||
public ZipFileSet() { | |||
super(); | |||
@@ -89,6 +92,7 @@ public class ZipFileSet extends FileSet { | |||
dirMode = fileset.dirMode; | |||
fileModeHasBeenSet = fileset.fileModeHasBeenSet; | |||
dirModeHasBeenSet = fileset.dirModeHasBeenSet; | |||
encoding = fileset.encoding; | |||
} | |||
/** | |||
@@ -98,9 +102,7 @@ public class ZipFileSet extends FileSet { | |||
* @throws BuildException on error | |||
*/ | |||
public void setDir(File dir) throws BuildException { | |||
if (isReference()) { | |||
throw tooManyAttributes(); | |||
} | |||
checkAttributesAllowed(); | |||
if (srcFile != null) { | |||
throw new BuildException("Cannot set both dir and src attributes"); | |||
} else { | |||
@@ -116,9 +118,7 @@ public class ZipFileSet extends FileSet { | |||
* @param srcFile The zip file from which to extract entries. | |||
*/ | |||
public void setSrc(File srcFile) { | |||
if (isReference()) { | |||
throw tooManyAttributes(); | |||
} | |||
checkAttributesAllowed(); | |||
if (hasDir) { | |||
throw new BuildException("Cannot set both dir and src attributes"); | |||
} | |||
@@ -189,6 +189,24 @@ public class ZipFileSet extends FileSet { | |||
return fullpath; | |||
} | |||
/** | |||
* Set the encoding used for this ZipFileSet. | |||
* @param enc encoding as String. | |||
* @since Ant 1.7 | |||
*/ | |||
public void setEncoding(String enc) { | |||
this.encoding = enc; | |||
} | |||
/** | |||
* Get the encoding used for this ZipFileSet. | |||
* @return String encoding. | |||
* @since Ant 1.7 | |||
*/ | |||
public String getEncoding() { | |||
return encoding; | |||
} | |||
/** | |||
* Return the DirectoryScanner associated with this FileSet. | |||
* If the ZipFileSet defines a source Zip file, then a ZipScanner | |||
@@ -200,16 +218,60 @@ public class ZipFileSet extends FileSet { | |||
if (isReference()) { | |||
return getRef(p).getDirectoryScanner(p); | |||
} | |||
if (srcFile != null) { | |||
ZipScanner zs = new ZipScanner(); | |||
zs.setSrc(srcFile); | |||
super.setDir(p.getBaseDir()); | |||
setupDirectoryScanner(zs, p); | |||
zs.init(); | |||
return zs; | |||
} else { | |||
if (srcFile == null) { | |||
return super.getDirectoryScanner(p); | |||
} | |||
ZipScanner zs = new ZipScanner(); | |||
zs.setSrc(srcFile); | |||
super.setDir(p.getBaseDir()); | |||
setupDirectoryScanner(zs, p); | |||
zs.init(); | |||
zs.setEncoding(encoding); | |||
return zs; | |||
} | |||
/** | |||
* Fulfill the ResourceCollection contract. | |||
* @return Iterator of Resources. | |||
* @since Ant 1.7 | |||
*/ | |||
public Iterator iterator() { | |||
if (isReference()) { | |||
return ((ResourceCollection) (getRef(getProject()))).iterator(); | |||
} | |||
if (srcFile == null) { | |||
return super.iterator(); | |||
} | |||
ZipScanner zs = (ZipScanner) getDirectoryScanner(getProject()); | |||
return zs.getResourceFiles(); | |||
} | |||
/** | |||
* Fulfill the ResourceCollection contract. | |||
* @return size of the collection as int. | |||
* @since Ant 1.7 | |||
*/ | |||
public int size() { | |||
if (isReference()) { | |||
return ((ResourceCollection) (getRef(getProject()))).size(); | |||
} | |||
if (srcFile == null) { | |||
return super.size(); | |||
} | |||
ZipScanner zs = (ZipScanner) getDirectoryScanner(getProject()); | |||
return zs.getIncludedFilesCount(); | |||
} | |||
/** | |||
* Indicate whether this ResourceCollection is composed entirely of | |||
* Resources accessible via local filesystem conventions. If true, | |||
* all Resources returned from this ResourceCollection should be | |||
* instances of FileResource. | |||
* @return whether this is a filesystem-only resource collection. | |||
* @since Ant 1.7 | |||
*/ | |||
public boolean isFilesystemOnly() { | |||
return srcFile == null; | |||
} | |||
/** | |||
@@ -297,11 +359,7 @@ public class ZipFileSet extends FileSet { | |||
* @return the abstract fileset instance | |||
*/ | |||
protected AbstractFileSet getRef(Project p) { | |||
if (!isChecked()) { | |||
Stack stk = new Stack(); | |||
stk.push(this); | |||
dieOnCircularReference(stk, p); | |||
} | |||
dieOnCircularReference(p); | |||
Object o = getRefid().getReferencedObject(p); | |||
if (o instanceof ZipFileSet) { | |||
return (AbstractFileSet) o; | |||
@@ -319,6 +377,7 @@ public class ZipFileSet extends FileSet { | |||
throw new BuildException(msg); | |||
} | |||
} | |||
/** | |||
* Return a ZipFileSet that has the same properties | |||
* as this one. | |||
@@ -19,14 +19,20 @@ package org.apache.tools.ant.types; | |||
import java.io.File; | |||
import java.io.IOException; | |||
import java.util.Arrays; | |||
import java.util.Vector; | |||
import java.util.Set; | |||
import java.util.TreeMap; | |||
import java.util.Iterator; | |||
import java.util.ArrayList; | |||
import java.util.Hashtable; | |||
import java.util.Comparator; | |||
import java.util.Collections; | |||
import java.util.Enumeration; | |||
import java.util.zip.ZipException; | |||
import org.apache.tools.ant.BuildException; | |||
import org.apache.tools.ant.DirectoryScanner; | |||
import org.apache.tools.ant.types.resources.ZipResource; | |||
import org.apache.tools.ant.types.resources.FileResourceIterator; | |||
import org.apache.tools.zip.ZipEntry; | |||
import org.apache.tools.zip.ZipFile; | |||
@@ -44,14 +50,31 @@ public class ZipScanner extends DirectoryScanner { | |||
* The zip file which should be scanned. | |||
*/ | |||
protected File srcFile; | |||
/** | |||
* to record the last scanned zip file with its modification date | |||
*/ | |||
private Resource lastScannedResource; | |||
/** | |||
* record list of all file zip entries | |||
*/ | |||
private TreeMap fileEntries = new TreeMap(); | |||
/** | |||
* record list of all zip entries | |||
* record list of all directory zip entries | |||
*/ | |||
private Hashtable myentries; | |||
private TreeMap dirEntries = new TreeMap(); | |||
/** | |||
* record list of matching file zip entries | |||
*/ | |||
private TreeMap matchFileEntries = new TreeMap(); | |||
/** | |||
* record list of matching directory zip entries | |||
*/ | |||
private TreeMap matchDirEntries = new TreeMap(); | |||
/** | |||
* encoding of file names. | |||
@@ -60,6 +83,17 @@ public class ZipScanner extends DirectoryScanner { | |||
*/ | |||
private String encoding; | |||
/** | |||
* Don't scan when we have no zipfile. | |||
* @since Ant 1.7 | |||
*/ | |||
public void scan() { | |||
if (srcFile == null) { | |||
return; | |||
} | |||
super.scan(); | |||
} | |||
/** | |||
* Sets the srcFile for scanning. This is the jar or zip file that | |||
* is scanned for matching entries. | |||
@@ -88,23 +122,25 @@ public class ZipScanner extends DirectoryScanner { | |||
* include patterns and none of the exclude patterns. | |||
*/ | |||
public String[] getIncludedFiles() { | |||
if (srcFile != null) { | |||
Vector myvector = new Vector(); | |||
// first check if the archive needs to be scanned again | |||
scanme(); | |||
for (Enumeration e = myentries.elements(); e.hasMoreElements();) { | |||
Resource myresource = (Resource) e.nextElement(); | |||
if (!myresource.isDirectory() && match(myresource.getName())) { | |||
myvector.addElement(myresource.getName()); | |||
} | |||
} | |||
String[] files = new String[myvector.size()]; | |||
myvector.copyInto(files); | |||
Arrays.sort(files); | |||
return files; | |||
} else { | |||
if (srcFile == null) { | |||
return super.getIncludedFiles(); | |||
} | |||
scanme(); | |||
Set s = matchFileEntries.keySet(); | |||
return (String[]) (s.toArray(new String[s.size()])); | |||
} | |||
/** | |||
* Override parent implementation. | |||
* @return count of included files. | |||
* @since Ant 1.7 | |||
*/ | |||
public int getIncludedFilesCount() { | |||
if (srcFile == null) { | |||
return super.getIncludedFilesCount(); | |||
} | |||
scanme(); | |||
return matchFileEntries.size(); | |||
} | |||
/** | |||
@@ -116,23 +152,51 @@ public class ZipScanner extends DirectoryScanner { | |||
* include patterns and none of the exclude patterns. | |||
*/ | |||
public String[] getIncludedDirectories() { | |||
if (srcFile != null) { | |||
Vector myvector = new Vector(); | |||
// first check if the archive needs to be scanned again | |||
scanme(); | |||
for (Enumeration e = myentries.elements(); e.hasMoreElements();) { | |||
Resource myresource = (Resource) e.nextElement(); | |||
if (myresource.isDirectory() && match(myresource.getName())) { | |||
myvector.addElement(myresource.getName()); | |||
} | |||
} | |||
String[] files = new String[myvector.size()]; | |||
myvector.copyInto(files); | |||
Arrays.sort(files); | |||
return files; | |||
} else { | |||
if (srcFile == null) { | |||
return super.getIncludedDirectories(); | |||
} | |||
scanme(); | |||
Set s = matchDirEntries.keySet(); | |||
return (String[]) (s.toArray(new String[s.size()])); | |||
} | |||
/** | |||
* Override parent implementation. | |||
* @return count of included directories. | |||
* @since Ant 1.7 | |||
*/ | |||
public int getIncludedDirsCount() { | |||
if (srcFile == null) { | |||
return super.getIncludedDirsCount(); | |||
} | |||
scanme(); | |||
return matchDirEntries.size(); | |||
} | |||
/** | |||
* Get the set of Resources that represent files. | |||
* @return an Iterator of Resources. | |||
* @since Ant 1.7 | |||
*/ | |||
/* package-private for now */ Iterator getResourceFiles() { | |||
if (srcFile == null) { | |||
return new FileResourceIterator(getBasedir(), getIncludedFiles()); | |||
} | |||
scanme(); | |||
return matchFileEntries.values().iterator(); | |||
} | |||
/** | |||
* Get the set of Resources that represent directories. | |||
* @return an Iterator of Resources. | |||
* @since Ant 1.7 | |||
*/ | |||
/* package-private for now */ Iterator getResourceDirectories() { | |||
if (srcFile == null) { | |||
return new FileResourceIterator(getBasedir(), getIncludedDirectories()); | |||
} | |||
scanme(); | |||
return matchDirEntries.values().iterator(); | |||
} | |||
/** | |||
@@ -165,6 +229,7 @@ public class ZipScanner extends DirectoryScanner { | |||
} | |||
/** | |||
* Get the named Resource. | |||
* @param name path name of the file sought in the archive | |||
* @return the resource | |||
* @since Ant 1.5.2 | |||
@@ -172,34 +237,35 @@ public class ZipScanner extends DirectoryScanner { | |||
public Resource getResource(String name) { | |||
if (srcFile == null) { | |||
return super.getResource(name); | |||
} else if (name.equals("")) { | |||
} | |||
if (name.equals("")) { | |||
// special case in ZIPs, we do not want this thing included | |||
return new Resource("", true, Long.MAX_VALUE, true); | |||
} | |||
// first check if the archive needs to be scanned again | |||
scanme(); | |||
if (myentries.containsKey(name)) { | |||
return (Resource) myentries.get(name); | |||
} else if (myentries.containsKey(name + "/")) { | |||
return (Resource) myentries.get(name + "/"); | |||
} else { | |||
return new Resource(name); | |||
if (fileEntries.containsKey(name)) { | |||
return (Resource) fileEntries.get(name); | |||
} | |||
name = trimSeparator(name); | |||
if (dirEntries.containsKey(name)) { | |||
return (Resource) dirEntries.get(name); | |||
} | |||
return new Resource(name); | |||
} | |||
/** | |||
* if the datetime of the archive did not change since | |||
* lastScannedResource was initialized returns immediately else if | |||
* the archive has not been scanned yet, then all the zip entries | |||
* are put into the vector myentries as a vector of the resource | |||
* type | |||
* are put into the appropriate tables. | |||
*/ | |||
private void scanme() { | |||
//do not use a FileResource b/c it pulls File info from the filesystem: | |||
Resource thisresource = new Resource(srcFile.getAbsolutePath(), | |||
srcFile.exists(), | |||
srcFile.lastModified()); | |||
// spare scanning again and again | |||
if (lastScannedResource != null | |||
&& lastScannedResource.getName().equals(thisresource.getName()) | |||
@@ -207,10 +273,15 @@ public class ZipScanner extends DirectoryScanner { | |||
== thisresource.getLastModified()) { | |||
return; | |||
} | |||
init(); | |||
ZipEntry entry = null; | |||
ZipFile zf = null; | |||
myentries = new Hashtable(); | |||
fileEntries.clear(); | |||
dirEntries.clear(); | |||
matchFileEntries.clear(); | |||
matchDirEntries.clear(); | |||
try { | |||
try { | |||
zf = new ZipFile(srcFile, encoding); | |||
@@ -219,15 +290,23 @@ public class ZipScanner extends DirectoryScanner { | |||
} catch (IOException ex) { | |||
throw new BuildException("problem opening " + srcFile, ex); | |||
} | |||
Enumeration e = zf.getEntries(); | |||
while (e.hasMoreElements()) { | |||
entry = (ZipEntry) e.nextElement(); | |||
myentries.put(new String(entry.getName()), | |||
new Resource(entry.getName(), true, | |||
entry.getTime(), | |||
entry.isDirectory(), | |||
entry.getSize())); | |||
Resource r = new ZipResource(srcFile, encoding, entry); | |||
String name = entry.getName(); | |||
if (entry.isDirectory()) { | |||
name = trimSeparator(name); | |||
dirEntries.put(name, r); | |||
if (match(name)) { | |||
matchDirEntries.put(name, r); | |||
} | |||
} else { | |||
fileEntries.put(name, r); | |||
if (match(name)) { | |||
matchFileEntries.put(name, r); | |||
} | |||
} | |||
} | |||
} finally { | |||
if (zf != null) { | |||
@@ -241,4 +320,9 @@ public class ZipScanner extends DirectoryScanner { | |||
// record data about the last scanned resource | |||
lastScannedResource = thisresource; | |||
} | |||
private static String trimSeparator(String s) { | |||
return s.endsWith("/") ? s.substring(0, s.length() - 1) : s; | |||
} | |||
} |
@@ -1,8 +1,4 @@ | |||
classfileset=org.apache.tools.ant.types.optional.depend.ClassfileSet | |||
description=org.apache.tools.ant.types.Description | |||
dirset=org.apache.tools.ant.types.DirSet | |||
filelist=org.apache.tools.ant.types.FileList | |||
fileset=org.apache.tools.ant.types.FileSet | |||
filterchain=org.apache.tools.ant.types.FilterChain | |||
filterreader=org.apache.tools.ant.types.AntFilterReader | |||
filterset=org.apache.tools.ant.types.FilterSet | |||
@@ -20,19 +16,15 @@ compositemapper=org.apache.tools.ant.util.CompositeMapper | |||
chainedmapper=org.apache.tools.ant.util.ChainedMapper | |||
filtermapper=org.apache.tools.ant.types.mappers.FilterMapper | |||
path=org.apache.tools.ant.types.Path | |||
patternset=org.apache.tools.ant.types.PatternSet | |||
regexp=org.apache.tools.ant.types.RegularExpression | |||
substitution=org.apache.tools.ant.types.Substitution | |||
xmlcatalog=org.apache.tools.ant.types.XMLCatalog | |||
extensionSet=org.apache.tools.ant.taskdefs.optional.extension.ExtensionSet | |||
extension=org.apache.tools.ant.taskdefs.optional.extension.ExtensionAdapter | |||
libfileset=org.apache.tools.ant.taskdefs.optional.extension.LibFileSet | |||
selector=org.apache.tools.ant.types.selectors.SelectSelector | |||
signedselector=org.apache.tools.ant.types.selectors.SignedSelector | |||
zipfileset=org.apache.tools.ant.types.ZipFileSet | |||
scriptfilter=org.apache.tools.ant.types.optional.ScriptFilter | |||
propertyset=org.apache.tools.ant.types.PropertySet | |||
assertions=org.apache.tools.ant.types.Assertions | |||
concatfilter=org.apache.tools.ant.filters.ConcatFilter | |||
issigned=org.apache.tools.ant.taskdefs.condition.IsSigned | |||
@@ -45,3 +37,28 @@ xor=org.apache.tools.ant.taskdefs.condition.Xor | |||
parsersupports=org.apache.tools.ant.taskdefs.condition.ParserSupports | |||
scriptmapper=org.apache.tools.ant.types.optional.ScriptMapper | |||
isfailure=org.apache.tools.ant.taskdefs.condition.IsFailure | |||
#ResourceCollections: | |||
dirset=org.apache.tools.ant.types.DirSet | |||
filelist=org.apache.tools.ant.types.FileList | |||
fileset=org.apache.tools.ant.types.FileSet | |||
path=org.apache.tools.ant.types.Path | |||
propertyset=org.apache.tools.ant.types.PropertySet | |||
zipfileset=org.apache.tools.ant.types.ZipFileSet | |||
classfileset=org.apache.tools.ant.types.optional.depend.ClassfileSet | |||
libfileset=org.apache.tools.ant.taskdefs.optional.extension.LibFileSet | |||
files=org.apache.tools.ant.types.resources.Files | |||
restrict=org.apache.tools.ant.types.resources.Restrict | |||
union=org.apache.tools.ant.types.resources.Union | |||
difference=org.apache.tools.ant.types.resources.Difference | |||
intersect=org.apache.tools.ant.types.resources.Intersect | |||
sort=org.apache.tools.ant.types.resources.Sort | |||
resources=org.apache.tools.ant.types.resources.Resources | |||
#Resources (single-element ResourceCollections): | |||
resource=org.apache.tools.ant.types.Resource | |||
file=org.apache.tools.ant.types.resources.FileResource | |||
url=org.apache.tools.ant.types.resources.URLResource | |||
string=org.apache.tools.ant.types.resources.StringResource | |||
zipentry=org.apache.tools.ant.types.resources.ZipResource | |||
propertyresource=org.apache.tools.ant.types.resources.PropertyResource |
@@ -0,0 +1,223 @@ | |||
/* | |||
* 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.types.resources; | |||
import java.io.File; | |||
import java.util.List; | |||
import java.util.Stack; | |||
import java.util.HashSet; | |||
import java.util.Iterator; | |||
import java.util.ArrayList; | |||
import java.util.Hashtable; | |||
import java.util.Collection; | |||
import java.util.Collections; | |||
import java.util.NoSuchElementException; | |||
import java.util.ConcurrentModificationException; | |||
import org.apache.tools.ant.Project; | |||
import org.apache.tools.ant.BuildException; | |||
import org.apache.tools.ant.types.DataType; | |||
import org.apache.tools.ant.types.Resource; | |||
import org.apache.tools.ant.types.ResourceCollection; | |||
/** | |||
* Base class for ResourceCollections that nest multiple ResourceCollections. | |||
* @since Ant 1.7 | |||
*/ | |||
public abstract class BaseResourceCollectionContainer | |||
extends DataType implements ResourceCollection, Cloneable { | |||
private List rc = new ArrayList(); | |||
private Collection coll = null; | |||
/** | |||
* Add a ResourceCollection to the container. | |||
* @param c the ResourceCollection to add. | |||
* @throws BuildException on error. | |||
*/ | |||
public synchronized void add(ResourceCollection c) throws BuildException { | |||
if (isReference()) { | |||
throw noChildrenAllowed(); | |||
} | |||
if (c == null) { | |||
return; | |||
} | |||
rc.add(c); | |||
FailFast.invalidate(this); | |||
coll = null; | |||
setChecked(false); | |||
} | |||
/** | |||
* Add the Collection of ResourceCollections to the container. | |||
* @param c the Collection whose elements to add. | |||
* @throws BuildException on error. | |||
*/ | |||
public synchronized void addAll(Collection c) throws BuildException { | |||
if (isReference()) { | |||
throw noChildrenAllowed(); | |||
} | |||
try { | |||
for (Iterator i = c.iterator(); i.hasNext();) { | |||
add((ResourceCollection) i.next()); | |||
} | |||
} catch (ClassCastException e) { | |||
throw new BuildException(e); | |||
} | |||
} | |||
/** | |||
* Fulfill the ResourceCollection contract. The Iterator returned | |||
* will throw ConcurrentModificationExceptions if ResourceCollections | |||
* are added to this container while the Iterator is in use. | |||
* @return a "fail-fast" Iterator. | |||
*/ | |||
public synchronized final Iterator iterator() { | |||
if (isReference()) { | |||
return ((BaseResourceCollectionContainer) getCheckedRef()).iterator(); | |||
} | |||
dieOnCircularReference(); | |||
cacheCollection(); | |||
return new FailFast(this, coll.iterator()); | |||
} | |||
/** | |||
* Fulfill the ResourceCollection contract. | |||
* @return number of elements as int. | |||
*/ | |||
public synchronized int size() { | |||
if (isReference()) { | |||
return ((BaseResourceCollectionContainer) getCheckedRef()).size(); | |||
} | |||
dieOnCircularReference(); | |||
cacheCollection(); | |||
return coll.size(); | |||
} | |||
/** | |||
* Fulfill the ResourceCollection contract. | |||
* @return whether this is a filesystem-only resource collection. | |||
*/ | |||
public synchronized boolean isFilesystemOnly() { | |||
if (isReference()) { | |||
return ((BaseResourceCollectionContainer) getCheckedRef()).isFilesystemOnly(); | |||
} | |||
dieOnCircularReference(); | |||
//first the easy way, if all children are filesystem-only, return true: | |||
boolean goEarly = true; | |||
for (Iterator i = rc.iterator(); goEarly && i.hasNext();) { | |||
goEarly &= ((ResourceCollection) i.next()).isFilesystemOnly(); | |||
} | |||
if (goEarly) { | |||
return true; | |||
} | |||
/* now check each Resource in case the child only | |||
lets through files from any children IT may have: */ | |||
cacheCollection(); | |||
for (Iterator i = coll.iterator(); i.hasNext();) { | |||
if (!(i.next() instanceof FileResource)) { | |||
return false; | |||
} | |||
} | |||
return true; | |||
} | |||
/** | |||
* Overrides the version of DataType to recurse on all DataType | |||
* child elements that may have been added. | |||
* @param stk the stack of data types to use (recursively). | |||
* @param p the project to use to dereference the references. | |||
* @throws BuildException on error. | |||
*/ | |||
protected void dieOnCircularReference(Stack stk, Project p) | |||
throws BuildException { | |||
if (isChecked()) { | |||
return; | |||
} | |||
if (isReference()) { | |||
super.dieOnCircularReference(stk, p); | |||
} else { | |||
for (Iterator i = rc.iterator(); i.hasNext();) { | |||
Object o = i.next(); | |||
if (o instanceof DataType) { | |||
stk.push(o); | |||
invokeCircularReferenceCheck((DataType) o, stk, p); | |||
stk.pop(); | |||
} | |||
} | |||
setChecked(true); | |||
} | |||
} | |||
/** | |||
* Get the nested ResourceCollections. | |||
* @return List. | |||
*/ | |||
protected synchronized final List getResourceCollections() { | |||
dieOnCircularReference(); | |||
return Collections.unmodifiableList(rc); | |||
} | |||
/** | |||
* Template method for subclasses to return a Collection object of Resources. | |||
* @return Collection. | |||
*/ | |||
protected abstract Collection getCollection(); | |||
/** | |||
* Implement clone. The set of nested resource | |||
* collections is shallowly cloned. | |||
* @return a cloned instance. | |||
*/ | |||
public Object clone() { | |||
try { | |||
BaseResourceCollectionContainer c | |||
= (BaseResourceCollectionContainer) super.clone(); | |||
c.rc = new ArrayList(rc); | |||
c.coll = null; | |||
return c; | |||
} catch (CloneNotSupportedException e) { | |||
throw new BuildException(e); | |||
} | |||
} | |||
/** | |||
* Format this BaseResourceCollectionContainer as a String. | |||
* @return a descriptive <code>String</code>. | |||
*/ | |||
public String toString() { | |||
if (isReference()) { | |||
return getCheckedRef().toString(); | |||
} | |||
cacheCollection(); | |||
if (coll.size() == 0) { | |||
return ""; | |||
} | |||
StringBuffer sb = new StringBuffer(); | |||
for (Iterator i = coll.iterator(); i.hasNext();) { | |||
if (sb.length() > 0) { | |||
sb.append(File.pathSeparatorChar); | |||
} | |||
sb.append(i.next()); | |||
} | |||
return sb.toString(); | |||
} | |||
private synchronized void cacheCollection() { | |||
coll = (coll == null) ? getCollection() : coll; | |||
} | |||
} |
@@ -0,0 +1,67 @@ | |||
/* | |||
* 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.types.resources; | |||
import java.util.List; | |||
import java.util.HashSet; | |||
import java.util.Iterator; | |||
import java.util.ArrayList; | |||
import java.util.Collection; | |||
import org.apache.tools.ant.Project; | |||
import org.apache.tools.ant.BuildException; | |||
import org.apache.tools.ant.types.ResourceCollection; | |||
/** | |||
* ResourceCollection representing the difference between | |||
* two or more nested ResourceCollections. | |||
* @since Ant 1.7 | |||
*/ | |||
public class Difference extends BaseResourceCollectionContainer { | |||
/** | |||
* Calculate the difference of the nested ResourceCollections. | |||
* @return a Collection of Resources. | |||
*/ | |||
protected Collection getCollection() { | |||
List rc = getResourceCollections(); | |||
int size = rc.size(); | |||
if (size < 2) { | |||
throw new BuildException("The difference of " + size | |||
+ " resource collection" + ((size == 1) ? "" : "s") | |||
+ " is undefined."); | |||
} | |||
HashSet hs = new HashSet(); | |||
ArrayList al = new ArrayList(); | |||
for (Iterator rcIter = rc.iterator(); rcIter.hasNext();) { | |||
for (Iterator r = nextRC(rcIter).iterator(); r.hasNext();) { | |||
Object next = r.next(); | |||
if (hs.add(next)) { | |||
al.add(next); | |||
} else { | |||
al.remove(next); | |||
} | |||
} | |||
} | |||
return al; | |||
} | |||
private static ResourceCollection nextRC(Iterator i) { | |||
return (ResourceCollection) i.next(); | |||
} | |||
} |
@@ -0,0 +1,132 @@ | |||
/* | |||
* 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.types.resources; | |||
import java.util.Set; | |||
import java.util.HashSet; | |||
import java.util.Iterator; | |||
import java.util.WeakHashMap; | |||
import java.util.NoSuchElementException; | |||
import java.util.ConcurrentModificationException; | |||
/** | |||
* Helper class for ResourceCollections to return Iterators | |||
* that fail on changes to the object. | |||
* @since Ant 1.7 | |||
*/ | |||
/*package-private*/ class FailFast implements Iterator { | |||
private static final WeakHashMap map = new WeakHashMap(); | |||
/** | |||
* Invalidate any in-use Iterators from the specified Object. | |||
* @param o the parent Object. | |||
*/ | |||
static synchronized void invalidate(Object o) { | |||
Set s = (Set) (map.get(o)); | |||
if (s != null) { | |||
s.clear(); | |||
} | |||
} | |||
private static synchronized void add(FailFast f) { | |||
Set s = (Set) (map.get(f.parent)); | |||
if (s == null) { | |||
s = new HashSet(); | |||
map.put(f.parent, s); | |||
} | |||
s.add(f); | |||
} | |||
private static synchronized void remove(FailFast f) { | |||
Set s = (Set) (map.get(f.parent)); | |||
if (s != null) { | |||
s.remove(f); | |||
} | |||
} | |||
private static synchronized void failFast(FailFast f) { | |||
Set s = (Set) (map.get(f.parent)); | |||
if (!s.contains(f)) { | |||
throw new ConcurrentModificationException(); | |||
} | |||
} | |||
private Object parent; | |||
private Iterator wrapped; | |||
/** | |||
* Construct a new FailFast Iterator wrapping the specified Iterator | |||
* and dependent upon the specified parent Object. | |||
* @param o the parent Object. | |||
* @param i the wrapped Iterator. | |||
*/ | |||
FailFast(Object o, Iterator i) { | |||
if (o == null) { | |||
throw new IllegalArgumentException("parent object is null"); | |||
} | |||
if (i == null) { | |||
throw new IllegalArgumentException("cannot wrap null iterator"); | |||
} | |||
parent = o; | |||
if (i.hasNext()) { | |||
wrapped = i; | |||
add(this); | |||
} | |||
} | |||
/** | |||
* Fulfill the Iterator contract. | |||
* @return true if there are more elements. | |||
*/ | |||
public boolean hasNext() { | |||
if (wrapped == null) { | |||
return false; | |||
} | |||
failFast(this); | |||
return wrapped.hasNext(); | |||
} | |||
/** | |||
* Fulfill the Iterator contract. | |||
* @return the next element. | |||
* @throws NoSuchElementException if no more elements. | |||
*/ | |||
public Object next() { | |||
if (wrapped == null || !wrapped.hasNext()) { | |||
throw new NoSuchElementException(); | |||
} | |||
failFast(this); | |||
try { | |||
return wrapped.next(); | |||
} finally { | |||
if (!wrapped.hasNext()) { | |||
wrapped = null; | |||
remove(this); | |||
} | |||
} | |||
} | |||
/** | |||
* Fulfill the Iterator contract. | |||
* @throws UnsupportedOperationException always. | |||
*/ | |||
public void remove() { | |||
throw new UnsupportedOperationException(); | |||
} | |||
} | |||
@@ -0,0 +1,300 @@ | |||
/* | |||
* 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.types.resources; | |||
import java.io.File; | |||
import java.io.IOException; | |||
import java.io.InputStream; | |||
import java.io.OutputStream; | |||
import java.io.FileInputStream; | |||
import java.io.FileOutputStream; | |||
import org.apache.tools.ant.Project; | |||
import org.apache.tools.ant.BuildException; | |||
import org.apache.tools.ant.util.FileUtils; | |||
import org.apache.tools.ant.types.Resource; | |||
import org.apache.tools.ant.types.Reference; | |||
/** | |||
* A Resource representation of a File. | |||
* @since Ant 1.7 | |||
*/ | |||
public class FileResource extends Resource implements Touchable { | |||
private static final FileUtils FILE_UTILS = FileUtils.getFileUtils(); | |||
private static final int NULL_FILE | |||
= Resource.getMagicNumber("null file".getBytes()); | |||
private File file; | |||
private File base; | |||
/** | |||
* Default constructor. | |||
*/ | |||
public FileResource() { | |||
} | |||
/** | |||
* Construct a new FileResource using the specified base File and relative name. | |||
* @param b the base File (directory). | |||
* @param name the relative filename. | |||
*/ | |||
public FileResource(File b, String name) { | |||
setFile(FILE_UTILS.resolveFile(b, name)); | |||
setBase(b); | |||
} | |||
/** | |||
* Construct a new FileResource from a File. | |||
* @param f the File represented. | |||
*/ | |||
public FileResource(File f) { | |||
setFile(f); | |||
} | |||
/** | |||
* Constructor for Ant attribute introspection. | |||
* @param p the Project against which to resolve <code>s</code>. | |||
* @param s the absolute or Project-relative filename as a String. | |||
* @see org.apache.tools.ant.IntrospectionHelper | |||
*/ | |||
public FileResource(Project p, String s) { | |||
this(p.resolveFile(s)); | |||
setProject(p); | |||
} | |||
/** | |||
* Set the File for this FileResource. | |||
* @param f the File to be represented. | |||
*/ | |||
public void setFile(File f) { | |||
checkAttributesAllowed(); | |||
file = f; | |||
} | |||
/** | |||
* Get the file represented by this FileResource. | |||
* @return the File. | |||
*/ | |||
public File getFile() { | |||
return isReference() ? ((FileResource) getCheckedRef()).getFile() : file; | |||
} | |||
/** | |||
* Set the base File for this FileResource. | |||
* @param b the base File. | |||
*/ | |||
public void setBase(File b) { | |||
checkAttributesAllowed(); | |||
base = b; | |||
} | |||
/** | |||
* Return the base to which the name is relative. | |||
* @return the base File. | |||
*/ | |||
public File getBase() { | |||
return isReference() | |||
? ((FileResource) getCheckedRef()).getBase() : base; | |||
} | |||
/** | |||
* Overrides the super version. | |||
* @param r the Reference to set. | |||
*/ | |||
public void setRefid(Reference r) { | |||
if (file != null || base != null) { | |||
throw tooManyAttributes(); | |||
} | |||
super.setRefid(r); | |||
} | |||
/** | |||
* Get the name of this FileResource relative to its base, if any. | |||
* @return the name of this resource. | |||
*/ | |||
public String getName() { | |||
if (isReference()) { | |||
return ((Resource) getCheckedRef()).getName(); | |||
} | |||
File b = getBase(); | |||
return b == null ? getNotNullFile().getAbsolutePath() | |||
: FILE_UTILS.removeLeadingPath(b, getNotNullFile()); | |||
} | |||
/** | |||
* Learn whether this file exists. | |||
* @return true if this resource exists. | |||
*/ | |||
public boolean isExists() { | |||
return isReference() ? ((Resource) getCheckedRef()).isExists() | |||
: getNotNullFile().exists(); | |||
} | |||
/** | |||
* Get the modification time in milliseconds since 01.01.1970 . | |||
* @return 0 if the resource does not exist. | |||
*/ | |||
public long getLastModified() { | |||
return isReference() | |||
? ((Resource) getCheckedRef()).getLastModified() | |||
: getNotNullFile().lastModified(); | |||
} | |||
/** | |||
* Learn whether the resource is a directory. | |||
* @return boolean flag indicating if the resource is a directory. | |||
*/ | |||
public boolean isDirectory() { | |||
return isReference() ? ((Resource) getCheckedRef()).isDirectory() | |||
: getNotNullFile().isDirectory(); | |||
} | |||
/** | |||
* Get the size of this Resource. | |||
* @return the size, as a long, 0 if the Resource does not exist. | |||
*/ | |||
public long getSize() { | |||
return isReference() ? ((Resource) getCheckedRef()).getSize() | |||
: getNotNullFile().length(); | |||
} | |||
/** | |||
* Return an InputStream for reading the contents of this Resource. | |||
* @return an InputStream object. | |||
* @throws IOException if an error occurs. | |||
*/ | |||
public InputStream getInputStream() throws IOException { | |||
return isReference() | |||
? ((Resource) getCheckedRef()).getInputStream() | |||
: new FileInputStream(getNotNullFile()); | |||
} | |||
/** | |||
* Get an OutputStream for the Resource. | |||
* @return an OutputStream to which content can be written. | |||
* @throws IOException if unable to provide the content of this | |||
* Resource as a stream. | |||
* @throws UnsupportedOperationException if OutputStreams are not | |||
* supported for this Resource type. | |||
*/ | |||
public OutputStream getOutputStream() throws IOException { | |||
if (isReference()) { | |||
return ((Resource) getCheckedRef()).getOutputStream(); | |||
} | |||
File f = getNotNullFile(); | |||
if (f.exists()) { | |||
if (f.isFile()) { | |||
f.delete(); | |||
} | |||
} else { | |||
File p = f.getParentFile(); | |||
if (p != null && !(p.exists())) { | |||
p.mkdirs(); | |||
} | |||
} | |||
return new FileOutputStream(f); | |||
} | |||
/** | |||
* Compare this FileResource to another Resource. | |||
* @param another the other Resource against which to compare. | |||
* @return a negative integer, zero, or a positive integer as this FileResource | |||
* is less than, equal to, or greater than the specified Resource. | |||
*/ | |||
public int compareTo(Object another) { | |||
if (isReference()) { | |||
return ((Comparable) getCheckedRef()).compareTo(another); | |||
} | |||
return this.equals(another) ? 0 : super.compareTo(another); | |||
} | |||
/** | |||
* Compare another Object to this FileResource for equality. | |||
* @param another the other Object to compare. | |||
* @return true if another is a FileResource representing the same file. | |||
*/ | |||
public boolean equals(Object another) { | |||
if (this == another) { | |||
return true; | |||
} | |||
if (isReference()) { | |||
return getCheckedRef().equals(another); | |||
} | |||
if (!(another.getClass().equals(getClass()))) { | |||
return false; | |||
} | |||
FileResource otherfr = (FileResource) another; | |||
return getFile() == null | |||
? otherfr.getFile() == null | |||
: getFile().equals(otherfr.getFile()); | |||
} | |||
/** | |||
* Get the hash code for this Resource. | |||
* @return hash code as int. | |||
*/ | |||
public int hashCode() { | |||
if (isReference()) { | |||
return getCheckedRef().hashCode(); | |||
} | |||
return MAGIC * (getFile() == null ? NULL_FILE : getFile().hashCode()); | |||
} | |||
/** | |||
* Get the string representation of this Resource. | |||
* @return this FileResource formatted as a String. | |||
*/ | |||
public String toString() { | |||
return isReference() ? getCheckedRef().toString() | |||
: FILE_UTILS.normalize(file.getAbsolutePath()).getAbsolutePath(); | |||
} | |||
/** | |||
* Fulfill the ResourceCollection contract. | |||
* @return whether this Resource is a FileResource. | |||
*/ | |||
public boolean isFilesystemOnly() { | |||
return !isReference() | |||
|| ((FileResource) getCheckedRef()).isFilesystemOnly(); | |||
} | |||
/** | |||
* Implement the Touchable interface. | |||
* @param modTime new last modification time. | |||
*/ | |||
public void touch(long modTime) { | |||
if (isReference()) { | |||
((FileResource) getCheckedRef()).touch(modTime); | |||
return; | |||
} | |||
getNotNullFile().setLastModified(modTime); | |||
} | |||
/** | |||
* Get the file represented by this FileResource, ensuring it is not null. | |||
* @return the not-null File. | |||
* @throws BuildException if file is null. | |||
*/ | |||
protected File getNotNullFile() { | |||
if (getFile() == null) { | |||
throw new BuildException("file attribute is null!"); | |||
} | |||
return getFile(); | |||
} | |||
} |
@@ -0,0 +1,108 @@ | |||
/* | |||
* 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.types.resources; | |||
import java.io.File; | |||
import java.util.Arrays; | |||
import java.util.Iterator; | |||
import java.util.ArrayList; | |||
import java.util.NoSuchElementException; | |||
/** | |||
* Iterator of FileResources from filenames. | |||
* @since Ant 1.7 | |||
*/ | |||
public class FileResourceIterator implements Iterator { | |||
private File basedir; | |||
private String[] files; | |||
private int pos = 0; | |||
/** | |||
* Construct a new FileResourceIterator. | |||
*/ | |||
public FileResourceIterator() { | |||
} | |||
/** | |||
* Construct a new FileResourceIterator relative to the specified | |||
* base directory. | |||
* @param f the base directory of this instance. | |||
*/ | |||
public FileResourceIterator(File f) { | |||
basedir = f; | |||
} | |||
/** | |||
* Construct a new FileResourceIterator over the specified filenames, | |||
* relative to the specified base directory. | |||
* @param f the base directory of this instance. | |||
* @param files the String[] of filenames. | |||
*/ | |||
public FileResourceIterator(File f, String[] s) { | |||
this(f); | |||
addFiles(s); | |||
} | |||
/** | |||
* Add an array of filenames to this FileResourceIterator. | |||
* @param s the filenames to add. | |||
*/ | |||
public void addFiles(String[] s) { | |||
int start = (files == null) ? 0 : files.length; | |||
String[] newfiles = new String[start + s.length]; | |||
if (start > 0) { | |||
System.arraycopy(files, 0, newfiles, 0, start); | |||
} | |||
files = newfiles; | |||
System.arraycopy(s, 0, files, start, s.length); | |||
} | |||
/** | |||
* Find out whether this FileResourceIterator has more elements. | |||
* @return whether there are more Resources to iterate over. | |||
*/ | |||
public boolean hasNext() { | |||
return pos < files.length; | |||
} | |||
/** | |||
* Get the next element from this FileResourceIterator. | |||
* @return the next Object. | |||
*/ | |||
public Object next() { | |||
return nextResource(); | |||
} | |||
/** | |||
* Not implemented. | |||
*/ | |||
public void remove() { | |||
throw new UnsupportedOperationException(); | |||
} | |||
/** | |||
* Convenience method to return the next resource. | |||
* @return the next File. | |||
*/ | |||
public FileResource nextResource() { | |||
if (!hasNext()) { | |||
throw new NoSuchElementException(); | |||
} | |||
return new FileResource(basedir, files[pos++]); | |||
} | |||
} |
@@ -0,0 +1,503 @@ | |||
/* | |||
* 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.types.resources; | |||
import java.io.File; | |||
import java.util.Stack; | |||
import java.util.Arrays; | |||
import java.util.Vector; | |||
import java.util.Iterator; | |||
import java.util.ArrayList; | |||
import java.util.Collections; | |||
import java.util.Enumeration; | |||
import org.apache.tools.ant.Project; | |||
import org.apache.tools.ant.BuildException; | |||
import org.apache.tools.ant.DirectoryScanner; | |||
import org.apache.tools.ant.types.Reference; | |||
import org.apache.tools.ant.types.PatternSet; | |||
import org.apache.tools.ant.types.ResourceCollection; | |||
import org.apache.tools.ant.types.selectors.FileSelector; | |||
import org.apache.tools.ant.types.selectors.AbstractSelectorContainer; | |||
/** | |||
* ResourceCollection implementation; like AbstractFileSet with absolute paths. | |||
* @since Ant 1.7 | |||
*/ | |||
public class Files extends AbstractSelectorContainer | |||
implements Cloneable, ResourceCollection { | |||
private static final Iterator EMPTY_ITERATOR | |||
= Collections.EMPTY_SET.iterator(); | |||
private PatternSet defaultPatterns = new PatternSet(); | |||
private Vector additionalPatterns = new Vector(); | |||
private Vector selectors = new Vector(); | |||
private boolean useDefaultExcludes = true; | |||
private boolean caseSensitive = true; | |||
private boolean followSymlinks = true; | |||
/* cached DirectoryScanner instance */ | |||
private DirectoryScanner ds = null; | |||
/** | |||
* Construct a new <code>Files</code> collection. | |||
*/ | |||
public Files() { | |||
super(); | |||
} | |||
/** | |||
* Construct a new <code>Files</code> collection, shallowly cloned | |||
* from the specified <code>Files</code>. | |||
* @param f the <code>Files</code> to use as a template. | |||
*/ | |||
protected Files(Files f) { | |||
this.defaultPatterns = f.defaultPatterns; | |||
this.additionalPatterns = f.additionalPatterns; | |||
this.selectors = f.selectors; | |||
this.useDefaultExcludes = f.useDefaultExcludes; | |||
this.caseSensitive = f.caseSensitive; | |||
this.followSymlinks = f.followSymlinks; | |||
this.ds = f.ds; | |||
setProject(f.getProject()); | |||
} | |||
/** | |||
* Make this instance in effect a reference to another instance. | |||
* | |||
* <p>You must not set another attribute or nest elements inside | |||
* this element if you make it a reference.</p> | |||
* @param r the <code>Reference</code> to use. | |||
*/ | |||
public void setRefid(Reference r) throws BuildException { | |||
if (hasPatterns(defaultPatterns)) { | |||
throw tooManyAttributes(); | |||
} | |||
if (!additionalPatterns.isEmpty()) { | |||
throw noChildrenAllowed(); | |||
} | |||
if (!selectors.isEmpty()) { | |||
throw noChildrenAllowed(); | |||
} | |||
super.setRefid(r); | |||
} | |||
/** | |||
* Create a nested patternset. | |||
* @return <code>PatternSet</code>. | |||
*/ | |||
public synchronized PatternSet createPatternSet() { | |||
if (isReference()) { | |||
throw noChildrenAllowed(); | |||
} | |||
PatternSet patterns = new PatternSet(); | |||
additionalPatterns.addElement(patterns); | |||
ds = null; | |||
return patterns; | |||
} | |||
/** | |||
* Add a name entry to the include list. | |||
* @return <code>PatternSet.NameEntry</code>. | |||
*/ | |||
public synchronized PatternSet.NameEntry createInclude() { | |||
if (isReference()) { | |||
throw noChildrenAllowed(); | |||
} | |||
ds = null; | |||
return defaultPatterns.createInclude(); | |||
} | |||
/** | |||
* Add a name entry to the include files list. | |||
* @return <code>PatternSet.NameEntry</code>. | |||
*/ | |||
public synchronized PatternSet.NameEntry createIncludesFile() { | |||
if (isReference()) { | |||
throw noChildrenAllowed(); | |||
} | |||
ds = null; | |||
return defaultPatterns.createIncludesFile(); | |||
} | |||
/** | |||
* Add a name entry to the exclude list. | |||
* @return <code>PatternSet.NameEntry</code>. | |||
*/ | |||
public synchronized PatternSet.NameEntry createExclude() { | |||
if (isReference()) { | |||
throw noChildrenAllowed(); | |||
} | |||
ds = null; | |||
return defaultPatterns.createExclude(); | |||
} | |||
/** | |||
* Add a name entry to the excludes files list. | |||
* @return <code>PatternSet.NameEntry</code>. | |||
*/ | |||
public synchronized PatternSet.NameEntry createExcludesFile() { | |||
if (isReference()) { | |||
throw noChildrenAllowed(); | |||
} | |||
ds = null; | |||
return defaultPatterns.createExcludesFile(); | |||
} | |||
/** | |||
* Append <code>includes</code> to the current list of include | |||
* patterns. | |||
* | |||
* <p>Patterns may be separated by a comma or a space.</p> | |||
* | |||
* @param includes the <code>String</code> containing the include patterns. | |||
*/ | |||
public synchronized void setIncludes(String includes) { | |||
checkAttributesAllowed(); | |||
defaultPatterns.setIncludes(includes); | |||
ds = null; | |||
} | |||
/** | |||
* Append <code>includes</code> to the current list of include | |||
* patterns. | |||
* | |||
* @param includes array containing the include patterns. | |||
*/ | |||
public synchronized void appendIncludes(String[] includes) { | |||
checkAttributesAllowed(); | |||
if (includes != null) { | |||
for (int i = 0; i < includes.length; i++) { | |||
defaultPatterns.createInclude().setName(includes[i]); | |||
} | |||
ds = null; | |||
} | |||
} | |||
/** | |||
* Append <code>excludes</code> to the current list of exclude | |||
* patterns. | |||
* | |||
* <p>Patterns may be separated by a comma or a space.</p> | |||
* | |||
* @param excludes the <code>String</code> containing the exclude patterns. | |||
*/ | |||
public synchronized void setExcludes(String excludes) { | |||
checkAttributesAllowed(); | |||
defaultPatterns.setExcludes(excludes); | |||
ds = null; | |||
} | |||
/** | |||
* Append <code>excludes</code> to the current list of include | |||
* patterns. | |||
* | |||
* @param excludes array containing the exclude patterns. | |||
*/ | |||
public synchronized void appendExcludes(String[] excludes) { | |||
checkAttributesAllowed(); | |||
if (excludes != null) { | |||
for (int i = 0; i < excludes.length; i++) { | |||
defaultPatterns.createExclude().setName(excludes[i]); | |||
} | |||
ds = null; | |||
} | |||
} | |||
/** | |||
* Set the <code>File</code> containing the includes patterns. | |||
* | |||
* @param incl <code>File</code> instance. | |||
*/ | |||
public synchronized void setIncludesfile(File incl) throws BuildException { | |||
checkAttributesAllowed(); | |||
defaultPatterns.setIncludesfile(incl); | |||
ds = null; | |||
} | |||
/** | |||
* Set the <code>File</code> containing the excludes patterns. | |||
* | |||
* @param excl <code>File</code> instance. | |||
*/ | |||
public synchronized void setExcludesfile(File excl) throws BuildException { | |||
checkAttributesAllowed(); | |||
defaultPatterns.setExcludesfile(excl); | |||
ds = null; | |||
} | |||
/** | |||
* Set whether default exclusions should be used or not. | |||
* | |||
* @param useDefaultExcludes <code>boolean</code>. | |||
*/ | |||
public synchronized void setDefaultexcludes(boolean useDefaultExcludes) { | |||
checkAttributesAllowed(); | |||
this.useDefaultExcludes = useDefaultExcludes; | |||
ds = null; | |||
} | |||
/** | |||
* Get whether default exclusions should be used or not. | |||
*/ | |||
public synchronized boolean getDefaultexcludes() { | |||
return (isReference()) | |||
? getRef().getDefaultexcludes() : useDefaultExcludes; | |||
} | |||
/** | |||
* Set case-sensitivity of the Files collection. | |||
* | |||
* @param caseSensitive <code>boolean</code>. | |||
*/ | |||
public synchronized void setCaseSensitive(boolean caseSensitive) { | |||
checkAttributesAllowed(); | |||
this.caseSensitive = caseSensitive; | |||
ds = null; | |||
} | |||
/** | |||
* Find out if this Files collection is case-sensitive. | |||
* | |||
* @return <code>boolean</code> indicating whether the Files | |||
* collection is case-sensitive. | |||
*/ | |||
public synchronized boolean isCaseSensitive() { | |||
return (isReference()) | |||
? getRef().isCaseSensitive() : caseSensitive; | |||
} | |||
/** | |||
* Set whether or not symbolic links should be followed. | |||
* | |||
* @param followSymlinks whether or not symbolic links should be followed. | |||
*/ | |||
public synchronized void setFollowSymlinks(boolean followSymlinks) { | |||
checkAttributesAllowed(); | |||
this.followSymlinks = followSymlinks; | |||
ds = null; | |||
} | |||
/** | |||
* Find out whether symbolic links should be followed. | |||
* | |||
* @return <code>boolean</code> indicating whether symbolic links | |||
* should be followed. | |||
*/ | |||
public synchronized boolean isFollowSymlinks() { | |||
return (isReference()) | |||
? getRef().isFollowSymlinks() : followSymlinks; | |||
} | |||
/** | |||
* Fulfill the ResourceCollection contract. | |||
* @return an Iterator of Resources. | |||
*/ | |||
public synchronized Iterator iterator() { | |||
if (isReference()) { | |||
return getRef().iterator(); | |||
} | |||
ensureDirectoryScannerSetup(); | |||
ds.scan(); | |||
int fct = ds.getIncludedFilesCount(); | |||
int dct = ds.getIncludedDirsCount(); | |||
if (fct + dct == 0) { | |||
return EMPTY_ITERATOR; | |||
} | |||
FileResourceIterator result = new FileResourceIterator(); | |||
if (fct > 0) { | |||
result.addFiles(ds.getIncludedFiles()); | |||
} | |||
if (dct > 0) { | |||
result.addFiles(ds.getIncludedDirectories()); | |||
} | |||
return result; | |||
} | |||
/** | |||
* Fulfill the ResourceCollection contract. | |||
* @return number of elements as int. | |||
*/ | |||
public synchronized int size() { | |||
if (isReference()) { | |||
return getRef().size(); | |||
} | |||
ensureDirectoryScannerSetup(); | |||
ds.scan(); | |||
return ds.getIncludedFilesCount() + ds.getIncludedDirsCount(); | |||
} | |||
/** | |||
* Find out whether this Files collection has patterns. | |||
* | |||
* @return whether any patterns are in this container. | |||
*/ | |||
public synchronized boolean hasPatterns() { | |||
if (isReference()) { | |||
return getRef().hasPatterns(); | |||
} | |||
if (hasPatterns(defaultPatterns)) { | |||
return true; | |||
} | |||
for (Iterator i = additionalPatterns.iterator(); i.hasNext();) { | |||
if (hasPatterns((PatternSet) i.next())) { | |||
return true; | |||
} | |||
} | |||
return false; | |||
} | |||
/** | |||
* Add a new selector into this container. | |||
* | |||
* @param selector the new <code>FileSelector</code> to add. | |||
*/ | |||
public synchronized void appendSelector(FileSelector selector) { | |||
if (isReference()) { | |||
throw noChildrenAllowed(); | |||
} | |||
super.appendSelector(selector); | |||
ds = null; | |||
} | |||
/** | |||
* Format this Files collection as a String. | |||
* @return a descriptive <code>String</code>. | |||
*/ | |||
public String toString() { | |||
if (isReference()) { | |||
return getRef().toString(); | |||
} | |||
Iterator i = iterator(); | |||
if (!i.hasNext()) { | |||
return ""; | |||
} | |||
StringBuffer sb = new StringBuffer(); | |||
while (i.hasNext()) { | |||
if (sb.length() > 0) { | |||
sb.append(File.pathSeparatorChar); | |||
} | |||
sb.append(i.next()); | |||
} | |||
return sb.toString(); | |||
} | |||
/** | |||
* Create a deep clone of this instance, except for the nested selectors | |||
* (the list of selectors is a shallow clone of this instance's list). | |||
* @return a cloned Object. | |||
*/ | |||
public synchronized Object clone() { | |||
if (isReference()) { | |||
return getRef().clone(); | |||
} | |||
try { | |||
Files f = (Files) super.clone(); | |||
f.defaultPatterns = (PatternSet) defaultPatterns.clone(); | |||
f.additionalPatterns = new Vector(additionalPatterns.size()); | |||
for (Iterator iter = additionalPatterns.iterator(); iter.hasNext();) { | |||
PatternSet ps = (PatternSet) iter.next(); | |||
f.additionalPatterns.add(ps.clone()); | |||
} | |||
f.selectors = new Vector(selectors); | |||
return f; | |||
} catch (CloneNotSupportedException e) { | |||
throw new BuildException(e); | |||
} | |||
} | |||
/** | |||
* Get the merged include patterns for this Files collection. | |||
* @param p Project instance. | |||
* @return the include patterns of the default pattern set and all | |||
* nested patternsets. | |||
*/ | |||
public String[] mergeIncludes(Project p) { | |||
return mergePatterns(p).getIncludePatterns(p); | |||
} | |||
/** | |||
* Get the merged exclude patterns for this Files collection. | |||
* @param p Project instance. | |||
* @return the exclude patterns of the default pattern set and all | |||
* nested patternsets. | |||
*/ | |||
public String[] mergeExcludes(Project p) { | |||
return mergePatterns(p).getExcludePatterns(p); | |||
} | |||
/** | |||
* Get the merged patterns for this Files collection. | |||
* @param p Project instance. | |||
* @return the default patternset merged with the additional sets | |||
* in a new PatternSet instance. | |||
*/ | |||
public synchronized PatternSet mergePatterns(Project p) { | |||
if (isReference()) { | |||
return getRef().mergePatterns(p); | |||
} | |||
PatternSet ps = new PatternSet(); | |||
ps.append(defaultPatterns, p); | |||
final int count = additionalPatterns.size(); | |||
for (int i = 0; i < count; i++) { | |||
Object o = additionalPatterns.elementAt(i); | |||
ps.append((PatternSet) o, p); | |||
} | |||
return ps; | |||
} | |||
/** | |||
* Always returns true. | |||
* @return true indicating that all elements of a Files collection | |||
* will be FileResources. | |||
*/ | |||
public boolean isFilesystemOnly() { | |||
return true; | |||
} | |||
/** | |||
* Perform the check for circular references and return the | |||
* referenced Files collection. | |||
* @return <code>FileCollection</code>. | |||
*/ | |||
protected Files getRef() { | |||
return (Files) getCheckedRef(); | |||
} | |||
private synchronized void ensureDirectoryScannerSetup() { | |||
if (ds == null) { | |||
ds = new DirectoryScanner(); | |||
PatternSet ps = mergePatterns(getProject()); | |||
ds.setIncludes(ps.getIncludePatterns(getProject())); | |||
ds.setExcludes(ps.getExcludePatterns(getProject())); | |||
ds.setSelectors(getSelectors(getProject())); | |||
if (useDefaultExcludes) { | |||
ds.addDefaultExcludes(); | |||
} | |||
ds.setCaseSensitive(caseSensitive); | |||
ds.setFollowSymlinks(followSymlinks); | |||
} | |||
} | |||
private boolean hasPatterns(PatternSet ps) { | |||
return ps.getIncludePatterns(getProject()).length > 0 | |||
|| ps.getExcludePatterns(getProject()).length > 0; | |||
} | |||
} |
@@ -0,0 +1,44 @@ | |||
/* | |||
* 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.types.resources; | |||
import java.io.IOException; | |||
/** | |||
* Exception thrown when an attempt is made to get an OutputStream | |||
* from an immutable Resource. | |||
* @since Ant 1.7 | |||
*/ | |||
public class ImmutableResourceException extends IOException { | |||
/** | |||
* Default constructor. | |||
*/ | |||
public ImmutableResourceException() { | |||
super(); | |||
} | |||
/** | |||
* Construct a new ImmutableResourceException with the specified message. | |||
* @param s the message String. | |||
*/ | |||
public ImmutableResourceException(String s) { | |||
super(s); | |||
} | |||
} |
@@ -0,0 +1,62 @@ | |||
/* | |||
* 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.types.resources; | |||
import java.util.List; | |||
import java.util.Iterator; | |||
import java.util.ArrayList; | |||
import java.util.Collection; | |||
import org.apache.tools.ant.BuildException; | |||
import org.apache.tools.ant.types.ResourceCollection; | |||
/** | |||
* ResourceCollection representing the intersection | |||
* of multiple nested ResourceCollections. | |||
* @since Ant 1.7 | |||
*/ | |||
public class Intersect extends BaseResourceCollectionContainer { | |||
/** | |||
* Calculate the intersection of the nested ResourceCollections. | |||
* @return a Collection of Resources. | |||
*/ | |||
protected Collection getCollection() { | |||
List rcs = getResourceCollections(); | |||
int size = rcs.size(); | |||
if (size < 2) { | |||
throw new BuildException("The intersection of " + size | |||
+ " resource collection" + ((size == 1) ? "" : "s") | |||
+ " is undefined."); | |||
} | |||
ArrayList al = new ArrayList(); | |||
Iterator rc = rcs.iterator(); | |||
al.addAll(collect(rc.next())); | |||
while (rc.hasNext()) { | |||
al.retainAll(collect(rc.next())); | |||
} | |||
return al; | |||
} | |||
private ArrayList collect(Object o) { | |||
ArrayList result = new ArrayList(); | |||
for (Iterator i = ((ResourceCollection) o).iterator(); i.hasNext();) { | |||
result.add(i.next()); | |||
} | |||
return result; | |||
} | |||
} |
@@ -0,0 +1,133 @@ | |||
/* | |||
* 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.types.resources; | |||
import java.io.IOException; | |||
import java.io.InputStream; | |||
import java.io.OutputStream; | |||
import java.io.ByteArrayInputStream; | |||
import org.apache.tools.ant.Project; | |||
import org.apache.tools.ant.types.Resource; | |||
import org.apache.tools.ant.util.PropertyOutputStream; | |||
/** | |||
* Exposes an Ant property as a Resource. | |||
* @since Ant 1.7 | |||
*/ | |||
public class PropertyResource extends Resource { | |||
/** Magic number */ | |||
private static final int PROPERTY_MAGIC | |||
= Resource.getMagicNumber("PropertyResource".getBytes()); | |||
private static final InputStream UNSET = new InputStream() { | |||
public int read() { | |||
return -1; | |||
} | |||
}; | |||
/** | |||
* Default constructor. | |||
*/ | |||
public PropertyResource() { | |||
} | |||
/** | |||
* Construct a new PropertyResource with the specified name. | |||
* @param n the String name of this PropertyResource (Ant property name/key). | |||
*/ | |||
public PropertyResource(Project p, String n) { | |||
super(n); | |||
setProject(p); | |||
} | |||
/** | |||
* Get the value of this PropertyResource. | |||
* @return the value of the specified Property. | |||
*/ | |||
public String getValue() { | |||
Project p = getProject(); | |||
return p == null ? null : p.getProperty(getName()); | |||
} | |||
/** | |||
* Find out whether this Resource exists. | |||
* @return true if the Property is set, false otherwise. | |||
*/ | |||
public boolean isExists() { | |||
return getValue() != null; | |||
} | |||
/** | |||
* Get the size of this Resource. | |||
* @return the size, as a long, 0 if the Resource does not exist (for | |||
* compatibility with java.io.File), or UNKNOWN_SIZE if not known. | |||
*/ | |||
public long getSize() { | |||
if (isReference()) { | |||
return ((Resource) getCheckedRef()).getSize(); | |||
} | |||
return isExists() ? (long) getValue().length() : 0L; | |||
} | |||
/** | |||
* Get the hash code for this Resource. | |||
* @return hash code as int. | |||
*/ | |||
public int hashCode() { | |||
if (isReference()) { | |||
return getCheckedRef().hashCode(); | |||
} | |||
return super.hashCode() * PROPERTY_MAGIC; | |||
} | |||
/** | |||
* Get an InputStream for the Resource. | |||
* @return an InputStream containing this Resource's content. | |||
* @throws IOException if unable to provide the content of this | |||
* Resource as a stream. | |||
* @throws UnsupportedOperationException if InputStreams are not | |||
* supported for this Resource type. | |||
*/ | |||
public InputStream getInputStream() throws IOException { | |||
if (isReference()) { | |||
return ((Resource) getCheckedRef()).getInputStream(); | |||
} | |||
return isExists() ? new ByteArrayInputStream(getValue().getBytes()) : UNSET; | |||
} | |||
/** | |||
* Get an OutputStream for the Resource. | |||
* @return an OutputStream to which content can be written. | |||
* @throws IOException if unable to provide the content of this | |||
* Resource as a stream. | |||
* @throws UnsupportedOperationException if OutputStreams are not | |||
* supported for this Resource type. | |||
*/ | |||
public OutputStream getOutputStream() throws IOException { | |||
if (isReference()) { | |||
return ((Resource) getCheckedRef()).getOutputStream(); | |||
} | |||
if (isExists()) { | |||
throw new ImmutableResourceException(); | |||
} | |||
return new PropertyOutputStream(getProject(), getName()); | |||
} | |||
} |
@@ -0,0 +1,187 @@ | |||
/* | |||
* 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.types.resources; | |||
import java.util.List; | |||
import java.util.Stack; | |||
import java.util.Vector; | |||
import java.util.Iterator; | |||
import java.util.Collection; | |||
import java.util.AbstractCollection; | |||
import java.util.NoSuchElementException; | |||
import org.apache.tools.ant.Project; | |||
import org.apache.tools.ant.BuildException; | |||
import org.apache.tools.ant.types.DataType; | |||
import org.apache.tools.ant.types.ResourceCollection; | |||
/** | |||
* Generic ResourceCollection: Either stores nested ResourceCollections, | |||
* making no attempt to remove duplicates, or references another ResourceCollection. | |||
* @since Ant 1.7 | |||
*/ | |||
public class Resources extends DataType implements ResourceCollection { | |||
private class MyCollection extends AbstractCollection { | |||
int size; | |||
MyCollection() { | |||
size = 0; | |||
for (Iterator rci = rc.iterator(); rci.hasNext();) { | |||
size += ((ResourceCollection) rci.next()).size(); | |||
} | |||
} | |||
public int size() { | |||
return size; | |||
} | |||
public Iterator iterator() { | |||
return new MyIterator(); | |||
} | |||
private class MyIterator implements Iterator { | |||
Iterator rci = rc.iterator(); | |||
Iterator ri = null; | |||
public boolean hasNext() { | |||
if ((ri == null || !ri.hasNext()) && rci.hasNext()) { | |||
ri = ((ResourceCollection) rci.next()).iterator(); | |||
} | |||
return ri != null && ri.hasNext(); | |||
} | |||
public Object next() { | |||
if (!hasNext()) { | |||
throw new NoSuchElementException(); | |||
} | |||
return ri.next(); | |||
} | |||
public void remove() { | |||
throw new UnsupportedOperationException(); | |||
} | |||
} | |||
} | |||
private Vector rc = null; | |||
private Collection coll = null; | |||
/** | |||
* Add a ResourceCollection. | |||
* @param c the ResourceCollection to add. | |||
*/ | |||
public synchronized void add(ResourceCollection c) { | |||
if (isReference()) { | |||
throw noChildrenAllowed(); | |||
} | |||
rc = (rc == null) ? new Vector() : rc; | |||
rc.add(c); | |||
FailFast.invalidate(this); | |||
coll = null; | |||
setChecked(false); | |||
} | |||
/** | |||
* Fulfill the ResourceCollection contract. | |||
* @return an Iterator of Resources. | |||
*/ | |||
public synchronized Iterator iterator() { | |||
if (isReference()) { | |||
return getRef().iterator(); | |||
} | |||
validate(); | |||
return new FailFast(this, coll.iterator()); | |||
} | |||
/** | |||
* Fulfill the ResourceCollection contract. | |||
* @return number of elements as int. | |||
*/ | |||
public synchronized int size() { | |||
if (isReference()) { | |||
return getRef().size(); | |||
} | |||
validate(); | |||
return coll.size(); | |||
} | |||
/** | |||
* Fulfill the ResourceCollection contract. | |||
* @return true if all Resources represent files. | |||
*/ | |||
public boolean isFilesystemOnly() { | |||
if (isReference()) { | |||
return getRef().isFilesystemOnly(); | |||
} | |||
validate(); | |||
//first the easy way, if all children are filesystem-only, return true: | |||
boolean goEarly = true; | |||
for (Iterator i = rc.iterator(); goEarly && i.hasNext();) { | |||
goEarly &= ((ResourceCollection) i.next()).isFilesystemOnly(); | |||
} | |||
if (goEarly) { | |||
return true; | |||
} | |||
/* now check each Resource in case the child only | |||
lets through files from any children IT may have: */ | |||
for (Iterator i = coll.iterator(); i.hasNext();) { | |||
if (!(i.next() instanceof FileResource)) { | |||
return false; | |||
} | |||
} | |||
return true; | |||
} | |||
/** | |||
* Overrides the version of DataType to recurse on all DataType | |||
* child elements that may have been added. | |||
* @param stk the stack of data types to use (recursively). | |||
* @param p the project to use to dereference the references. | |||
* @throws BuildException on error. | |||
*/ | |||
protected void dieOnCircularReference(Stack stk, Project p) | |||
throws BuildException { | |||
if (isChecked()) { | |||
return; | |||
} | |||
if (isReference()) { | |||
super.dieOnCircularReference(stk, p); | |||
} else { | |||
for (Iterator i = rc.iterator(); i.hasNext();) { | |||
Object o = i.next(); | |||
if (o instanceof DataType) { | |||
invokeCircularReferenceCheck((DataType) o, stk, p); | |||
} | |||
} | |||
setChecked(true); | |||
} | |||
} | |||
/** | |||
* Resolves references, allowing any ResourceCollection. | |||
* @return the referenced ResourceCollection. | |||
*/ | |||
private ResourceCollection getRef() { | |||
return (ResourceCollection) getCheckedRef( | |||
ResourceCollection.class, "ResourceCollection"); | |||
} | |||
private synchronized void validate() { | |||
dieOnCircularReference(); | |||
if (rc == null || rc.size() == 0) { | |||
throw new BuildException("Resources: no resources specified."); | |||
} | |||
coll = (coll == null) ? new MyCollection() : coll; | |||
} | |||
} |
@@ -0,0 +1,137 @@ | |||
/* | |||
* 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.types.resources; | |||
import java.util.Iterator; | |||
import java.util.ArrayList; | |||
import java.util.Collection; | |||
import org.apache.tools.ant.BuildException; | |||
import org.apache.tools.ant.types.Resource; | |||
import org.apache.tools.ant.types.ResourceCollection; | |||
import org.apache.tools.ant.types.resources.selectors.ResourceSelector; | |||
import org.apache.tools.ant.types.resources.selectors.ResourceSelectorContainer; | |||
/** | |||
* ResourceCollection that allows a number of selectors to be | |||
* applied to a single ResourceCollection for the purposes of | |||
* restricting or narrowing results. | |||
* @since Ant 1.7 | |||
*/ | |||
public class Restrict | |||
extends ResourceSelectorContainer implements ResourceCollection { | |||
private static final String ONE_NESTED_MESSAGE | |||
= "Restriction is to be applied to exactly one nested resource collection."; | |||
private ResourceCollection rc; | |||
/** | |||
* Add the ResourceCollection. | |||
* @param c the ResourceCollection to add. | |||
*/ | |||
public synchronized void add(ResourceCollection c) { | |||
if (isReference()) { | |||
throw noChildrenAllowed(); | |||
} | |||
if (rc != null) { | |||
throw new BuildException(ONE_NESTED_MESSAGE); | |||
} | |||
rc = c; | |||
} | |||
/** | |||
* Add a ResourceSelector. | |||
* @param the ResourceSelector to add. | |||
*/ | |||
public synchronized void add(ResourceSelector s) { | |||
super.add(s); | |||
FailFast.invalidate(this); | |||
} | |||
/** | |||
* Fulfill the ResourceCollection contract. | |||
* @return an Iterator of Resources. | |||
*/ | |||
public final synchronized Iterator iterator() { | |||
if (isReference()) { | |||
return ((Restrict) getCheckedRef()).iterator(); | |||
} | |||
dieOnCircularReference(); | |||
if (rc == null) { | |||
throw new BuildException(ONE_NESTED_MESSAGE); | |||
} | |||
return new FailFast(this, getCollection().iterator()); | |||
} | |||
/** | |||
* Fulfill the ResourceCollection contract. | |||
* @return number of elements as int. | |||
*/ | |||
public synchronized int size() { | |||
if (isReference()) { | |||
return ((Restrict) getCheckedRef()).size(); | |||
} | |||
dieOnCircularReference(); | |||
return getCollection().size(); | |||
} | |||
/** | |||
* Fulfill the ResourceCollection contract. | |||
* @return whether this is a filesystem-only resource collection. | |||
*/ | |||
public synchronized boolean isFilesystemOnly() { | |||
if (isReference()) { | |||
return ((Restrict) getCheckedRef()).isFilesystemOnly(); | |||
} | |||
dieOnCircularReference(); | |||
if (rc == null) { | |||
throw new BuildException(ONE_NESTED_MESSAGE); | |||
} | |||
//first the easy way, if child is filesystem-only, return true: | |||
if (rc.isFilesystemOnly()) { | |||
return true; | |||
} | |||
/* now check each Resource in case the child only | |||
lets through files from any children IT may have: */ | |||
for (Iterator i = getCollection().iterator(); i.hasNext();) { | |||
if (!(i.next() instanceof FileResource)) { | |||
return false; | |||
} | |||
} | |||
return true; | |||
} | |||
/** | |||
* Restrict the nested ResourceCollection based on the nested selectors. | |||
* @return a Collection of Resources. | |||
*/ | |||
protected Collection getCollection() { | |||
ArrayList result = new ArrayList(); | |||
outer: for (Iterator ri = rc.iterator(); ri.hasNext();) { | |||
Resource r = (Resource) ri.next(); | |||
for (Iterator i = getSelectors(); i.hasNext();) { | |||
if (!((ResourceSelector) (i.next())).isSelected(r)) { | |||
continue outer; | |||
} | |||
} | |||
result.add(r); | |||
} | |||
return result; | |||
} | |||
} |
@@ -0,0 +1,107 @@ | |||
/* | |||
* 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.types.resources; | |||
import java.util.List; | |||
import java.util.Stack; | |||
import java.util.Iterator; | |||
import java.util.ArrayList; | |||
import java.util.Collection; | |||
import java.util.Collections; | |||
import org.apache.tools.ant.Project; | |||
import org.apache.tools.ant.BuildException; | |||
import org.apache.tools.ant.types.DataType; | |||
import org.apache.tools.ant.types.ResourceCollection; | |||
import org.apache.tools.ant.types.resources.comparators.ResourceComparator; | |||
/** | |||
* ResourceCollection that sorts another ResourceCollection. | |||
* @since Ant 1.7 | |||
*/ | |||
public class Sort extends BaseResourceCollectionContainer { | |||
private static final String ONE_NESTED_MESSAGE | |||
= "Sorting is to be applied to exactly one nested resource collection."; | |||
private Stack compStack = new Stack(); | |||
/** | |||
* Sort the contained elements. | |||
* @return a Collection of Resources. | |||
*/ | |||
protected Collection getCollection() { | |||
List rcs = getResourceCollections(); | |||
if (rcs.size() != 1) { | |||
throw new BuildException(ONE_NESTED_MESSAGE); | |||
} | |||
Iterator nested = ((ResourceCollection) (rcs.get(0))).iterator(); | |||
if (!(nested.hasNext())) { | |||
return Collections.EMPTY_SET; | |||
} | |||
ArrayList al = new ArrayList(); | |||
while (nested.hasNext()) { | |||
al.add(nested.next()); | |||
} | |||
if (compStack.empty()) { | |||
Collections.sort(al); | |||
} else { | |||
for (Stack s = (Stack) compStack.clone(); !s.empty();) { | |||
Collections.sort(al, (ResourceComparator) s.pop()); | |||
} | |||
} | |||
return al; | |||
} | |||
/** | |||
* Add a ResourceComparator to this Sort ResourceCollection. | |||
* If multiple ResourceComparator are added, they will be processed in LIFO order. | |||
* @param c the ResourceComparator to add. | |||
*/ | |||
public void add(ResourceComparator c) { | |||
if (isReference()) { | |||
throw noChildrenAllowed(); | |||
} | |||
compStack.push(c); | |||
} | |||
/** | |||
* Overrides the BaseResourceCollectionContainer version | |||
* to recurse on nested ResourceComparators. | |||
* @param stk the stack of data types to use (recursively). | |||
* @param p the project to use to dereference the references. | |||
* @throws BuildException on error. | |||
*/ | |||
protected void dieOnCircularReference(Stack stk, Project p) | |||
throws BuildException { | |||
if (isChecked()) { | |||
return; | |||
} | |||
if (isReference()) { | |||
super.dieOnCircularReference(stk, p); | |||
} else { | |||
for (Iterator i = compStack.iterator(); i.hasNext();) { | |||
Object o = i.next(); | |||
if (o instanceof DataType) { | |||
stk.push(o); | |||
invokeCircularReferenceCheck((DataType) o, stk, p); | |||
} | |||
} | |||
setChecked(true); | |||
} | |||
} | |||
} |
@@ -0,0 +1,204 @@ | |||
/* | |||
* 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.types.resources; | |||
import java.io.IOException; | |||
import java.io.InputStream; | |||
import java.io.OutputStream; | |||
import java.io.FilterOutputStream; | |||
import java.io.ByteArrayInputStream; | |||
import java.io.ByteArrayOutputStream; | |||
import org.apache.tools.ant.Project; | |||
import org.apache.tools.ant.BuildException; | |||
import org.apache.tools.ant.types.Resource; | |||
import org.apache.tools.ant.types.Reference; | |||
/** | |||
* Exposes a string as a Resource. | |||
* @since Ant 1.7 | |||
*/ | |||
public class StringResource extends Resource { | |||
/** Magic number */ | |||
private static final int STRING_MAGIC | |||
= Resource.getMagicNumber("StringResource".getBytes()); | |||
private String encoding = null; | |||
/** | |||
* Default constructor. | |||
*/ | |||
public StringResource() { | |||
} | |||
/** | |||
* Construct a StringResource with the supplied value. | |||
* @param value the value of this StringResource. | |||
*/ | |||
public StringResource(String value) { | |||
setValue(value); | |||
} | |||
/** | |||
* Enforce String immutability. | |||
* @param s the new name/value for this StringResource. | |||
*/ | |||
public synchronized void setName(String s) { | |||
if (getName() != null) { | |||
throw new BuildException(new ImmutableResourceException()); | |||
} | |||
super.setName(s); | |||
} | |||
/** | |||
* The value attribute is a semantically superior alias for the name attribute. | |||
* @param s the String's value. | |||
*/ | |||
public synchronized void setValue(String s) { | |||
setName(s); | |||
} | |||
/** | |||
* Synchronize access. | |||
* @return the name/value of this StringResource. | |||
*/ | |||
public synchronized String getName() { | |||
return super.getName(); | |||
} | |||
/** | |||
* Get the value of this StringResource. | |||
* @return the represented String. | |||
*/ | |||
public synchronized String getValue() { | |||
return getName(); | |||
} | |||
/** | |||
* Set the encoding to be used for this StringResource. | |||
* @param s the encoding name. | |||
*/ | |||
public synchronized void setEncoding(String s) { | |||
encoding = s; | |||
} | |||
/** | |||
* Get the encoding used by this StringResource. | |||
* @return the encoding name. | |||
*/ | |||
public synchronized String getEncoding() { | |||
return encoding; | |||
} | |||
/** | |||
* Get the size of this Resource. | |||
* @return the size, as a long, 0 if the Resource does not exist (for | |||
* compatibility with java.io.File), or UNKNOWN_SIZE if not known. | |||
*/ | |||
public synchronized long getSize() { | |||
return isReference() | |||
? ((Resource) getCheckedRef()).getSize() | |||
: (long) getContent().length(); | |||
} | |||
/** | |||
* Get the hash code for this Resource. | |||
* @return hash code as int. | |||
*/ | |||
public synchronized int hashCode() { | |||
if (isReference()) { | |||
return getCheckedRef().hashCode(); | |||
} | |||
return super.hashCode() * STRING_MAGIC; | |||
} | |||
/** | |||
* Get an InputStream for the Resource. | |||
* @return an InputStream containing this Resource's content. | |||
* @throws IOException if unable to provide the content of this | |||
* Resource as a stream. | |||
* @throws UnsupportedOperationException if InputStreams are not | |||
* supported for this Resource type. | |||
*/ | |||
public synchronized InputStream getInputStream() throws IOException { | |||
if (isReference()) { | |||
return ((Resource) getCheckedRef()).getInputStream(); | |||
} | |||
//I can't get my head around this; is encoding treatment needed here? | |||
return | |||
//new oata.util.ReaderInputStream(new InputStreamReader( | |||
new ByteArrayInputStream(getContent().getBytes()) | |||
//, encoding), encoding) | |||
; | |||
} | |||
/** | |||
* Get an OutputStream for the Resource. | |||
* @return an OutputStream to which content can be written. | |||
* @throws IOException if unable to provide the content of this | |||
* Resource as a stream. | |||
* @throws UnsupportedOperationException if OutputStreams are not | |||
* supported for this Resource type. | |||
*/ | |||
public synchronized OutputStream getOutputStream() throws IOException { | |||
if (isReference()) { | |||
return ((Resource) getCheckedRef()).getOutputStream(); | |||
} | |||
if (getValue() != null) { | |||
throw new ImmutableResourceException(); | |||
} | |||
final ByteArrayOutputStream baos = new ByteArrayOutputStream(); | |||
return new FilterOutputStream(baos) { | |||
public void close() throws IOException { | |||
super.close(); | |||
StringResource.this.setValue(encoding == null | |||
? baos.toString() : baos.toString(encoding)); | |||
} | |||
}; | |||
} | |||
/** | |||
* Overrides the super version. | |||
* @param r the Reference to set. | |||
*/ | |||
public void setRefid(Reference r) { | |||
if (encoding != null) { | |||
throw tooManyAttributes(); | |||
} | |||
super.setRefid(r); | |||
} | |||
/** | |||
* Get the content of this StringResource. | |||
* @return a String; if the Project has been set properties | |||
* replacement will be attempted. | |||
*/ | |||
protected synchronized String getContent() { | |||
if (isReference()) { | |||
return ((StringResource) getCheckedRef()).getContent(); | |||
} | |||
String value = getValue(); | |||
if (value == null) { | |||
return value; | |||
} | |||
return getProject() == null | |||
? value : getProject().replaceProperties(value); | |||
} | |||
} |
@@ -0,0 +1,26 @@ | |||
/* | |||
* 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.types.resources; | |||
/** | |||
* Interface to be implemented by "touchable" resources; i.e. those | |||
* whose modification time can be altered. | |||
* @since Ant 1.7 | |||
*/ | |||
public interface Touchable { | |||
void touch(long modTime); | |||
} |
@@ -0,0 +1,373 @@ | |||
/* | |||
* 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.types.resources; | |||
import java.io.File; | |||
import java.io.IOException; | |||
import java.io.InputStream; | |||
import java.io.OutputStream; | |||
import java.net.URL; | |||
import java.net.URLConnection; | |||
import java.net.MalformedURLException; | |||
import org.apache.tools.ant.Project; | |||
import org.apache.tools.ant.AntClassLoader; | |||
import org.apache.tools.ant.BuildException; | |||
import org.apache.tools.ant.types.Path; | |||
import org.apache.tools.ant.types.Resource; | |||
import org.apache.tools.ant.types.Reference; | |||
import org.apache.tools.ant.util.FileUtils; | |||
/** | |||
* Exposes a URL as a Resource. | |||
* @since Ant 1.7 | |||
*/ | |||
public class URLResource extends Resource { | |||
private static final FileUtils FILE_UTILS = FileUtils.getFileUtils(); | |||
private static final int NULL_URL | |||
= Resource.getMagicNumber("null URL".getBytes()); | |||
private URL url; | |||
private String javaResource; | |||
private URLConnection conn; | |||
private Path classpath; | |||
/** | |||
* Default constructor. | |||
*/ | |||
public URLResource() { | |||
} | |||
/** | |||
* Convenience constructor. | |||
* @param u the URL to expose. | |||
*/ | |||
public URLResource(URL u) { | |||
setURL(u); | |||
} | |||
/** | |||
* Convenience constructor. | |||
* @param f the File to set as a URL. | |||
*/ | |||
public URLResource(File f) { | |||
setFile(f); | |||
} | |||
/** | |||
* String constructor for Ant attribute introspection. | |||
* @param u String representation of this URL. | |||
* @see org.apache.tools.ant.IntrospectionHelper | |||
*/ | |||
public URLResource(String u) { | |||
this(newURL(u)); | |||
} | |||
/** | |||
* Set the URL for this URLResource. | |||
* @param u the URL to expose. | |||
*/ | |||
public synchronized void setURL(URL u) { | |||
checkAttributesAllowed(); | |||
url = u; | |||
} | |||
/** | |||
* Set the URL from a File. | |||
* @param f the File to set as a URL. | |||
*/ | |||
public synchronized void setFile(File f) { | |||
try { | |||
setURL(FILE_UTILS.getFileURL(f)); | |||
} catch (MalformedURLException e) { | |||
throw new BuildException(e); | |||
} | |||
} | |||
/** | |||
* Set the resource name with which to expose a Java resource. | |||
* @param s the Java resource name. | |||
* @see java.lang.ClassLoader#getResource() | |||
*/ | |||
public synchronized void setJavaResource(String s) { | |||
checkAttributesAllowed(); | |||
javaResource = s; | |||
} | |||
/** | |||
* Set the classpath for this URLResource. | |||
* @param p the Path against which to resolve Java resources. | |||
*/ | |||
public synchronized void setClasspath(Path p) { | |||
checkAttributesAllowed(); | |||
addConfiguredClasspath(p); | |||
} | |||
/** | |||
* Create a nested classpath element. | |||
* @return a Path object. | |||
*/ | |||
public synchronized void addConfiguredClasspath(Path p) { | |||
checkChildrenAllowed(); | |||
if (classpath == null) { | |||
classpath = new Path(getProject()); | |||
} | |||
classpath.add(p); | |||
} | |||
/** | |||
* Get the URL used by this URLResource. | |||
* @return a URL object. | |||
*/ | |||
public synchronized URL getURL() { | |||
if (isReference()) { | |||
return ((URLResource) getCheckedRef()).getURL(); | |||
} | |||
if (url == null && javaResource != null) { | |||
ClassLoader cl = null; | |||
AntClassLoader acl = null; | |||
if (classpath != null) { | |||
acl = getProject().createClassLoader(classpath); | |||
cl = acl; | |||
} else { | |||
cl = getClass().getClassLoader(); | |||
if (cl == null) { | |||
cl = ClassLoader.getSystemClassLoader(); | |||
} | |||
} | |||
if (cl != null) { | |||
setURL(cl.getResource(javaResource)); | |||
if (acl != null) { | |||
acl.cleanup(); | |||
} | |||
} | |||
} | |||
return url; | |||
} | |||
/** | |||
* Overrides the super version. | |||
* @param r the Reference to set. | |||
*/ | |||
public synchronized void setRefid(Reference r) { | |||
//not using the accessor in this case to avoid side effects | |||
if (url != null || javaResource != null) { | |||
throw tooManyAttributes(); | |||
} | |||
super.setRefid(r); | |||
} | |||
/** | |||
* Get the name of this URLResource | |||
* (its file component minus the leading separator). | |||
* @return the name of this resource. | |||
*/ | |||
public synchronized String getName() { | |||
return isReference() ? ((Resource) getCheckedRef()).getName() | |||
: getURL().getFile().substring(1); | |||
} | |||
/** | |||
* Return this URLResource formatted as a String. | |||
* @return a String representation of this URLResource. | |||
*/ | |||
public synchronized String toString() { | |||
return isReference() | |||
? getCheckedRef().toString() : String.valueOf(getURL()); | |||
} | |||
/** | |||
* Find out whether the URL exists . | |||
* @return true if this resource exists. | |||
*/ | |||
public synchronized boolean isExists() { | |||
if (isReference()) { | |||
return ((Resource) getCheckedRef()).isExists(); | |||
} | |||
if (getURL() == null) { | |||
return false; | |||
} | |||
try { | |||
connect(); | |||
return true; | |||
} catch (IOException e) { | |||
return false; | |||
} | |||
} | |||
/** | |||
* Tells the modification time in milliseconds since 01.01.1970 . | |||
* | |||
* @return 0 if the resource does not exist to mirror the behavior | |||
* of {@link java.io.File File}. | |||
*/ | |||
public synchronized long getLastModified() { | |||
if (isReference()) { | |||
return ((Resource) getCheckedRef()).getLastModified(); | |||
} | |||
if (!isExists()) { | |||
return 0L; | |||
} | |||
try { | |||
connect(); | |||
return conn.getLastModified(); | |||
} catch (IOException e) { | |||
return 0L; | |||
} | |||
} | |||
/** | |||
* Tells if the resource is a directory. | |||
* @return boolean whether the resource is a directory. | |||
*/ | |||
public synchronized boolean isDirectory() { | |||
return isReference() | |||
? ((Resource) getCheckedRef()).isDirectory() | |||
: getName().endsWith("/"); | |||
} | |||
/** | |||
* Get the size of this Resource. | |||
* @return the size, as a long, 0 if the Resource does not exist (for | |||
* compatibility with java.io.File), or UNKNOWN_SIZE if not known. | |||
*/ | |||
public synchronized long getSize() { | |||
if (isReference()) { | |||
return ((Resource) getCheckedRef()).getSize(); | |||
} | |||
if (!isExists()) { | |||
return 0L; | |||
} | |||
try { | |||
connect(); | |||
return conn.getContentLength(); | |||
} catch (IOException e) { | |||
return UNKNOWN_SIZE; | |||
} | |||
} | |||
/** | |||
* Test whether an Object equals this URLResource. | |||
* @param another the other Object to compare. | |||
* @return true if the specified Object is equal to this Resource. | |||
*/ | |||
public synchronized boolean equals(Object another) { | |||
if (this == another) { | |||
return true; | |||
} | |||
if (isReference()) { | |||
return getCheckedRef().equals(another); | |||
} | |||
if (!(another.getClass().equals(getClass()))) { | |||
return false; | |||
} | |||
URLResource otheru = (URLResource) another; | |||
return getURL() == null | |||
? otheru.getURL() == null | |||
: getURL().equals(otheru.getURL()); | |||
} | |||
/** | |||
* Get the hash code for this Resource. | |||
* @return hash code as int. | |||
*/ | |||
public synchronized int hashCode() { | |||
if (isReference()) { | |||
return getCheckedRef().hashCode(); | |||
} | |||
return MAGIC * ((getURL() == null) ? NULL_URL : getURL().hashCode()); | |||
} | |||
/** | |||
* Get an InputStream for the Resource. | |||
* @return an InputStream containing this Resource's content. | |||
* @throws IOException if unable to provide the content of this | |||
* Resource as a stream. | |||
* @throws UnsupportedOperationException if InputStreams are not | |||
* supported for this Resource type. | |||
*/ | |||
public synchronized InputStream getInputStream() throws IOException { | |||
if (isReference()) { | |||
return ((Resource) getCheckedRef()).getInputStream(); | |||
} | |||
connect(); | |||
try { | |||
return conn.getInputStream(); | |||
} finally { | |||
conn = null; | |||
} | |||
} | |||
/** | |||
* Get an OutputStream for the Resource. | |||
* @return an OutputStream to which content can be written. | |||
* @throws IOException if unable to provide the content of this | |||
* Resource as a stream. | |||
* @throws UnsupportedOperationException if OutputStreams are not | |||
* supported for this Resource type. | |||
*/ | |||
public synchronized OutputStream getOutputStream() throws IOException { | |||
if (isReference()) { | |||
return ((Resource) getCheckedRef()).getOutputStream(); | |||
} | |||
connect(); | |||
try { | |||
return conn.getOutputStream(); | |||
} finally { | |||
conn = null; | |||
} | |||
} | |||
/** | |||
* Ensure that we have a connection. | |||
*/ | |||
protected synchronized void connect() throws IOException { | |||
URL u = getURL(); | |||
if (u == null) { | |||
throw new BuildException("URL not set"); | |||
} | |||
if (conn == null) { | |||
try { | |||
conn = u.openConnection(); | |||
conn.connect(); | |||
} catch (IOException e) { | |||
log(e.toString(), Project.MSG_ERR); | |||
conn = null; | |||
throw e; | |||
} | |||
} | |||
} | |||
/** | |||
* Finalize this URLResource. | |||
* @throws Throwable on error. | |||
*/ | |||
protected void finalize() throws Throwable { | |||
conn = null; | |||
super.finalize(); | |||
} | |||
private static URL newURL(String u) { | |||
try { | |||
return new URL(u); | |||
} catch (MalformedURLException e) { | |||
throw new BuildException(e); | |||
} | |||
} | |||
} |
@@ -0,0 +1,85 @@ | |||
/* | |||
* 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.types.resources; | |||
import java.util.List; | |||
import java.util.Iterator; | |||
import java.util.ArrayList; | |||
import java.util.Collection; | |||
import java.util.Collections; | |||
import org.apache.tools.ant.types.ResourceCollection; | |||
/** | |||
* ResourceCollection representing the union of multiple nested ResourceCollections. | |||
* @since Ant 1.7 | |||
*/ | |||
public class Union extends BaseResourceCollectionContainer { | |||
/** | |||
* Returns all Resources in String format. Moved up from | |||
* Path for convenience. | |||
* @return String array of Resources. | |||
*/ | |||
public String[] list() { | |||
if (isReference()) { | |||
return ((Union) getCheckedRef()).list(); | |||
} | |||
Collection result = getCollection(true); | |||
return (String[]) (result.toArray(new String[result.size()])); | |||
} | |||
/** | |||
* Unify the contained Resources. | |||
* @return a Collection of Resources. | |||
*/ | |||
protected Collection getCollection() { | |||
return getCollection(false); | |||
} | |||
/** | |||
* Unify the contained Resources. | |||
* @param asString indicates whether the resulting Collection | |||
* should contain Strings instead of Resources. | |||
* @return a Collection of Resources. | |||
*/ | |||
protected Collection getCollection(boolean asString) { | |||
List rc = getResourceCollections(); | |||
if (rc.isEmpty()) { | |||
return Collections.EMPTY_LIST; | |||
} | |||
//preserve order-encountered using a list; enforce set logic manually: | |||
ArrayList union = new ArrayList(rc.size() * 2); | |||
for (Iterator rcIter = rc.iterator(); rcIter.hasNext();) { | |||
for (Iterator r = nextRC(rcIter).iterator(); r.hasNext();) { | |||
Object o = r.next(); | |||
if (asString) { | |||
o = o.toString(); | |||
} | |||
if (!(union.contains(o))) { | |||
union.add(o); | |||
} | |||
} | |||
} | |||
return union; | |||
} | |||
private static ResourceCollection nextRC(Iterator i) { | |||
return (ResourceCollection) i.next(); | |||
} | |||
} | |||
@@ -0,0 +1,299 @@ | |||
/* | |||
* 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.types.resources; | |||
import java.io.File; | |||
import java.io.InputStream; | |||
import java.io.OutputStream; | |||
import java.io.IOException; | |||
import java.io.FilterInputStream; | |||
import org.apache.tools.ant.Project; | |||
import org.apache.tools.ant.BuildException; | |||
import org.apache.tools.ant.types.Resource; | |||
import org.apache.tools.ant.types.Reference; | |||
import org.apache.tools.ant.util.FileUtils; | |||
import org.apache.tools.zip.ZipFile; | |||
import org.apache.tools.zip.ZipEntry; | |||
/** | |||
* A Resource representation of an entry in a zipfile. | |||
* @since Ant 1.7 | |||
*/ | |||
public class ZipResource extends Resource { | |||
private static final int NULL_ZIPFILE | |||
= Resource.getMagicNumber("null zipfile".getBytes()); | |||
private String encoding; | |||
private File zipfile; | |||
private boolean haveEntry = false; | |||
/** | |||
* Default constructor. | |||
*/ | |||
public ZipResource() { | |||
} | |||
/** | |||
* Construct a ZipResource representing the specified | |||
* entry in the specified zipfile. | |||
* @param z the zipfile as File. | |||
* @param enc the encoding used for filenames. | |||
* @param e the ZipEntry. | |||
*/ | |||
public ZipResource(File z, String enc, ZipEntry e) { | |||
setEntry(e); | |||
setZipfile(z); | |||
setEncoding(enc); | |||
} | |||
/** | |||
* Set the zipfile that holds this ZipResource. | |||
* @param z the zipfile as a File. | |||
*/ | |||
public void setZipfile(File z) { | |||
checkAttributesAllowed(); | |||
zipfile = z; | |||
} | |||
/** | |||
* Get the zipfile that holds this ZipResource. | |||
* @return the zipfile as a File. | |||
*/ | |||
public File getZipfile() { | |||
return isReference() | |||
? ((ZipResource) getCheckedRef()).getZipfile() : zipfile; | |||
} | |||
/** | |||
* Set the encoding to use with the zipfile. | |||
* @param enc the String encoding. | |||
*/ | |||
public void setEncoding(String enc) { | |||
checkAttributesAllowed(); | |||
encoding = enc; | |||
} | |||
/** | |||
* Get the encoding to use with the zipfile. | |||
* @return String encoding. | |||
*/ | |||
public String getEncoding() { | |||
return isReference() | |||
? ((ZipResource) getCheckedRef()).getEncoding() : encoding; | |||
} | |||
/** | |||
* Get the last modified date of this ZipResource. | |||
* @return the last modification date. | |||
*/ | |||
public long getLastModified() { | |||
if (isReference()) { | |||
return ((Resource) getCheckedRef()).getLastModified(); | |||
} | |||
checkEntry(); | |||
return super.getLastModified(); | |||
} | |||
/** | |||
* Get the size of this ZipResource. | |||
* @return the long size of this ZipResource. | |||
*/ | |||
public long getSize() { | |||
if (isReference()) { | |||
return ((Resource) getCheckedRef()).getSize(); | |||
} | |||
checkEntry(); | |||
return super.getSize(); | |||
} | |||
/** | |||
* Learn whether this ZipResource represents a directory. | |||
* @return boolean flag indicating whether the zip entry is a directory. | |||
*/ | |||
public boolean isDirectory() { | |||
if (isReference()) { | |||
return ((Resource) getCheckedRef()).isDirectory(); | |||
} | |||
checkEntry(); | |||
return super.isDirectory(); | |||
} | |||
/** | |||
* Find out whether this ZipResource represents an existing Resource. | |||
* @return boolean existence flag. | |||
*/ | |||
public boolean isExists() { | |||
if (isReference()) { | |||
return ((Resource) getCheckedRef()).isExists(); | |||
} | |||
checkEntry(); | |||
return super.isExists(); | |||
} | |||
/** | |||
* Overrides the super version. | |||
* @param r the Reference to set. | |||
*/ | |||
public void setRefid(Reference r) { | |||
if (encoding != null || zipfile != null) { | |||
throw tooManyAttributes(); | |||
} | |||
super.setRefid(r); | |||
} | |||
/** | |||
* Return an InputStream for reading the contents of this Resource. | |||
* @return an InputStream object. | |||
* @throws IOException if the zip file cannot be opened, | |||
* or the entry cannot be read. | |||
*/ | |||
public InputStream getInputStream() throws IOException { | |||
if (isReference()) { | |||
return ((Resource) getCheckedRef()).getInputStream(); | |||
} | |||
final ZipFile z = new ZipFile(getZipfile(), getEncoding()); | |||
return new FilterInputStream(z.getInputStream(z.getEntry(getName()))) { | |||
public void close() throws IOException { | |||
FileUtils.close(in); | |||
z.close(); | |||
} | |||
protected void finalize() throws Throwable { | |||
try { | |||
close(); | |||
} finally { | |||
super.finalize(); | |||
} | |||
} | |||
}; | |||
} | |||
/** | |||
* Get an OutputStream for the Resource. | |||
* @return an OutputStream to which content can be written. | |||
* @throws IOException if unable to provide the content of this | |||
* Resource as a stream. | |||
* @throws UnsupportedOperationException if OutputStreams are not | |||
* supported for this Resource type. | |||
*/ | |||
public OutputStream getOutputStream() throws IOException { | |||
if (isReference()) { | |||
return ((Resource) getCheckedRef()).getOutputStream(); | |||
} | |||
throw new UnsupportedOperationException( | |||
"Use the zip task for zip output."); | |||
} | |||
/** | |||
* Compare this ZipResource to another Resource. | |||
* @param another the other Resource against which to compare. | |||
* @return a negative integer, zero, or a positive integer as this ZipResource | |||
* is less than, equal to, or greater than the specified Resource. | |||
*/ | |||
public int compareTo(Object another) { | |||
return this.equals(another) ? 0 : super.compareTo(another); | |||
} | |||
/** | |||
* Compare another Object to this ZipResource for equality. | |||
* @param another the other Object to compare. | |||
* @return true if another is a ZipResource representing | |||
* the same entry in the same zipfile. | |||
*/ | |||
public boolean equals(Object another) { | |||
if (this == another) { | |||
return true; | |||
} | |||
if (isReference()) { | |||
return getCheckedRef().equals(another); | |||
} | |||
if (!(another.getClass().equals(getClass()))) { | |||
return false; | |||
} | |||
ZipResource r = (ZipResource) another; | |||
return getZipfile().equals(r.getZipfile()) | |||
&& getName().equals(r.getName()); | |||
} | |||
/** | |||
* Get the hash code for this Resource. | |||
* @return hash code as int. | |||
*/ | |||
public int hashCode() { | |||
return super.hashCode() | |||
* (getZipfile() == null ? NULL_ZIPFILE : getZipfile().hashCode()); | |||
} | |||
/** | |||
* Format this ZipResource as a String. | |||
* @return String representatation of this ZipResource. | |||
*/ | |||
public String toString() { | |||
return isReference() ? getCheckedRef().toString() | |||
: getZipfile().toString() + ':' + getName(); | |||
} | |||
private synchronized void checkEntry() throws BuildException { | |||
if (haveEntry) { | |||
return; | |||
} | |||
String name = getName(); | |||
if (name == null) { | |||
throw new BuildException("zip entry name not set"); | |||
} | |||
File f = getZipfile(); | |||
if (f == null) { | |||
throw new BuildException("zipfile attribute not set"); | |||
} | |||
if (!f.exists()) { | |||
throw new BuildException(f.getAbsolutePath() + " does not exist."); | |||
} | |||
if (f.isDirectory()) { | |||
throw new BuildException(f + " denotes a directory."); | |||
} | |||
ZipFile z = null; | |||
try { | |||
z = new ZipFile(f, getEncoding()); | |||
setEntry(z.getEntry(name)); | |||
} catch (IOException e) { | |||
log(e.getMessage(), Project.MSG_DEBUG); | |||
throw new BuildException(e); | |||
} finally { | |||
if (z != null) { | |||
try { | |||
z.close(); | |||
} catch (IOException e) { | |||
//? | |||
} | |||
} | |||
} | |||
} | |||
private synchronized void setEntry(ZipEntry e) { | |||
haveEntry = true; | |||
if (e == null) { | |||
super.setExists(false); | |||
return; | |||
} | |||
super.setName(e.getName()); | |||
super.setExists(true); | |||
super.setLastModified(e.getTime()); | |||
super.setDirectory(e.isDirectory()); | |||
super.setSize(e.getSize()); | |||
} | |||
} |
@@ -0,0 +1,69 @@ | |||
/* | |||
* 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.types.resources.comparators; | |||
import java.io.IOException; | |||
import org.apache.tools.ant.BuildException; | |||
import org.apache.tools.ant.types.Resource; | |||
import org.apache.tools.ant.util.FileUtils; | |||
/** | |||
* Compares Resources by content. | |||
* @since Ant 1.7 | |||
*/ | |||
public class Content extends ResourceComparator { | |||
private boolean binary = true; | |||
/** | |||
* Set binary mode for this Content ResourceComparator. If this | |||
* attribute is set to false, Resource content will be compared | |||
* ignoring platform line-ending conventions. | |||
* Default is <code>true</code>. | |||
* @param b whether to compare content in binary mode. | |||
*/ | |||
public void setBinary(boolean b) { | |||
binary = b; | |||
} | |||
/** | |||
* Learn whether this Content ResourceComparator is operating in binary mode. | |||
* @return boolean binary flag. | |||
*/ | |||
public boolean isBinary() { | |||
return binary; | |||
} | |||
/** | |||
* Compare two Resources by content. | |||
* @param foo the first Resource. | |||
* @param bar the second Resource. | |||
* @return a negative integer, zero, or a positive integer as the first | |||
* argument is less than, equal to, or greater than the second. | |||
* @throws BuildException if I/O errors occur. | |||
* @see org.apache.tools.ant.util.FileUtils#compareContent(Resource, Resource, boolean). | |||
*/ | |||
protected int resourceCompare(Resource foo, Resource bar) { | |||
try { | |||
return FileUtils.getFileUtils().compareContent(foo, bar, !binary); | |||
} catch (IOException e) { | |||
throw new BuildException(e); | |||
} | |||
} | |||
} |
@@ -0,0 +1,37 @@ | |||
/* | |||
* 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.types.resources.comparators; | |||
import org.apache.tools.ant.types.Resource; | |||
/** | |||
* Compares Resources by last modification date. | |||
* @since Ant 1.7 | |||
*/ | |||
public class Date extends ResourceComparator { | |||
/** | |||
* Compare two Resources. | |||
* @param foo the first Resource. | |||
* @param bar the second Resource. | |||
* @return a negative integer, zero, or a positive integer as the first | |||
* argument is less than, equal to, or greater than the second. | |||
*/ | |||
protected int resourceCompare(Resource foo, Resource bar) { | |||
return (int) (foo.getLastModified() - bar.getLastModified()); | |||
} | |||
} |
@@ -0,0 +1,42 @@ | |||
/* | |||
* 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.types.resources.comparators; | |||
import org.apache.tools.ant.types.Resource; | |||
/** | |||
* Compares Resources by existence. Not existing is "less than" existing. | |||
* @since Ant 1.7 | |||
*/ | |||
public class Exists extends ResourceComparator { | |||
/** | |||
* Compare two Resources. | |||
* @param foo the first Resource. | |||
* @param bar the second Resource. | |||
* @return a negative integer, zero, or a positive integer as the first | |||
* argument is less than, equal to, or greater than the second. | |||
*/ | |||
protected int resourceCompare(Resource foo, Resource bar) { | |||
boolean f = foo.isExists(); | |||
if (f == bar.isExists()) { | |||
return 0; | |||
} | |||
return f ? 1 : -1; | |||
} | |||
} |
@@ -0,0 +1,37 @@ | |||
/* | |||
* 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.types.resources.comparators; | |||
import org.apache.tools.ant.types.Resource; | |||
/** | |||
* Compares Resources by name. | |||
* @since Ant 1.7 | |||
*/ | |||
public class Name extends ResourceComparator { | |||
/** | |||
* Compare two Resources. | |||
* @param foo the first Resource. | |||
* @param bar the second Resource. | |||
* @return a negative integer, zero, or a positive integer as the first | |||
* argument is less than, equal to, or greater than the second. | |||
*/ | |||
protected int resourceCompare(Resource foo, Resource bar) { | |||
return foo.getName().compareTo(bar.getName()); | |||
} | |||
} |
@@ -0,0 +1,62 @@ | |||
/* | |||
* 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.types.resources.comparators; | |||
import java.util.Comparator; | |||
import org.apache.tools.ant.types.Resource; | |||
/** | |||
* Abstract Resource Comparator. | |||
* @since Ant 1.7 | |||
*/ | |||
public abstract class ResourceComparator implements Comparator { | |||
/** | |||
* Compare two objects. | |||
* @param foo the first Object. | |||
* @param bar the second Object. | |||
* @return a negative integer, zero, or a positive integer as the first | |||
* argument is less than, equal to, or greater than the second. | |||
* @throws ClassCastException if either argument is null. | |||
*/ | |||
public final int compare(Object foo, Object bar) { | |||
return resourceCompare((Resource) foo, (Resource) bar); | |||
} | |||
/** | |||
* Test for equality with this ResourceComparator. | |||
* @param o the Object to compare against. | |||
* @return true if the specified Object equals this one. | |||
*/ | |||
public final boolean equals(Object o) { | |||
if (o == null) { | |||
return false; | |||
} | |||
return o == this || o.getClass().equals(getClass()); | |||
} | |||
/** | |||
* Compare two Resources. | |||
* @param foo the first Resource. | |||
* @param bar the second Resource. | |||
* @return a negative integer, zero, or a positive integer as the first | |||
* argument is less than, equal to, or greater than the second. | |||
*/ | |||
protected abstract int resourceCompare(Resource foo, Resource bar); | |||
} |
@@ -0,0 +1,56 @@ | |||
/* | |||
* 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.types.resources.comparators; | |||
import org.apache.tools.ant.BuildException; | |||
import org.apache.tools.ant.types.Resource; | |||
/** | |||
* Reverses another ResourceComparator. If no nested ResourceComparator | |||
* is supplied, the compared Resources' natural order will be reversed. | |||
* @since Ant 1.7 | |||
*/ | |||
public class Reverse extends ResourceComparator { | |||
private static final String ONE_NESTED | |||
= "You must not nest more than one ResourceComparator for reversal."; | |||
private ResourceComparator nested; | |||
/** | |||
* Add the ResourceComparator to reverse. | |||
* @param nested the ResourceComparator to add. | |||
*/ | |||
public void add(ResourceComparator c) { | |||
if (nested != null) { | |||
throw new BuildException(ONE_NESTED); | |||
} | |||
nested = c; | |||
} | |||
/** | |||
* Compare two Resources. | |||
* @param foo the first Resource. | |||
* @param bar the second Resource. | |||
* @return a negative integer, zero, or a positive integer as the first | |||
* argument is greater than, equal to, or less than the second. | |||
*/ | |||
protected int resourceCompare(Resource foo, Resource bar) { | |||
return -1 * (nested == null | |||
? foo.compareTo(bar) : nested.compare(foo, bar)); | |||
} | |||
} |
@@ -0,0 +1,37 @@ | |||
/* | |||
* 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.types.resources.comparators; | |||
import org.apache.tools.ant.types.Resource; | |||
/** | |||
* Compares Resources by size. | |||
* @since Ant 1.7 | |||
*/ | |||
public class Size extends ResourceComparator { | |||
/** | |||
* Compare two Resources. | |||
* @param foo the first Resource. | |||
* @param bar the second Resource. | |||
* @return a negative integer, zero, or a positive integer as the first | |||
* argument is less than, equal to, or greater than the second. | |||
*/ | |||
protected int resourceCompare(Resource foo, Resource bar) { | |||
return (int) (foo.getSize() - bar.getSize()); | |||
} | |||
} |
@@ -0,0 +1,43 @@ | |||
/* | |||
* 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.types.resources.comparators; | |||
import org.apache.tools.ant.types.Resource; | |||
/** | |||
* Compares Resources by is-directory status. As a container | |||
* of files, a directory is deemed "greater" than a file. | |||
* @since Ant 1.7 | |||
*/ | |||
public class Type extends ResourceComparator { | |||
/** | |||
* Compare two Resources. | |||
* @param foo the first Resource. | |||
* @param bar the second Resource. | |||
* @return a negative integer, zero, or a positive integer as the first | |||
* argument is less than, equal to, or greater than the second. | |||
*/ | |||
protected int resourceCompare(Resource foo, Resource bar) { | |||
boolean f = foo.isDirectory(); | |||
if (f == bar.isDirectory()) { | |||
return 0; | |||
} | |||
return f ? 1 : -1; | |||
} | |||
} |
@@ -0,0 +1,43 @@ | |||
/* | |||
* 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.types.resources.selectors; | |||
import java.util.Iterator; | |||
import org.apache.tools.ant.types.Resource; | |||
/** | |||
* And ResourceSelector. | |||
* @since Ant 1.7 | |||
*/ | |||
public class And extends ResourceSelectorContainer implements ResourceSelector { | |||
/** | |||
* Return true if this Resource is selected. | |||
* @param r the Resource to check. | |||
* @return whether the Resource was selected. | |||
*/ | |||
public boolean isSelected(Resource r) { | |||
for (Iterator i = getSelectors(); i.hasNext();) { | |||
if (!((ResourceSelector) i.next()).isSelected(r)) { | |||
return false; | |||
} | |||
} | |||
return true; | |||
} | |||
} |
@@ -0,0 +1,161 @@ | |||
/* | |||
* 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.types.resources.selectors; | |||
import java.text.DateFormat; | |||
import java.text.SimpleDateFormat; | |||
import java.text.ParseException; | |||
import java.util.Locale; | |||
import org.apache.tools.ant.BuildException; | |||
import org.apache.tools.ant.types.Resource; | |||
import org.apache.tools.ant.types.TimeComparison; | |||
import org.apache.tools.ant.util.FileUtils; | |||
/** | |||
* Date ResourceSelector. Based on the date FileSelector, with the most | |||
* notable difference being the lack of support for the includedirs attribute. | |||
* It is recommended that the effect of includeDirs = "false" be achieved for | |||
* resources by enclosing a "dir" Type ResourceSelector and a Date | |||
* ResourceSelector in an Or ResourceSelector. | |||
* @since Ant 1.7 | |||
*/ | |||
public class Date implements ResourceSelector { | |||
private static final String MILLIS_OR_DATETIME | |||
= "Either the millis or the datetime attribute must be set."; | |||
private static final FileUtils FILE_UTILS = FileUtils.getFileUtils(); | |||
private Long millis = null; | |||
private String dateTime = null; | |||
private String pattern = null; | |||
private TimeComparison when = TimeComparison.EQUAL; | |||
private long granularity = FILE_UTILS.getFileTimestampGranularity(); | |||
/** | |||
* Set the date/time in milliseconds since 1970. | |||
* @param m the number of millis. | |||
*/ | |||
public synchronized void setMillis(long m) { | |||
millis = new Long(m); | |||
} | |||
/** | |||
* Get the date/time in ms. | |||
* @return long number of millis since 1970. | |||
*/ | |||
public synchronized long getMillis() { | |||
return millis == null ? -1L : millis.longValue(); | |||
} | |||
/** | |||
* Set the date and time as a String. | |||
* @param s the date & time to use. | |||
*/ | |||
public synchronized void setDateTime(String s) { | |||
dateTime = s; | |||
millis = null; | |||
} | |||
/** | |||
* Get the date & time in String format. | |||
* @return a String representing a date & time. | |||
*/ | |||
public synchronized String getDatetime() { | |||
return dateTime; | |||
} | |||
/** | |||
* Set the granularity to use for this ResourceSelector. | |||
* @param g the timestamp granularity. | |||
*/ | |||
public synchronized void setGranularity(long g) { | |||
granularity = g; | |||
} | |||
/** | |||
* Get the timestamp granularity used by this ResourceSelector. | |||
* @return the long granularity. | |||
*/ | |||
public synchronized long getGranularity() { | |||
return granularity; | |||
} | |||
/** | |||
* Set the optional pattern to use with the datetime attribute. | |||
* @param p the SimpleDateFormat-compatible pattern string. | |||
*/ | |||
public synchronized void setPattern(String p) { | |||
pattern = p; | |||
} | |||
/** | |||
* Get the pattern for use with the datetime attribute. | |||
* @return a SimpleDateFormat-compatible pattern string. | |||
*/ | |||
public synchronized String getPattern() { | |||
return pattern; | |||
} | |||
/** | |||
* Set the comparison mode. | |||
* @param c a TimeComparison object. | |||
*/ | |||
public synchronized void setWhen(TimeComparison c) { | |||
when = c; | |||
} | |||
/** | |||
* Get the comparison mode. | |||
* @return a TimeComparison object. | |||
*/ | |||
public synchronized TimeComparison getWhen() { | |||
return when; | |||
} | |||
/** | |||
* Return true if this Resource is selected. | |||
* @param r the Resource to check. | |||
* @return whether the Resource was selected. | |||
*/ | |||
public synchronized boolean isSelected(Resource r) { | |||
if (dateTime == null && millis == null) { | |||
throw new BuildException(MILLIS_OR_DATETIME); | |||
} | |||
if (millis == null) { | |||
DateFormat df = ((pattern == null) | |||
? DateFormat.getDateTimeInstance( | |||
DateFormat.SHORT, DateFormat.SHORT, Locale.US) | |||
: new SimpleDateFormat(pattern)); | |||
try { | |||
long m = df.parse(dateTime).getTime(); | |||
if (m < 0) { | |||
throw new BuildException("Date of " + dateTime | |||
+ " results in negative milliseconds value" | |||
+ " relative to epoch (January 1, 1970, 00:00:00 GMT)."); | |||
} | |||
setMillis(m); | |||
} catch (ParseException pe) { | |||
throw new BuildException("Date of " + dateTime | |||
+ " Cannot be parsed correctly. It should be in" | |||
+ (pattern == null | |||
? " MM/DD/YYYY HH:MM AM_PM" : pattern) + " format."); | |||
} | |||
} | |||
return when.evaluate(r.getLastModified(), millis.longValue(), granularity); | |||
} | |||
} |
@@ -0,0 +1,36 @@ | |||
/* | |||
* 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.types.resources.selectors; | |||
import org.apache.tools.ant.types.Resource; | |||
/** | |||
* Exists ResourceSelector. | |||
* @since Ant 1.7 | |||
*/ | |||
public class Exists implements ResourceSelector { | |||
/** | |||
* Return true if this Resource is selected. | |||
* @param r the Resource to check. | |||
* @return whether the Resource was selected. | |||
*/ | |||
public boolean isSelected(Resource r) { | |||
return r.isExists(); | |||
} | |||
} |
@@ -0,0 +1,129 @@ | |||
/* | |||
* 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.types.resources.selectors; | |||
import org.apache.tools.ant.Project; | |||
import org.apache.tools.ant.ProjectHelper; | |||
import org.apache.tools.ant.BuildException; | |||
import org.apache.tools.ant.ComponentHelper; | |||
import org.apache.tools.ant.AntTypeDefinition; | |||
import org.apache.tools.ant.types.Resource; | |||
/** | |||
* InstanceOf ResourceSelector. | |||
* @since Ant 1.7 | |||
*/ | |||
public class InstanceOf implements ResourceSelector { | |||
private static final String ONE_ONLY = "Exactly one of class|type must be set."; | |||
private Project project; | |||
private Class clazz; | |||
private String type; | |||
private String uri; | |||
/** | |||
* Set the Project instance for this InstanceOf selector. | |||
* @param p the Project instance used for type comparisons. | |||
*/ | |||
public void setProject(Project p) { | |||
project = p; | |||
} | |||
/** | |||
* Set the class to compare against. | |||
* @param c the class. | |||
*/ | |||
public void setClass(Class c) { | |||
if (clazz != null) { | |||
throw new BuildException("The class attribute has already been set."); | |||
} | |||
clazz = c; | |||
} | |||
/** | |||
* Set the Ant type to compare against. | |||
* @param s the type name. | |||
*/ | |||
public void setType(String s) { | |||
type = s; | |||
} | |||
/** | |||
* Set the URI in which the Ant type, if specified, should be defined. | |||
* @param u the URI. | |||
*/ | |||
public void setURI(String u) { | |||
uri = u; | |||
} | |||
/** | |||
* Get the comparison class. | |||
* @return the Class object. | |||
*/ | |||
public Class getCheckClass() { | |||
return clazz; | |||
} | |||
/** | |||
* Get the comparison type. | |||
* @return the String typename. | |||
*/ | |||
public String getType() { | |||
return type; | |||
} | |||
/** | |||
* Get the type's URI. | |||
* @return the String URI. | |||
*/ | |||
public String getURI() { | |||
return uri; | |||
} | |||
/** | |||
* Return true if this Resource is selected. | |||
* @param r the Resource to check. | |||
* @return whether the Resource was selected. | |||
* @throws BuildException if an error occurs. | |||
*/ | |||
public boolean isSelected(Resource r) { | |||
if ((clazz == null) == (type == null)) { | |||
throw new BuildException(ONE_ONLY); | |||
} | |||
Class c = clazz; | |||
if (type != null) { | |||
if (project == null) { | |||
throw new BuildException( | |||
"No project set for InstanceOf ResourceSelector; " | |||
+ "the type attribute is invalid."); | |||
} | |||
AntTypeDefinition d = ComponentHelper.getComponentHelper( | |||
project).getDefinition(ProjectHelper.genComponentName(uri, type)); | |||
if (d == null) { | |||
throw new BuildException("type " + type + " not found."); | |||
} | |||
try { | |||
c = d.innerGetTypeClass(); | |||
} catch (ClassNotFoundException e) { | |||
throw new BuildException(e); | |||
} | |||
} | |||
return c.isAssignableFrom(r.getClass()); | |||
} | |||
} |
@@ -0,0 +1,69 @@ | |||
/* | |||
* 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.types.resources.selectors; | |||
import java.util.Iterator; | |||
import org.apache.tools.ant.types.Resource; | |||
/** | |||
* Majority ResourceSelector. | |||
* @since Ant 1.7 | |||
*/ | |||
public class Majority | |||
extends ResourceSelectorContainer implements ResourceSelector { | |||
private boolean tie = true; | |||
/** | |||
* Set whether ties are allowed. | |||
* @param b whether a tie is a pass. | |||
*/ | |||
public synchronized void setAllowtie(boolean b) { | |||
tie = b; | |||
} | |||
/** | |||
* Return true if this Resource is selected. | |||
* @param r the Resource to check. | |||
* @return whether the Resource was selected. | |||
*/ | |||
public synchronized boolean isSelected(Resource r) { | |||
int passed = 0; | |||
int failed = 0; | |||
int count = selectorCount(); | |||
boolean even = count % 2 == 0; | |||
int threshold = count / 2; | |||
for (Iterator i = getSelectors(); i.hasNext();) { | |||
if (((ResourceSelector) i.next()).isSelected(r)) { | |||
++passed; | |||
if (passed > threshold || (even && tie && passed == threshold)) { | |||
return true; | |||
} | |||
} else { | |||
++failed; | |||
if (failed > threshold || (even && !tie && failed == threshold)) { | |||
return false; | |||
} | |||
} | |||
} | |||
//dummy | |||
return false; | |||
} | |||
} |
@@ -0,0 +1,76 @@ | |||
/* | |||
* 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.types.resources.selectors; | |||
import org.apache.tools.ant.types.Resource; | |||
import org.apache.tools.ant.types.selectors.SelectorUtils; | |||
/** | |||
* Name ResourceSelector. | |||
* @since Ant 1.7 | |||
*/ | |||
public class Name implements ResourceSelector { | |||
private String pattern; | |||
private boolean cs = true; | |||
/** | |||
* Set the pattern to compare names against. | |||
* @param n the pattern String to set. | |||
*/ | |||
public void setName(String n) { | |||
pattern = n; | |||
} | |||
/** | |||
* Get the pattern used by this Name ResourceSelector. | |||
* @return the String selection pattern. | |||
*/ | |||
public String getName() { | |||
return pattern; | |||
} | |||
/** | |||
* Set whether the name comparisons are case-sensitive. | |||
* @param b boolean case-sensitivity flag. | |||
*/ | |||
public void setCaseSensitive(boolean b) { | |||
cs = b; | |||
} | |||
/** | |||
* Learn whether this Name ResourceSelector is case-sensitive. | |||
* @return boolean case-sensitivity flag. | |||
*/ | |||
public boolean isCaseSensitive() { | |||
return cs; | |||
} | |||
/** | |||
* Return true if this Resource is selected. | |||
* @param r the Resource to check. | |||
* @return whether the Resource was selected. | |||
*/ | |||
public boolean isSelected(Resource r) { | |||
String n = r.getName(); | |||
if (SelectorUtils.match(pattern, n, cs)) { | |||
return true; | |||
} | |||
String s = r.toString(); | |||
return s.equals(n) ? false : SelectorUtils.match(pattern, s, cs); | |||
} | |||
} |
@@ -0,0 +1,43 @@ | |||
/* | |||
* 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.types.resources.selectors; | |||
import java.util.Iterator; | |||
import org.apache.tools.ant.types.Resource; | |||
/** | |||
* None ResourceSelector. | |||
* @since Ant 1.7 | |||
*/ | |||
public class None | |||
extends ResourceSelectorContainer implements ResourceSelector { | |||
/** | |||
* Return true if this Resource is selected. | |||
* @param r the Resource to check. | |||
* @return whether the Resource was selected. | |||
*/ | |||
public boolean isSelected(Resource r) { | |||
boolean none = true; | |||
for (Iterator i = getSelectors(); none && i.hasNext();) { | |||
none = !((ResourceSelector) i.next()).isSelected(r); | |||
} | |||
return none; | |||
} | |||
} |
@@ -0,0 +1,65 @@ | |||
/* | |||
* 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.types.resources.selectors; | |||
import org.apache.tools.ant.types.Resource; | |||
/** | |||
* Not ResourceSelector. | |||
* @since Ant 1.7 | |||
*/ | |||
public class Not implements ResourceSelector { | |||
private ResourceSelector sel; | |||
/** | |||
* Default constructor. | |||
*/ | |||
public Not() { | |||
} | |||
/** | |||
* Convenience constructor. | |||
* @param s the ResourceSelector to negate. | |||
*/ | |||
public Not(ResourceSelector s) { | |||
add(s); | |||
} | |||
/** | |||
* Set the ResourceSelector. | |||
* @param s the ResourceSelector to negate. | |||
* @throws IllegalStateException if already set. | |||
*/ | |||
public void add(ResourceSelector s) { | |||
if (sel != null) { | |||
throw new IllegalStateException( | |||
"The Not ResourceSelector accepts a single nested ResourceSelector"); | |||
} | |||
sel = s; | |||
} | |||
/** | |||
* Return true if this Resource is selected. | |||
* @param r the Resource to check. | |||
* @return whether the Resource was selected. | |||
*/ | |||
public boolean isSelected(Resource r) { | |||
return !(sel.isSelected(r)); | |||
} | |||
} |
@@ -0,0 +1,43 @@ | |||
/* | |||
* 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.types.resources.selectors; | |||
import java.util.Iterator; | |||
import org.apache.tools.ant.types.Resource; | |||
/** | |||
* Or ResourceSelector. | |||
* @since Ant 1.7 | |||
*/ | |||
public class Or extends ResourceSelectorContainer implements ResourceSelector { | |||
/** | |||
* Return true if this Resource is selected. | |||
* @param r the Resource to check. | |||
* @return whether the Resource was selected. | |||
*/ | |||
public boolean isSelected(Resource r) { | |||
for (Iterator i = getSelectors(); i.hasNext();) { | |||
if (((ResourceSelector) i.next()).isSelected(r)) { | |||
return true; | |||
} | |||
} | |||
return false; | |||
} | |||
} |
@@ -0,0 +1,34 @@ | |||
/* | |||
* 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.types.resources.selectors; | |||
import org.apache.tools.ant.types.Resource; | |||
/** | |||
* Interface for a Resource selector. | |||
* @since Ant 1.7 | |||
*/ | |||
public interface ResourceSelector { | |||
/** | |||
* Return true if this Resource is selected. | |||
* @param r the Resource to check. | |||
* @return whether the Resource was selected. | |||
*/ | |||
public boolean isSelected(Resource r); | |||
} |
@@ -0,0 +1,111 @@ | |||
/* | |||
* 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.types.resources.selectors; | |||
import java.util.Stack; | |||
import java.util.Vector; | |||
import java.util.Iterator; | |||
import java.util.Collections; | |||
import org.apache.tools.ant.Project; | |||
import org.apache.tools.ant.BuildException; | |||
import org.apache.tools.ant.types.DataType; | |||
/** | |||
* ResourceSelector container. | |||
* @since Ant 1.7 | |||
*/ | |||
public class ResourceSelectorContainer extends DataType { | |||
private Vector v = new Vector(); | |||
/** | |||
* Add a ResourceSelector to the container. | |||
* @param s the ResourceSelector to add. | |||
*/ | |||
public void add(ResourceSelector s) { | |||
if (isReference()) { | |||
throw noChildrenAllowed(); | |||
} | |||
if (s == null) { | |||
return; | |||
} | |||
v.add(s); | |||
setChecked(false); | |||
} | |||
/** | |||
* Learn whether this ResourceSelectorContainer has selectors. | |||
* @return boolean indicating whether selectors have been added to the container. | |||
*/ | |||
public boolean hasSelectors() { | |||
if (isReference()) { | |||
return ((ResourceSelectorContainer) getCheckedRef()).hasSelectors(); | |||
} | |||
dieOnCircularReference(); | |||
return !v.isEmpty(); | |||
} | |||
/** | |||
* Get the count of nested selectors. | |||
* @return the selector count as int. | |||
*/ | |||
public int selectorCount() { | |||
if (isReference()) { | |||
return ((ResourceSelectorContainer) getCheckedRef()).selectorCount(); | |||
} | |||
dieOnCircularReference(); | |||
return v.size(); | |||
} | |||
/** | |||
* Return an Iterator over the nested selectors. | |||
* @return Iterator of ResourceSelectors. | |||
*/ | |||
public Iterator getSelectors() { | |||
if (isReference()) { | |||
return ((ResourceSelectorContainer) getCheckedRef()).getSelectors(); | |||
} | |||
dieOnCircularReference(); | |||
return Collections.unmodifiableList(v).iterator(); | |||
} | |||
/** | |||
* Overrides the version from DataType to recurse on nested ResourceSelectors. | |||
* @param stk the Stack of references. | |||
* @param p the Project to resolve against. | |||
* @throws BuildException on error. | |||
*/ | |||
public void dieOnCircularReference(Stack stk, Project p) { | |||
if (isChecked()) { | |||
return; | |||
} | |||
if (isReference()) { | |||
super.dieOnCircularReference(stk, p); | |||
} else { | |||
for (Iterator i = v.iterator(); i.hasNext();) { | |||
Object o = i.next(); | |||
if (o instanceof DataType) { | |||
stk.push(o); | |||
invokeCircularReferenceCheck((DataType) o, stk, p); | |||
} | |||
} | |||
setChecked(true); | |||
} | |||
} | |||
} |
@@ -0,0 +1,72 @@ | |||
/* | |||
* 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.types.resources.selectors; | |||
import org.apache.tools.ant.types.Resource; | |||
import org.apache.tools.ant.types.Comparison; | |||
/** | |||
* Size ResourceSelector. | |||
* @since Ant 1.7 | |||
*/ | |||
public class Size implements ResourceSelector { | |||
private long size = -1; | |||
private Comparison when = Comparison.EQUAL; | |||
/** | |||
* Set the size to compare against. | |||
* @param l the long resource size. | |||
*/ | |||
public void setSize(long l) { | |||
size = l; | |||
} | |||
/** | |||
* Get the size compared to by this Size ResourceSelector. | |||
* @return the long resource size. | |||
*/ | |||
public long getSize() { | |||
return size; | |||
} | |||
/** | |||
* Set the comparison mode. | |||
* @param c a Comparison object. | |||
*/ | |||
public void setWhen(Comparison c) { | |||
when = c; | |||
} | |||
/** | |||
* Get the comparison mode. | |||
* @return a Comparison object. | |||
*/ | |||
public Comparison getWhen() { | |||
return when; | |||
} | |||
/** | |||
* Return true if this Resource is selected. | |||
* @param r the Resource to check. | |||
* @return whether the Resource was selected. | |||
*/ | |||
public boolean isSelected(Resource r) { | |||
long diff = r.getSize() - size; | |||
return when.evaluate(diff == 0 ? 0 : (int) (diff / Math.abs(diff))); | |||
} | |||
} |
@@ -0,0 +1,67 @@ | |||
/* | |||
* 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.types.resources.selectors; | |||
import org.apache.tools.ant.BuildException; | |||
import org.apache.tools.ant.types.Resource; | |||
import org.apache.tools.ant.types.EnumeratedAttribute; | |||
/** | |||
* Type file/dir ResourceSelector. | |||
* @since Ant 1.7 | |||
*/ | |||
public class Type implements ResourceSelector { | |||
/** | |||
* Implements the type attribute. | |||
*/ | |||
public static class FileDir extends EnumeratedAttribute { | |||
private static final String[] VALUES = new String[] {"file", "dir"}; | |||
/** | |||
* Return the possible values. | |||
* @return a String array. | |||
*/ | |||
public String[] getValues() { | |||
return VALUES; | |||
} | |||
} | |||
private FileDir type = null; | |||
/** | |||
* Set type; file|dir. | |||
* @param fd a FileDir object. | |||
*/ | |||
public void setType(FileDir fd) { | |||
type = fd; | |||
} | |||
/** | |||
* Return true if this Resource is selected. | |||
* @param r the Resource to check. | |||
* @return whether the Resource was selected. | |||
*/ | |||
public boolean isSelected(Resource r) { | |||
if (type == null) { | |||
throw new BuildException("The type attribute is required."); | |||
} | |||
int i = type.getIndex(); | |||
return r.isDirectory() ? i == 1 : i == 0; | |||
} | |||
} |
@@ -0,0 +1,143 @@ | |||
/* | |||
* 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.util; | |||
import java.io.InputStream; | |||
import java.io.BufferedInputStream; | |||
import java.io.IOException; | |||
import java.util.Iterator; | |||
import org.apache.tools.ant.Project; | |||
import org.apache.tools.ant.ProjectComponent; | |||
import org.apache.tools.ant.types.Resource; | |||
import org.apache.tools.ant.types.ResourceCollection; | |||
/** | |||
* Special <code>InputStream</code> that will | |||
* concatenate the contents of Resources from a single ResourceCollection. | |||
*/ | |||
public class ConcatResourceInputStream extends InputStream { | |||
private static final int EOF = -1; | |||
private boolean eof = false; | |||
private Iterator iter; | |||
private InputStream currentStream; | |||
private ProjectComponent managingPc; | |||
private boolean ignoreErrors = false; | |||
/** | |||
* Construct a new ConcatResourceInputStream | |||
* for the specified ResourceCollection. | |||
* @param rc the ResourceCollection to combine. | |||
* @throws IOException if I/O errors occur. | |||
*/ | |||
public ConcatResourceInputStream(ResourceCollection rc) throws IOException { | |||
iter = rc.iterator(); | |||
} | |||
/** | |||
* Set whether this ConcatResourceInputStream ignores errors. | |||
* @param b whether to ignore errors. | |||
*/ | |||
public void setIgnoreErrors(boolean b) { | |||
ignoreErrors = b; | |||
} | |||
/** | |||
* Find out whether this ConcatResourceInputStream ignores errors. | |||
* @return boolean ignore-errors flag. | |||
*/ | |||
public boolean isIgnoreErrors() { | |||
return ignoreErrors; | |||
} | |||
// inherit doc | |||
public void close() throws IOException { | |||
closeCurrent(); | |||
eof = true; | |||
} | |||
// inherit doc | |||
public int read() throws IOException { | |||
if (eof) { | |||
return EOF; | |||
} | |||
int result = readCurrent(); | |||
if (result == EOF) { | |||
nextResource(); | |||
result = readCurrent(); | |||
} | |||
return result; | |||
} | |||
/** | |||
* Set a managing <code>ProjectComponent</code> for | |||
* this <code>ConcatResourceInputStream</code>. | |||
* @param task the managing <code>Task</code>. | |||
*/ | |||
public void setManagingComponent(ProjectComponent pc) { | |||
this.managingPc = pc; | |||
} | |||
/** | |||
* Log a message with the specified logging level. | |||
* @param message the <code>String</code> message. | |||
* @param loglevel the <code>int</code> logging level. | |||
*/ | |||
public void log(String message, int loglevel) { | |||
if (managingPc != null) { | |||
managingPc.log(message, loglevel); | |||
} else { | |||
if (loglevel > Project.MSG_WARN) { | |||
System.out.println(message); | |||
} else { | |||
System.err.println(message); | |||
} | |||
} | |||
} | |||
private int readCurrent() throws IOException { | |||
return (eof || currentStream == null) ? EOF : currentStream.read(); | |||
} | |||
private void nextResource() throws IOException { | |||
closeCurrent(); | |||
while (iter.hasNext()) { | |||
Resource r = (Resource) iter.next(); | |||
if (!r.isExists()) { | |||
continue; | |||
} | |||
log("Concating " + r.toLongString(), Project.MSG_VERBOSE); | |||
try { | |||
currentStream = new BufferedInputStream(r.getInputStream()); | |||
return; | |||
} catch (IOException eyeOhEx) { | |||
if (!ignoreErrors) { | |||
log("Failed to get input stream for " + r, Project.MSG_ERR); | |||
throw eyeOhEx; | |||
} | |||
} | |||
} | |||
eof = true; | |||
} | |||
private void closeCurrent() { | |||
FileUtils.close(currentStream); | |||
currentStream = null; | |||
} | |||
} |
@@ -45,7 +45,10 @@ import org.apache.tools.ant.BuildException; | |||
import org.apache.tools.ant.Project; | |||
import org.apache.tools.ant.filters.util.ChainReaderHelper; | |||
import org.apache.tools.ant.taskdefs.condition.Os; | |||
import org.apache.tools.ant.types.Resource; | |||
import org.apache.tools.ant.types.FilterSetCollection; | |||
import org.apache.tools.ant.types.resources.Touchable; | |||
import org.apache.tools.ant.types.resources.FileResource; | |||
import org.apache.tools.ant.launch.Locator; | |||
/** | |||
@@ -521,139 +524,204 @@ public class FileUtils { | |||
String inputEncoding, String outputEncoding, | |||
Project project) | |||
throws IOException { | |||
copyResource(new FileResource(sourceFile), new FileResource(destFile), | |||
filters, filterChains, overwrite, preserveLastModified, | |||
inputEncoding, outputEncoding, project); | |||
} | |||
if (overwrite || !destFile.exists() | |||
|| destFile.lastModified() < sourceFile.lastModified()) { | |||
/** | |||
* Convenience method to copy content from one Resource to another. | |||
* No filtering is performed. | |||
* | |||
* @param source the Resource to copy from. | |||
* Must not be <code>null</code>. | |||
* @param dest the Resource to copy to. | |||
* Must not be <code>null</code>. | |||
* | |||
* @throws IOException if the copying fails. | |||
* | |||
* @since Ant 1.7 | |||
*/ | |||
public void copyResource(Resource source, Resource dest) throws IOException { | |||
copyResource(source, dest, null); | |||
} | |||
if (destFile.exists() && destFile.isFile()) { | |||
destFile.delete(); | |||
} | |||
// ensure that parent dir of dest file exists! | |||
// not using getParentFile method to stay 1.1 compat | |||
File parent = destFile.getParentFile(); | |||
if (parent != null && !parent.exists()) { | |||
parent.mkdirs(); | |||
/** | |||
* Convenience method to copy content from one Resource to another. | |||
* No filtering is performed. | |||
* | |||
* @param source the Resource to copy from. | |||
* Must not be <code>null</code>. | |||
* @param dest the Resource to copy to. | |||
* Must not be <code>null</code>. | |||
* @param project the project instance. | |||
* | |||
* @throws IOException if the copying fails. | |||
* | |||
* @since Ant 1.7 | |||
*/ | |||
public void copyResource(Resource source, Resource dest, Project project) | |||
throws IOException { | |||
copyResource(source, dest, null, null, false, | |||
false, null, null, project); | |||
} | |||
/** | |||
* Convenience method to copy content from one Resource to another | |||
* specifying whether token filtering must be used, whether filter chains | |||
* must be used, whether newer destination files may be overwritten and | |||
* whether the last modified time of <code>dest</code> file should be made | |||
* equal to the last modified time of <code>source</code>. | |||
* | |||
* @param source the Resource to copy from. | |||
* Must not be <code>null</code>. | |||
* @param dest the Resource to copy to. | |||
* Must not be <code>null</code>. | |||
* @param filters the collection of filters to apply to this copy. | |||
* @param filterChains filterChains to apply during the copy. | |||
* @param overwrite Whether or not the destination Resource should be | |||
* overwritten if it already exists. | |||
* @param preserveLastModified Whether or not the last modified time of | |||
* the destination Resource should be set to that | |||
* of the source. | |||
* @param inputEncoding the encoding used to read the files. | |||
* @param outputEncoding the encoding used to write the files. | |||
* @param project the project instance. | |||
* | |||
* @throws IOException if the copying fails. | |||
* | |||
* @since Ant 1.7 | |||
*/ | |||
public void copyResource(Resource source, Resource dest, | |||
FilterSetCollection filters, Vector filterChains, | |||
boolean overwrite, boolean preserveLastModified, | |||
String inputEncoding, String outputEncoding, | |||
Project project) | |||
throws IOException { | |||
if (!overwrite) { | |||
long slm = source.getLastModified(); | |||
if (dest.isExists() && slm != 0 | |||
&& dest.getLastModified() > slm) { | |||
return; | |||
} | |||
final boolean filterSetsAvailable = (filters != null | |||
&& filters.hasFilters()); | |||
final boolean filterChainsAvailable = (filterChains != null | |||
&& filterChains.size() > 0); | |||
if (filterSetsAvailable) { | |||
BufferedReader in = null; | |||
BufferedWriter out = null; | |||
try { | |||
if (inputEncoding == null) { | |||
in = new BufferedReader(new FileReader(sourceFile)); | |||
} else { | |||
InputStreamReader isr | |||
= new InputStreamReader(new FileInputStream(sourceFile), | |||
inputEncoding); | |||
in = new BufferedReader(isr); | |||
} | |||
if (outputEncoding == null) { | |||
out = new BufferedWriter(new FileWriter(destFile)); | |||
} | |||
final boolean filterSetsAvailable = (filters != null | |||
&& filters.hasFilters()); | |||
final boolean filterChainsAvailable = (filterChains != null | |||
&& filterChains.size() > 0); | |||
if (filterSetsAvailable) { | |||
BufferedReader in = null; | |||
BufferedWriter out = null; | |||
try { | |||
InputStreamReader isr = null; | |||
if (inputEncoding == null) { | |||
isr = new InputStreamReader(source.getInputStream()); | |||
} else { | |||
isr = new InputStreamReader(source.getInputStream(), | |||
inputEncoding); | |||
} | |||
in = new BufferedReader(isr); | |||
OutputStreamWriter osw = null; | |||
if (outputEncoding == null) { | |||
osw = new OutputStreamWriter(dest.getOutputStream()); | |||
} else { | |||
osw = new OutputStreamWriter(dest.getOutputStream(), | |||
outputEncoding); | |||
} | |||
out = new BufferedWriter(osw); | |||
if (filterChainsAvailable) { | |||
ChainReaderHelper crh = new ChainReaderHelper(); | |||
crh.setBufferSize(BUF_SIZE); | |||
crh.setPrimaryReader(in); | |||
crh.setFilterChains(filterChains); | |||
crh.setProject(project); | |||
Reader rdr = crh.getAssembledReader(); | |||
in = new BufferedReader(rdr); | |||
} | |||
LineTokenizer lineTokenizer = new LineTokenizer(); | |||
lineTokenizer.setIncludeDelims(true); | |||
String newline = null; | |||
String line = lineTokenizer.getToken(in); | |||
while (line != null) { | |||
if (line.length() == 0) { | |||
// this should not happen, because the lines are | |||
// returned with the end of line delimiter | |||
out.newLine(); | |||
} else { | |||
OutputStreamWriter osw | |||
= new OutputStreamWriter(new FileOutputStream(destFile), | |||
outputEncoding); | |||
out = new BufferedWriter(osw); | |||
} | |||
if (filterChainsAvailable) { | |||
ChainReaderHelper crh = new ChainReaderHelper(); | |||
crh.setBufferSize(BUF_SIZE); | |||
crh.setPrimaryReader(in); | |||
crh.setFilterChains(filterChains); | |||
crh.setProject(project); | |||
Reader rdr = crh.getAssembledReader(); | |||
in = new BufferedReader(rdr); | |||
} | |||
LineTokenizer lineTokenizer = new LineTokenizer(); | |||
lineTokenizer.setIncludeDelims(true); | |||
String newline = null; | |||
String line = lineTokenizer.getToken(in); | |||
while (line != null) { | |||
if (line.length() == 0) { | |||
// this should not happen, because the lines are | |||
// returned with the end of line delimiter | |||
out.newLine(); | |||
} else { | |||
newline = filters.replaceTokens(line); | |||
out.write(newline); | |||
} | |||
line = lineTokenizer.getToken(in); | |||
newline = filters.replaceTokens(line); | |||
out.write(newline); | |||
} | |||
} finally { | |||
close(out); | |||
close(in); | |||
line = lineTokenizer.getToken(in); | |||
} | |||
} else if (filterChainsAvailable | |||
|| (inputEncoding != null | |||
&& !inputEncoding.equals(outputEncoding)) | |||
|| (inputEncoding == null && outputEncoding != null)) { | |||
BufferedReader in = null; | |||
BufferedWriter out = null; | |||
try { | |||
if (inputEncoding == null) { | |||
in = new BufferedReader(new FileReader(sourceFile)); | |||
} else { | |||
in = | |||
new BufferedReader( | |||
new InputStreamReader( | |||
new FileInputStream(sourceFile), | |||
inputEncoding)); | |||
} | |||
if (outputEncoding == null) { | |||
out = new BufferedWriter(new FileWriter(destFile)); | |||
} else { | |||
out = | |||
new BufferedWriter( | |||
new OutputStreamWriter( | |||
new FileOutputStream(destFile), | |||
outputEncoding)); | |||
} | |||
if (filterChainsAvailable) { | |||
ChainReaderHelper crh = new ChainReaderHelper(); | |||
crh.setBufferSize(BUF_SIZE); | |||
crh.setPrimaryReader(in); | |||
crh.setFilterChains(filterChains); | |||
crh.setProject(project); | |||
Reader rdr = crh.getAssembledReader(); | |||
in = new BufferedReader(rdr); | |||
} | |||
char[] buffer = new char[BUF_SIZE]; | |||
while (true) { | |||
int nRead = in.read(buffer, 0, buffer.length); | |||
if (nRead == -1) { | |||
break; | |||
} | |||
out.write(buffer, 0, nRead); | |||
} | |||
} finally { | |||
close(out); | |||
close(in); | |||
} | |||
} else { | |||
FileInputStream in = null; | |||
FileOutputStream out = null; | |||
try { | |||
in = new FileInputStream(sourceFile); | |||
out = new FileOutputStream(destFile); | |||
byte[] buffer = new byte[BUF_SIZE]; | |||
int count = 0; | |||
do { | |||
out.write(buffer, 0, count); | |||
count = in.read(buffer, 0, buffer.length); | |||
} while (count != -1); | |||
} finally { | |||
close(out); | |||
close(in); | |||
} finally { | |||
close(out); | |||
close(in); | |||
} | |||
} else if (filterChainsAvailable | |||
|| (inputEncoding != null | |||
&& !inputEncoding.equals(outputEncoding)) | |||
|| (inputEncoding == null && outputEncoding != null)) { | |||
BufferedReader in = null; | |||
BufferedWriter out = null; | |||
try { | |||
InputStreamReader isr = null; | |||
if (inputEncoding == null) { | |||
isr = new InputStreamReader(source.getInputStream()); | |||
} else { | |||
isr = new InputStreamReader(source.getInputStream(), | |||
inputEncoding); | |||
} | |||
in = new BufferedReader(isr); | |||
OutputStreamWriter osw = null; | |||
if (outputEncoding == null) { | |||
osw = new OutputStreamWriter(dest.getOutputStream()); | |||
} else { | |||
osw = new OutputStreamWriter(dest.getOutputStream(), | |||
outputEncoding); | |||
} | |||
out = new BufferedWriter(osw); | |||
if (filterChainsAvailable) { | |||
ChainReaderHelper crh = new ChainReaderHelper(); | |||
crh.setBufferSize(BUF_SIZE); | |||
crh.setPrimaryReader(in); | |||
crh.setFilterChains(filterChains); | |||
crh.setProject(project); | |||
Reader rdr = crh.getAssembledReader(); | |||
in = new BufferedReader(rdr); | |||
} | |||
char[] buffer = new char[BUF_SIZE]; | |||
while (true) { | |||
int nRead = in.read(buffer, 0, buffer.length); | |||
if (nRead == -1) { | |||
break; | |||
} | |||
out.write(buffer, 0, nRead); | |||
} | |||
} finally { | |||
close(out); | |||
close(in); | |||
} | |||
if (preserveLastModified) { | |||
setFileLastModified(destFile, sourceFile.lastModified()); | |||
} else { | |||
InputStream in = null; | |||
OutputStream out = null; | |||
try { | |||
in = source.getInputStream(); | |||
out = dest.getOutputStream(); | |||
byte[] buffer = new byte[BUF_SIZE]; | |||
int count = 0; | |||
do { | |||
out.write(buffer, 0, count); | |||
count = in.read(buffer, 0, buffer.length); | |||
} while (count != -1); | |||
} finally { | |||
close(out); | |||
close(in); | |||
} | |||
} | |||
if (preserveLastModified && dest instanceof Touchable) { | |||
setLastModified((Touchable) dest, source.getLastModified()); | |||
} | |||
} | |||
/** | |||
@@ -665,7 +733,19 @@ public class FileUtils { | |||
* if this is -1, the current time is used. | |||
*/ | |||
public void setFileLastModified(File file, long time) { | |||
file.setLastModified((time < 0) ? System.currentTimeMillis() : time); | |||
setLastModified(new FileResource(file), time); | |||
} | |||
/** | |||
* Set the last modified time of an object implementing | |||
* org.apache.tools.ant.types.resources.Touchable . | |||
* | |||
* @param t the Touchable whose modified time is to be set. | |||
* @param time the time to which the last modified time is to be set. | |||
* if this is -1, the current time is used. | |||
*/ | |||
public void setLastModified(Touchable t, long time) { | |||
t.touch((time < 0) ? System.currentTimeMillis() : time); | |||
} | |||
/** | |||
@@ -987,62 +1067,108 @@ public class FileUtils { | |||
* @since Ant 1.6.3 | |||
*/ | |||
public boolean contentEquals(File f1, File f2, boolean textfile) throws IOException { | |||
if (f1.exists() != f2.exists()) { | |||
return contentEquals(new FileResource(f1), new FileResource(f2), textfile); | |||
} | |||
/** | |||
* Compares the contents of two Resources. | |||
* | |||
* @param r1 the Resource whose content is to be compared. | |||
* @param r2 the other Resource whose content is to be compared. | |||
* @param text true if the content is to be treated as text and | |||
* differences in kind of line break are to be ignored. | |||
* | |||
* @return true if the content of the Resources is the same. | |||
* | |||
* @throws IOException if the Resources cannot be read. | |||
* @since Ant 1.6.3 | |||
*/ | |||
public boolean contentEquals(Resource r1, Resource r2, boolean text) throws IOException { | |||
if (r1.isExists() != r2.isExists()) { | |||
return false; | |||
} | |||
if (!f1.exists()) { | |||
if (!r1.isExists()) { | |||
// two not existing files are equal | |||
return true; | |||
} | |||
// should the following two be switched? If f1 and f2 refer to the same file, | |||
// should the following two be switched? If r1 and r2 refer to the same file, | |||
// isn't their content equal regardless of whether that file is a directory? | |||
if (f1.isDirectory() || f2.isDirectory()) { | |||
if (r1.isDirectory() || r2.isDirectory()) { | |||
// don't want to compare directory contents for now | |||
return false; | |||
} | |||
if (fileNameEquals(f1, f2)) { | |||
// same filename => true | |||
if (r1.equals(r2)) { | |||
return true; | |||
} | |||
return textfile ? textEquals(f1, f2) : binaryEquals(f1, f2); | |||
if (!text && r1.getSize() != r2.getSize()) { | |||
return false; | |||
} | |||
return compareContent(r1, r2, text) == 0; | |||
} | |||
/** | |||
* Binary compares the contents of two files. | |||
* Compare the content of two Resources. A nonexistent Resource's | |||
* content is "less than" that of an existing Resource; a directory-type | |||
* Resource's content is "less than" that of a file-type Resource. | |||
* @param r1 the Resource whose content is to be compared. | |||
* @param r2 the other Resource whose content is to be compared. | |||
* @param text true if the content is to be treated as text and | |||
* differences in kind of line break are to be ignored. | |||
* @return a negative integer, zero, or a positive integer as the first | |||
* argument is less than, equal to, or greater than the second. | |||
* @throws IOException if the Resources cannot be read. | |||
*/ | |||
public int compareContent(Resource r1, Resource r2, boolean text) throws IOException { | |||
if (r1.equals(r2)) { | |||
return 0; | |||
} | |||
boolean e1 = r1.isExists(); | |||
boolean e2 = r2.isExists(); | |||
if (!(e1 || e2)) { | |||
return 0; | |||
} | |||
if (e1 != e2) { | |||
return e1 ? 1 : -1; | |||
} | |||
boolean d1 = r1.isDirectory(); | |||
boolean d2 = r2.isDirectory(); | |||
if (d1 && d2) { | |||
return 0; | |||
} | |||
if (d1 || d2) { | |||
return d1 ? -1 : 1; | |||
} | |||
return text ? textCompare(r1, r2) : binaryCompare(r1, r2); | |||
} | |||
/** | |||
* Binary compares the contents of two Resources. | |||
* <p> | |||
* simple but sub-optimal comparision algorithm. written for working | |||
* rather than fast. Better would be a block read into buffers followed | |||
* by long comparisions apart from the final 1-7 bytes. | |||
* </p> | |||
* | |||
* @param f1 the file whose content is to be compared. | |||
* @param f2 the other file whose content is to be compared. | |||
* @return true if the content of the files is the same. | |||
* @throws IOException if the files cannot be read. | |||
* @param r1 the Resource whose content is to be compared. | |||
* @param r2 the other Resource whose content is to be compared. | |||
* @return a negative integer, zero, or a positive integer as the first | |||
* argument is less than, equal to, or greater than the second. | |||
* @throws IOException if the Resources cannot be read. | |||
*/ | |||
private boolean binaryEquals(File f1, File f2) throws IOException { | |||
if (f1.length() != f2.length()) { | |||
// different size =>false | |||
return false; | |||
} | |||
private int binaryCompare(Resource r1, Resource r2) throws IOException { | |||
InputStream in1 = null; | |||
InputStream in2 = null; | |||
try { | |||
in1 = new BufferedInputStream(new FileInputStream(f1)); | |||
in2 = new BufferedInputStream(new FileInputStream(f2)); | |||
in1 = new BufferedInputStream(r1.getInputStream()); | |||
in2 = new BufferedInputStream(r2.getInputStream()); | |||
int expectedByte = in1.read(); | |||
while (expectedByte != -1) { | |||
if (expectedByte != in2.read()) { | |||
return false; | |||
for (int b1 = in1.read(); b1 != -1; b1 = in1.read()) { | |||
int b2 = in2.read(); | |||
if (b1 != b2) { | |||
return b1 > b2 ? 1 : -1; | |||
} | |||
expectedByte = in1.read(); | |||
} | |||
if (in2.read() != -1) { | |||
return false; | |||
} | |||
return true; | |||
return in2.read() == -1 ? 0 : -1; | |||
} finally { | |||
close(in1); | |||
close(in2); | |||
@@ -1050,33 +1176,30 @@ public class FileUtils { | |||
} | |||
/** | |||
* Text compares the contents of two files. | |||
* | |||
* Text compares the contents of two Resources. | |||
* Ignores different kinds of line endings. | |||
* | |||
* @param f1 the file whose content is to be compared. | |||
* @param f2 the other file whose content is to be compared. | |||
* @return true if the content of the files is the same. | |||
* @throws IOException if the files cannot be read. | |||
* @param r1 the Resource whose content is to be compared. | |||
* @param r2 the other Resource whose content is to be compared. | |||
* @return a negative integer, zero, or a positive integer as the first | |||
* argument is less than, equal to, or greater than the second. | |||
* @throws IOException if the Resources cannot be read. | |||
*/ | |||
private boolean textEquals(File f1, File f2) throws IOException { | |||
private int textCompare(Resource r1, Resource r2) throws IOException { | |||
BufferedReader in1 = null; | |||
BufferedReader in2 = null; | |||
try { | |||
in1 = new BufferedReader(new FileReader(f1)); | |||
in2 = new BufferedReader(new FileReader(f2)); | |||
in1 = new BufferedReader(new InputStreamReader(r1.getInputStream())); | |||
in2 = new BufferedReader(new InputStreamReader(r2.getInputStream())); | |||
String expected = in1.readLine(); | |||
while (expected != null) { | |||
if (!expected.equals(in2.readLine())) { | |||
return false; | |||
String actual = in2.readLine(); | |||
if (!expected.equals(actual)) { | |||
return expected.compareTo(actual); | |||
} | |||
expected = in1.readLine(); | |||
} | |||
if (in2.readLine() != null) { | |||
return false; | |||
} | |||
return true; | |||
return in2.readLine() == null ? 0 : -1; | |||
} finally { | |||
close(in1); | |||
close(in2); | |||
@@ -1384,7 +1507,6 @@ public class FileUtils { | |||
return isUpToDate(sourceTime, destTime, granularity); | |||
} | |||
/** | |||
* Returns true if the source is older than the dest. | |||
* @param source source file (should be the older). | |||
@@ -0,0 +1,69 @@ | |||
/* | |||
* 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.util; | |||
import java.io.IOException; | |||
import java.io.ByteArrayOutputStream; | |||
import org.apache.tools.ant.Project; | |||
/** | |||
* Exception thrown when an attempt is made to get an OutputStream | |||
* from an immutable Resource. | |||
* @since Ant 1.7 | |||
*/ | |||
public class PropertyOutputStream extends ByteArrayOutputStream { | |||
private Project project; | |||
private String property; | |||
private boolean trim; | |||
/** | |||
* Construct a new PropertyOutputStream for the specified Project | |||
* and property name, trimming the property value. | |||
* @param p the associated Ant Project. | |||
* @param s the String property name. | |||
*/ | |||
public PropertyOutputStream(Project p, String s) { | |||
this(p, s, true); | |||
} | |||
/** | |||
* Construct a new PropertyOutputStream for | |||
* the specified Project, property name, and trim mode. | |||
* @param p the associated Ant Project. | |||
* @param s the String property name. | |||
* @param b the boolean trim mode. | |||
*/ | |||
public PropertyOutputStream(Project p, String s, boolean b) { | |||
project = p; | |||
property = s; | |||
trim = b; | |||
} | |||
/** | |||
* Close the PropertyOutputStream, storing the property. | |||
*/ | |||
public void close() { | |||
if (project != null && property != null) { | |||
String s = new String(toByteArray()); | |||
project.setNewProperty(property, trim ? s.trim() : s); | |||
} | |||
} | |||
} | |||
@@ -370,27 +370,29 @@ public class ZipFile { | |||
*/ | |||
private void positionAtCentralDirectory() | |||
throws IOException { | |||
long off = archive.length() - MIN_EOCD_SIZE; | |||
archive.seek(off); | |||
byte[] sig = ZipOutputStream.EOCD_SIG; | |||
int curr = archive.read(); | |||
boolean found = false; | |||
while (curr != -1) { | |||
if (curr == sig[0]) { | |||
curr = archive.read(); | |||
if (curr == sig[1]) { | |||
long off = archive.length() - MIN_EOCD_SIZE; | |||
if (off >= 0) { | |||
archive.seek(off); | |||
byte[] sig = ZipOutputStream.EOCD_SIG; | |||
int curr = archive.read(); | |||
while (curr != -1) { | |||
if (curr == sig[0]) { | |||
curr = archive.read(); | |||
if (curr == sig[2]) { | |||
if (curr == sig[1]) { | |||
curr = archive.read(); | |||
if (curr == sig[3]) { | |||
found = true; | |||
break; | |||
if (curr == sig[2]) { | |||
curr = archive.read(); | |||
if (curr == sig[3]) { | |||
found = true; | |||
break; | |||
} | |||
} | |||
} | |||
} | |||
archive.seek(--off); | |||
curr = archive.read(); | |||
} | |||
archive.seek(--off); | |||
curr = archive.read(); | |||
} | |||
if (!found) { | |||
throw new ZipException("archive is not a ZIP archive"); | |||
@@ -0,0 +1,16 @@ | |||
<antlib> | |||
<typedef name="name" | |||
classname="org.apache.tools.ant.types.resources.comparators.Name" /> | |||
<typedef name="size" | |||
classname="org.apache.tools.ant.types.resources.comparators.Size" /> | |||
<typedef name="date" | |||
classname="org.apache.tools.ant.types.resources.comparators.Date" /> | |||
<typedef name="exists" | |||
classname="org.apache.tools.ant.types.resources.comparators.Exists" /> | |||
<typedef name="type" | |||
classname="org.apache.tools.ant.types.resources.comparators.Type" /> | |||
<typedef name="content" | |||
classname="org.apache.tools.ant.types.resources.comparators.Content" /> | |||
<typedef name="reverse" | |||
classname="org.apache.tools.ant.types.resources.comparators.Reverse" /> | |||
</antlib> |
@@ -0,0 +1,24 @@ | |||
<antlib> | |||
<typedef name="name" | |||
classname="org.apache.tools.ant.types.resources.selectors.Name" /> | |||
<typedef name="not" | |||
classname="org.apache.tools.ant.types.resources.selectors.Not" /> | |||
<typedef name="none" | |||
classname="org.apache.tools.ant.types.resources.selectors.None" /> | |||
<typedef name="and" | |||
classname="org.apache.tools.ant.types.resources.selectors.And" /> | |||
<typedef name="or" | |||
classname="org.apache.tools.ant.types.resources.selectors.Or" /> | |||
<typedef name="exists" | |||
classname="org.apache.tools.ant.types.resources.selectors.Exists" /> | |||
<typedef name="type" | |||
classname="org.apache.tools.ant.types.resources.selectors.Type" /> | |||
<typedef name="majority" | |||
classname="org.apache.tools.ant.types.resources.selectors.Majority" /> | |||
<typedef name="instanceof" | |||
classname="org.apache.tools.ant.types.resources.selectors.InstanceOf" /> | |||
<typedef name="size" | |||
classname="org.apache.tools.ant.types.resources.selectors.Size" /> | |||
<typedef name="date" | |||
classname="org.apache.tools.ant.types.resources.selectors.Date" /> | |||
</antlib> |
@@ -275,4 +275,9 @@ public class ConcatTest | |||
File f2 = getProject().resolveFile("concat.utf8"); | |||
assertTrue(FILE_UTILS.contentEquals(f1, f2)); | |||
} | |||
public void testResources() { | |||
executeTarget("testResources"); | |||
} | |||
} |
@@ -0,0 +1,136 @@ | |||
/* | |||
* 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.types; | |||
import org.apache.tools.ant.BuildFileTest; | |||
public class ResourceCollectionsTest extends BuildFileTest { | |||
public ResourceCollectionsTest(String name) { | |||
super(name); | |||
} | |||
public void setUp() { | |||
configureProject("src/etc/testcases/types/resources/build.xml"); | |||
} | |||
public void tearDown() { | |||
executeTarget("tearDown"); | |||
} | |||
public void testdifference() { | |||
executeTarget("testdifference"); | |||
} | |||
public void testdirset() { | |||
executeTarget("testdirset"); | |||
} | |||
public void testfile() { | |||
executeTarget("testfile"); | |||
} | |||
public void testfilelist() { | |||
executeTarget("testfilelist"); | |||
} | |||
public void testfiles1() { | |||
executeTarget("testfiles1"); | |||
} | |||
public void testfiles2() { | |||
executeTarget("testfiles2"); | |||
} | |||
public void testfiles3() { | |||
executeTarget("testfiles3"); | |||
} | |||
public void testfileset() { | |||
executeTarget("testfileset"); | |||
} | |||
public void testfileurl() { | |||
executeTarget("testfileurl"); | |||
} | |||
public void testfileurlref() { | |||
executeTarget("testfileurlref"); | |||
} | |||
public void testhttpurl1() { | |||
executeTarget("testhttpurl1"); | |||
} | |||
public void testhttpurl2() { | |||
executeTarget("testhttpurl2"); | |||
} | |||
public void testintersect() { | |||
executeTarget("testintersect"); | |||
} | |||
public void testjarurl() { | |||
executeTarget("testjarurl"); | |||
} | |||
public void testnestedresources() { | |||
executeTarget("testnestedresources"); | |||
} | |||
public void testpath() { | |||
executeTarget("testpath"); | |||
} | |||
public void testpropertyset() { | |||
executeTarget("testpropertyset"); | |||
} | |||
public void testresource() { | |||
executeTarget("testresource"); | |||
} | |||
public void testresourcesref() { | |||
executeTarget("testresourcesref"); | |||
} | |||
public void testresourceurl() { | |||
executeTarget("testresourceurl"); | |||
} | |||
public void teststring1() { | |||
executeTarget("teststring1"); | |||
} | |||
public void teststring2() { | |||
executeTarget("teststring2"); | |||
} | |||
public void testunion() { | |||
executeTarget("testunion"); | |||
} | |||
public void testzipentry() { | |||
executeTarget("testzipentry"); | |||
} | |||
public void testzipfileset() { | |||
executeTarget("testzipfileset"); | |||
} | |||
} |
@@ -0,0 +1,100 @@ | |||
/* | |||
* 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.types; | |||
import org.apache.tools.ant.BuildFileTest; | |||
public class ResourceComparatorsTest extends BuildFileTest { | |||
public ResourceComparatorsTest(String name) { | |||
super(name); | |||
} | |||
public void setUp() { | |||
configureProject("src/etc/testcases/types/resources/comparators/build.xml"); | |||
} | |||
public void tearDown() { | |||
executeTarget("tearDown"); | |||
} | |||
public void testcompoundsort1() { | |||
executeTarget("testcompoundsort1"); | |||
} | |||
public void testcompoundsort2() { | |||
executeTarget("testcompoundsort2"); | |||
} | |||
public void testcontent() { | |||
executeTarget("testcontent"); | |||
} | |||
public void testexists() { | |||
executeTarget("testexists"); | |||
} | |||
public void testdate() { | |||
executeTarget("testdate"); | |||
} | |||
public void testname() { | |||
executeTarget("testname"); | |||
} | |||
public void testrvcontent() { | |||
executeTarget("testrvcontent"); | |||
} | |||
public void testrvdefault() { | |||
executeTarget("testrvdefault"); | |||
} | |||
public void testrvexists() { | |||
executeTarget("testrvexists"); | |||
} | |||
public void testrvdate() { | |||
executeTarget("testrvdate"); | |||
} | |||
public void testrvname() { | |||
executeTarget("testrvname"); | |||
} | |||
public void testrvsize() { | |||
executeTarget("testrvsize"); | |||
} | |||
public void testrvtype() { | |||
executeTarget("testrvtype"); | |||
} | |||
public void testsize() { | |||
executeTarget("testsize"); | |||
} | |||
public void testsortdefault() { | |||
executeTarget("testsortdefault"); | |||
} | |||
public void testtype() { | |||
executeTarget("testtype"); | |||
} | |||
} |
@@ -0,0 +1,153 @@ | |||
/* | |||
* 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.types; | |||
import java.io.File; | |||
import java.io.IOException; | |||
import java.io.InputStreamReader; | |||
import java.net.UnknownServiceException; | |||
import org.apache.tools.ant.Project; | |||
import org.apache.tools.ant.BuildFileTest; | |||
import org.apache.tools.ant.BuildException; | |||
import org.apache.tools.ant.taskdefs.Zip; | |||
import org.apache.tools.ant.types.Resource; | |||
import org.apache.tools.ant.types.resources.URLResource; | |||
import org.apache.tools.ant.types.resources.ZipResource; | |||
import org.apache.tools.ant.types.resources.FileResource; | |||
import org.apache.tools.ant.types.resources.StringResource; | |||
import org.apache.tools.ant.types.resources.PropertyResource; | |||
import org.apache.tools.ant.types.resources.ImmutableResourceException; | |||
import org.apache.tools.ant.util.FileUtils; | |||
public class ResourceOutputTest extends BuildFileTest { | |||
private static final FileUtils FILE_UTILS = FileUtils.getFileUtils(); | |||
private static final File basedir = new File(System.getProperty("root"), | |||
"src/etc/testcases/types/resources"); | |||
public ResourceOutputTest(String name) { | |||
super(name); | |||
} | |||
public void setUp() { | |||
project = new Project(); | |||
project.init(); | |||
project.setUserProperty("basedir" , basedir.getAbsolutePath()); | |||
} | |||
public void testresourceoutput() { | |||
try { | |||
testoutputbe(new Resource("foo")); | |||
fail("should have caught UnsupportedOperationException"); | |||
} catch (UnsupportedOperationException e) { | |||
} | |||
} | |||
public void teststringoutput1() { | |||
StringResource r = new StringResource(); | |||
testoutputbe(r); | |||
assertEquals("foo", r.getValue()); | |||
} | |||
public void teststringoutput2() { | |||
StringResource r = new StringResource("bar"); | |||
try { | |||
testoutput(r); | |||
fail("should have caught ImmutableResourceException"); | |||
} catch (ImmutableResourceException e) { | |||
} catch (IOException e) { | |||
fail("caught some other IOException: " + e); | |||
} | |||
assertEquals("bar", r.getValue()); | |||
} | |||
public void testpropertyoutput1() { | |||
PropertyResource r = new PropertyResource(getProject(), "bar"); | |||
testoutputbe(r); | |||
assertPropertyEquals("bar", "foo"); | |||
} | |||
public void testpropertyoutput2() { | |||
getProject().setNewProperty("bar", "bar"); | |||
PropertyResource r = new PropertyResource(getProject(), "bar"); | |||
try { | |||
testoutput(r); | |||
fail("should have caught ImmutableResourceException"); | |||
} catch (ImmutableResourceException e) { | |||
} catch (IOException e) { | |||
fail("caught some other IOException: " + e); | |||
} | |||
assertPropertyEquals("bar", "bar"); | |||
} | |||
public void testurloutput() { | |||
File f = getProject().resolveFile("testurloutput"); | |||
try { | |||
FILE_UTILS.createNewFile(f); | |||
testoutput(new URLResource(f)); | |||
fail("should have caught UnknownServiceException"); | |||
} catch (UnknownServiceException e) { | |||
} catch (IOException e) { | |||
e.printStackTrace(System.err); | |||
fail("caught some other IOException: " + e); | |||
} finally { | |||
if (!f.delete()) { | |||
f.deleteOnExit(); | |||
} | |||
} | |||
} | |||
public void testzipentryoutput() { | |||
Zip z = new Zip(); | |||
z.setProject(getProject()); | |||
Zip.WhenEmpty create = new Zip.WhenEmpty(); | |||
create.setValue("create"); | |||
z.setWhenempty(create); | |||
z.setBasedir(basedir); | |||
z.setExcludes("**/*"); | |||
File f = getProject().resolveFile("foo"); | |||
z.setDestFile(f); | |||
z.execute(); | |||
ZipResource r = new ZipResource(); | |||
r.setZipfile(f); | |||
r.setName("foo"); | |||
try { | |||
testoutputbe(r); | |||
fail("should have caught UnsupportedOperationException"); | |||
} catch (UnsupportedOperationException e) { | |||
} finally { | |||
if (!f.delete()) { | |||
f.deleteOnExit(); | |||
} | |||
} | |||
} | |||
private void testoutputbe(Resource dest) { | |||
try { | |||
testoutput(dest); | |||
} catch (IOException e) { | |||
throw new BuildException(e); | |||
} | |||
} | |||
private void testoutput(Resource dest) throws IOException { | |||
FILE_UTILS.copyResource(new StringResource("foo"), dest, null); | |||
} | |||
} |
@@ -0,0 +1,100 @@ | |||
/* | |||
* 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.types; | |||
import org.apache.tools.ant.BuildFileTest; | |||
public class ResourceSelectorsTest extends BuildFileTest { | |||
public ResourceSelectorsTest(String name) { | |||
super(name); | |||
} | |||
public void setUp() { | |||
configureProject("src/etc/testcases/types/resources/selectors/build.xml"); | |||
} | |||
public void testname1() { | |||
executeTarget("testname1"); | |||
} | |||
public void testname2() { | |||
executeTarget("testname2"); | |||
} | |||
public void testexists() { | |||
executeTarget("testexists"); | |||
} | |||
public void testinstanceoftype1() { | |||
executeTarget("testinstanceoftype1"); | |||
} | |||
public void testinstanceoftype2() { | |||
executeTarget("testinstanceoftype2"); | |||
} | |||
public void testinstanceofclass() { | |||
executeTarget("testinstanceofclass"); | |||
} | |||
public void testtype() { | |||
executeTarget("testtype"); | |||
} | |||
public void testdate() { | |||
executeTarget("testdate"); | |||
} | |||
public void testsize() { | |||
executeTarget("testsize"); | |||
} | |||
public void testand() { | |||
executeTarget("testand"); | |||
} | |||
public void testor() { | |||
executeTarget("testor"); | |||
} | |||
public void testnot() { | |||
executeTarget("testnot"); | |||
} | |||
public void testnone() { | |||
executeTarget("testnone"); | |||
} | |||
public void testmajority1() { | |||
executeTarget("testmajority1"); | |||
} | |||
public void testmajority2() { | |||
executeTarget("testmajority2"); | |||
} | |||
public void testmajority3() { | |||
executeTarget("testmajority3"); | |||
} | |||
public void testmajority4() { | |||
executeTarget("testmajority4"); | |||
} | |||
} |
@@ -172,4 +172,9 @@ public class ClassFileSetTest extends BuildFileTest { | |||
assertTrue("Result did not contain test" + File.separator + "ContainsOnlyInner.class", | |||
files.containsKey("test" + File.separator + "MethodParam.class")); | |||
} | |||
public void testResourceCollection() { | |||
executeTarget("testresourcecollection"); | |||
} | |||
} |