Browse Source

ResourceCollections

git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@278337 13f79535-47bb-0310-9956-ffa450edef68
master
Matthew Jason Benson 20 years ago
parent
commit
fbb9886634
73 changed files with 8470 additions and 883 deletions
  1. +600
    -0
      docs/manual/CoreTypes/resources.html
  2. +2
    -0
      docs/manual/conceptstypeslist.html
  3. +27
    -0
      src/etc/testcases/taskdefs/concat.xml
  4. +24
    -0
      src/etc/testcases/taskdefs/optional/depend/depend.xml
  5. +450
    -0
      src/etc/testcases/types/resources/build.xml
  6. +326
    -0
      src/etc/testcases/types/resources/comparators/build.xml
  7. +410
    -0
      src/etc/testcases/types/resources/selectors/build.xml
  8. +196
    -256
      src/main/org/apache/tools/ant/taskdefs/Concat.java
  9. +53
    -66
      src/main/org/apache/tools/ant/taskdefs/Length.java
  10. +52
    -40
      src/main/org/apache/tools/ant/taskdefs/PathConvert.java
  11. +124
    -0
      src/main/org/apache/tools/ant/taskdefs/ResourceCount.java
  12. +1
    -0
      src/main/org/apache/tools/ant/taskdefs/defaults.properties
  13. +93
    -0
      src/main/org/apache/tools/ant/types/Comparison.java
  14. +39
    -1
      src/main/org/apache/tools/ant/types/DirSet.java
  15. +44
    -22
      src/main/org/apache/tools/ant/types/FileList.java
  16. +39
    -1
      src/main/org/apache/tools/ant/types/FileSet.java
  17. +55
    -212
      src/main/org/apache/tools/ant/types/Path.java
  18. +39
    -1
      src/main/org/apache/tools/ant/types/PropertySet.java
  19. +226
    -20
      src/main/org/apache/tools/ant/types/Resource.java
  20. +49
    -0
      src/main/org/apache/tools/ant/types/ResourceCollection.java
  21. +78
    -19
      src/main/org/apache/tools/ant/types/ZipFileSet.java
  22. +137
    -53
      src/main/org/apache/tools/ant/types/ZipScanner.java
  23. +25
    -8
      src/main/org/apache/tools/ant/types/defaults.properties
  24. +223
    -0
      src/main/org/apache/tools/ant/types/resources/BaseResourceCollectionContainer.java
  25. +67
    -0
      src/main/org/apache/tools/ant/types/resources/Difference.java
  26. +132
    -0
      src/main/org/apache/tools/ant/types/resources/FailFast.java
  27. +300
    -0
      src/main/org/apache/tools/ant/types/resources/FileResource.java
  28. +108
    -0
      src/main/org/apache/tools/ant/types/resources/FileResourceIterator.java
  29. +503
    -0
      src/main/org/apache/tools/ant/types/resources/Files.java
  30. +44
    -0
      src/main/org/apache/tools/ant/types/resources/ImmutableResourceException.java
  31. +62
    -0
      src/main/org/apache/tools/ant/types/resources/Intersect.java
  32. +133
    -0
      src/main/org/apache/tools/ant/types/resources/PropertyResource.java
  33. +187
    -0
      src/main/org/apache/tools/ant/types/resources/Resources.java
  34. +137
    -0
      src/main/org/apache/tools/ant/types/resources/Restrict.java
  35. +107
    -0
      src/main/org/apache/tools/ant/types/resources/Sort.java
  36. +204
    -0
      src/main/org/apache/tools/ant/types/resources/StringResource.java
  37. +26
    -0
      src/main/org/apache/tools/ant/types/resources/Touchable.java
  38. +373
    -0
      src/main/org/apache/tools/ant/types/resources/URLResource.java
  39. +85
    -0
      src/main/org/apache/tools/ant/types/resources/Union.java
  40. +299
    -0
      src/main/org/apache/tools/ant/types/resources/ZipResource.java
  41. +69
    -0
      src/main/org/apache/tools/ant/types/resources/comparators/Content.java
  42. +37
    -0
      src/main/org/apache/tools/ant/types/resources/comparators/Date.java
  43. +42
    -0
      src/main/org/apache/tools/ant/types/resources/comparators/Exists.java
  44. +37
    -0
      src/main/org/apache/tools/ant/types/resources/comparators/Name.java
  45. +62
    -0
      src/main/org/apache/tools/ant/types/resources/comparators/ResourceComparator.java
  46. +56
    -0
      src/main/org/apache/tools/ant/types/resources/comparators/Reverse.java
  47. +37
    -0
      src/main/org/apache/tools/ant/types/resources/comparators/Size.java
  48. +43
    -0
      src/main/org/apache/tools/ant/types/resources/comparators/Type.java
  49. +43
    -0
      src/main/org/apache/tools/ant/types/resources/selectors/And.java
  50. +161
    -0
      src/main/org/apache/tools/ant/types/resources/selectors/Date.java
  51. +36
    -0
      src/main/org/apache/tools/ant/types/resources/selectors/Exists.java
  52. +129
    -0
      src/main/org/apache/tools/ant/types/resources/selectors/InstanceOf.java
  53. +69
    -0
      src/main/org/apache/tools/ant/types/resources/selectors/Majority.java
  54. +76
    -0
      src/main/org/apache/tools/ant/types/resources/selectors/Name.java
  55. +43
    -0
      src/main/org/apache/tools/ant/types/resources/selectors/None.java
  56. +65
    -0
      src/main/org/apache/tools/ant/types/resources/selectors/Not.java
  57. +43
    -0
      src/main/org/apache/tools/ant/types/resources/selectors/Or.java
  58. +34
    -0
      src/main/org/apache/tools/ant/types/resources/selectors/ResourceSelector.java
  59. +111
    -0
      src/main/org/apache/tools/ant/types/resources/selectors/ResourceSelectorContainer.java
  60. +72
    -0
      src/main/org/apache/tools/ant/types/resources/selectors/Size.java
  61. +67
    -0
      src/main/org/apache/tools/ant/types/resources/selectors/Type.java
  62. +143
    -0
      src/main/org/apache/tools/ant/util/ConcatResourceInputStream.java
  63. +292
    -170
      src/main/org/apache/tools/ant/util/FileUtils.java
  64. +69
    -0
      src/main/org/apache/tools/ant/util/PropertyOutputStream.java
  65. +16
    -14
      src/main/org/apache/tools/zip/ZipFile.java
  66. +16
    -0
      src/resources/org/apache/tools/ant/types/resources/comparators/antlib.xml
  67. +24
    -0
      src/resources/org/apache/tools/ant/types/resources/selectors/antlib.xml
  68. +5
    -0
      src/testcases/org/apache/tools/ant/taskdefs/ConcatTest.java
  69. +136
    -0
      src/testcases/org/apache/tools/ant/types/ResourceCollectionsTest.java
  70. +100
    -0
      src/testcases/org/apache/tools/ant/types/ResourceComparatorsTest.java
  71. +153
    -0
      src/testcases/org/apache/tools/ant/types/ResourceOutputTest.java
  72. +100
    -0
      src/testcases/org/apache/tools/ant/types/ResourceSelectorsTest.java
  73. +5
    -0
      src/testcases/org/apache/tools/ant/types/optional/depend/ClassFileSetTest.java

+ 600
- 0
docs/manual/CoreTypes/resources.html View File

@@ -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>&lt;resources&gt;</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>&lt;patternset&gt;</code>
elements. In addition, <code>&lt;files&gt;</code> holds an implicit
PatternSet and supports the nested <code>&lt;include&gt;</code>,
<code>&lt;includesfile&gt;</code>, <code>&lt;exclude&gt;</code>
and <code>&lt;excludesfile&gt;</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>&lt;files&gt;</code> is thus equivalent to an
<code>&lt;and&gt;</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 &copy; 2005 The Apache Software Foundation. All rights
Reserved.</p>

</body>
</html>

+ 2
- 0
docs/manual/conceptstypeslist.html View File

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


+ 27
- 0
src/etc/testcases/taskdefs/concat.xml View File

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

+ 24
- 0
src/etc/testcases/taskdefs/optional/depend/depend.xml View File

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


+ 450
- 0
src/etc/testcases/types/resources/build.xml View File

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

+ 326
- 0
src/etc/testcases/types/resources/comparators/build.xml View File

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

+ 410
- 0
src/etc/testcases/types/resources/selectors/build.xml View File

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

+ 196
- 256
src/main/org/apache/tools/ant/taskdefs/Concat.java View File

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


+ 53
- 66
src/main/org/apache/tools/ant/taskdefs/Length.java View File

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


+ 52
- 40
src/main/org/apache/tools/ant/taskdefs/PathConvert.java View File

@@ -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.");
}



+ 124
- 0
src/main/org/apache/tools/ant/taskdefs/ResourceCount.java View File

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

}

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

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


+ 93
- 0
src/main/org/apache/tools/ant/types/Comparison.java View File

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

}


+ 39
- 1
src/main/org/apache/tools/ant/types/DirSet.java View File

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

}

+ 44
- 22
src/main/org/apache/tools/ant/types/FileList.java View File

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

}

+ 39
- 1
src/main/org/apache/tools/ant/types/FileSet.java View File

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

}

+ 55
- 212
src/main/org/apache/tools/ant/types/Path.java View File

@@ -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>&lt;pathelement&gt;</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 &quot;last&quot; as
@@ -737,4 +579,5 @@ public class Path extends DataType implements Cloneable {
}
}
}

}

+ 39
- 1
src/main/org/apache/tools/ant/types/PropertySet.java View File

@@ -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();
}

}

+ 226
- 20
src/main/org/apache/tools/ant/types/Resource.java View File

@@ -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 {
* &quot;/&quot; 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);
}

}

+ 49
- 0
src/main/org/apache/tools/ant/types/ResourceCollection.java View File

@@ -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();

}

+ 78
- 19
src/main/org/apache/tools/ant/types/ZipFileSet.java View File

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


+ 137
- 53
src/main/org/apache/tools/ant/types/ZipScanner.java View File

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

}

+ 25
- 8
src/main/org/apache/tools/ant/types/defaults.properties View File

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

+ 223
- 0
src/main/org/apache/tools/ant/types/resources/BaseResourceCollectionContainer.java View File

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

}

+ 67
- 0
src/main/org/apache/tools/ant/types/resources/Difference.java View File

@@ -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();
}

}

+ 132
- 0
src/main/org/apache/tools/ant/types/resources/FailFast.java View File

@@ -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();
}

}


+ 300
- 0
src/main/org/apache/tools/ant/types/resources/FileResource.java View File

@@ -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();
}

}

+ 108
- 0
src/main/org/apache/tools/ant/types/resources/FileResourceIterator.java View File

@@ -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++]);
}

}

+ 503
- 0
src/main/org/apache/tools/ant/types/resources/Files.java View File

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

}

+ 44
- 0
src/main/org/apache/tools/ant/types/resources/ImmutableResourceException.java View File

@@ -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);
}

}

+ 62
- 0
src/main/org/apache/tools/ant/types/resources/Intersect.java View File

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

+ 133
- 0
src/main/org/apache/tools/ant/types/resources/PropertyResource.java View File

@@ -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());
}

}

+ 187
- 0
src/main/org/apache/tools/ant/types/resources/Resources.java View File

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

}

+ 137
- 0
src/main/org/apache/tools/ant/types/resources/Restrict.java View File

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

}

+ 107
- 0
src/main/org/apache/tools/ant/types/resources/Sort.java View File

@@ -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);
}
}

}

+ 204
- 0
src/main/org/apache/tools/ant/types/resources/StringResource.java View File

@@ -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);
}

}

+ 26
- 0
src/main/org/apache/tools/ant/types/resources/Touchable.java View File

@@ -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);
}

+ 373
- 0
src/main/org/apache/tools/ant/types/resources/URLResource.java View File

@@ -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);
}
}

}

+ 85
- 0
src/main/org/apache/tools/ant/types/resources/Union.java View File

@@ -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();
}
}


+ 299
- 0
src/main/org/apache/tools/ant/types/resources/ZipResource.java View File

@@ -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());
}

}

+ 69
- 0
src/main/org/apache/tools/ant/types/resources/comparators/Content.java View File

@@ -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);
}
}

}

+ 37
- 0
src/main/org/apache/tools/ant/types/resources/comparators/Date.java View File

@@ -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());
}

}

+ 42
- 0
src/main/org/apache/tools/ant/types/resources/comparators/Exists.java View File

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

}

+ 37
- 0
src/main/org/apache/tools/ant/types/resources/comparators/Name.java View File

@@ -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());
}

}

+ 62
- 0
src/main/org/apache/tools/ant/types/resources/comparators/ResourceComparator.java View File

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

}

+ 56
- 0
src/main/org/apache/tools/ant/types/resources/comparators/Reverse.java View File

@@ -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));
}

}

+ 37
- 0
src/main/org/apache/tools/ant/types/resources/comparators/Size.java View File

@@ -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());
}

}

+ 43
- 0
src/main/org/apache/tools/ant/types/resources/comparators/Type.java View File

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

}

+ 43
- 0
src/main/org/apache/tools/ant/types/resources/selectors/And.java View File

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

}

+ 161
- 0
src/main/org/apache/tools/ant/types/resources/selectors/Date.java View File

@@ -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);
}

}

+ 36
- 0
src/main/org/apache/tools/ant/types/resources/selectors/Exists.java View File

@@ -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();
}

}

+ 129
- 0
src/main/org/apache/tools/ant/types/resources/selectors/InstanceOf.java View File

@@ -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());
}

}

+ 69
- 0
src/main/org/apache/tools/ant/types/resources/selectors/Majority.java View File

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

}

+ 76
- 0
src/main/org/apache/tools/ant/types/resources/selectors/Name.java View File

@@ -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);
}

}

+ 43
- 0
src/main/org/apache/tools/ant/types/resources/selectors/None.java View File

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

}

+ 65
- 0
src/main/org/apache/tools/ant/types/resources/selectors/Not.java View File

@@ -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));
}

}

+ 43
- 0
src/main/org/apache/tools/ant/types/resources/selectors/Or.java View File

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

}

+ 34
- 0
src/main/org/apache/tools/ant/types/resources/selectors/ResourceSelector.java View File

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

}

+ 111
- 0
src/main/org/apache/tools/ant/types/resources/selectors/ResourceSelectorContainer.java View File

@@ -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);
}
}

}

+ 72
- 0
src/main/org/apache/tools/ant/types/resources/selectors/Size.java View File

@@ -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)));
}

}

+ 67
- 0
src/main/org/apache/tools/ant/types/resources/selectors/Type.java View File

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

}

+ 143
- 0
src/main/org/apache/tools/ant/util/ConcatResourceInputStream.java View File

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

+ 292
- 170
src/main/org/apache/tools/ant/util/FileUtils.java View File

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


+ 69
- 0
src/main/org/apache/tools/ant/util/PropertyOutputStream.java View File

@@ -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);
}
}

}


+ 16
- 14
src/main/org/apache/tools/zip/ZipFile.java View File

@@ -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");


+ 16
- 0
src/resources/org/apache/tools/ant/types/resources/comparators/antlib.xml View File

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

+ 24
- 0
src/resources/org/apache/tools/ant/types/resources/selectors/antlib.xml View File

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

+ 5
- 0
src/testcases/org/apache/tools/ant/taskdefs/ConcatTest.java View File

@@ -275,4 +275,9 @@ public class ConcatTest
File f2 = getProject().resolveFile("concat.utf8");
assertTrue(FILE_UTILS.contentEquals(f1, f2));
}

public void testResources() {
executeTarget("testResources");
}

}

+ 136
- 0
src/testcases/org/apache/tools/ant/types/ResourceCollectionsTest.java View File

@@ -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");
}

}

+ 100
- 0
src/testcases/org/apache/tools/ant/types/ResourceComparatorsTest.java View File

@@ -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");
}

}

+ 153
- 0
src/testcases/org/apache/tools/ant/types/ResourceOutputTest.java View File

@@ -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);
}

}

+ 100
- 0
src/testcases/org/apache/tools/ant/types/ResourceSelectorsTest.java View File

@@ -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");
}

}

+ 5
- 0
src/testcases/org/apache/tools/ant/types/optional/depend/ClassFileSetTest.java View File

@@ -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");
}

}

Loading…
Cancel
Save