git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@278337 13f79535-47bb-0310-9956-ffa450edef68master
| @@ -0,0 +1,600 @@ | |||||
| <html> | |||||
| <head> | |||||
| <meta http-equiv="Content-Language" content="en-us"> | |||||
| <link rel="stylesheet" type="text/css" href="../stylesheets/style.css"> | |||||
| <title>Resources and Resource Collections</title> | |||||
| </head> | |||||
| <body> | |||||
| <h2><a name="resource">Resources</a></h2> | |||||
| <p> | |||||
| A file-like entity can be abstracted to the concept of a <i>resource</i>. | |||||
| In addition to providing access to file-like attributes, a resource | |||||
| implementation should, when possible, provide the means to read content | |||||
| from and/or write content to the underlying entity. Although the resource | |||||
| concept was introduced in <i>Ant 1.5.2</i>, resources are available for | |||||
| explicit use beginning in <b>Ant 1.7</b>. | |||||
| </p> | |||||
| <h3>The built-in resource types are:</h3> | |||||
| <ul> | |||||
| <li><a href="#basic">resource</a> - a basic resource.</li> | |||||
| <li><a href="#file">file</a> - a file.</li> | |||||
| <li><a href="#zipentry">zipentry</a> - an entry in a zip file.</li> | |||||
| <li><a href="#url">url</a> - a URL.</li> | |||||
| <li><a href="#string">string</a> - a text string.</li> | |||||
| <li><a href="#property">property</a> - an Ant property.</li> | |||||
| </ul> | |||||
| <h4><a name="basic">resource</a></h4> | |||||
| <p>A basic resource. Other resource types derive from this basic | |||||
| type; as such all its attributes are available, though in most cases | |||||
| irrelevant attributes will be ignored. This and all resource | |||||
| implementations are also usable as single-element | |||||
| <a href="#collection">Resource Collections</a>. | |||||
| </p> | |||||
| <table border="1" cellpadding="2" cellspacing="0"> | |||||
| <tr> | |||||
| <td valign="top"><b>Attribute</b></td> | |||||
| <td valign="top"><b>Description</b></td> | |||||
| <td align="center" valign="top"><b>Required</b></td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td valign="top">name</td> | |||||
| <td valign="top">The name of this resource</td> | |||||
| <td align="center" valign="top">No</td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td valign="top">exists</td> | |||||
| <td valign="top">Whether this resource exists</td> | |||||
| <td align="center" valign="top">No, default <i>true</i></td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td valign="top">lastmodified</td> | |||||
| <td valign="top">The last modification time of this resource</td> | |||||
| <td align="center" valign="top">No</td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td valign="top">directory</td> | |||||
| <td valign="top">Whether this resource is directory-like</td> | |||||
| <td align="center" valign="top">No, default <i>false</i></td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td valign="top">size</td> | |||||
| <td valign="top">The size of this resource</td> | |||||
| <td align="center" valign="top">No</td> | |||||
| </tr> | |||||
| </table> | |||||
| <h4><a name="file">file</a></h4> | |||||
| <p>Represents a file accessible via local filesystem conventions.</p> | |||||
| <table border="1" cellpadding="2" cellspacing="0"> | |||||
| <tr> | |||||
| <td valign="top"><b>Attribute</b></td> | |||||
| <td valign="top"><b>Description</b></td> | |||||
| <td align="center" valign="top"><b>Required</b></td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td valign="top">file</td> | |||||
| <td valign="top">The file represented by this resource</td> | |||||
| <td align="center" valign="top">Yes</td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td valign="top">base</td> | |||||
| <td valign="top">The base directory of this resource. When this | |||||
| attribute is set, attempts to access the name of the resource | |||||
| will yield a path relative to this location.</td> | |||||
| <td align="center" valign="top">No</td> | |||||
| </tr> | |||||
| </table> | |||||
| <h4><a name="zipentry">zipentry</a></h4> | |||||
| <p>Represents an entry in a ZIP archive.</p> | |||||
| <table border="1" cellpadding="2" cellspacing="0"> | |||||
| <tr> | |||||
| <td valign="top"><b>Attribute</b></td> | |||||
| <td valign="top"><b>Description</b></td> | |||||
| <td align="center" valign="top"><b>Required</b></td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td valign="top">zipfile</td> | |||||
| <td valign="top">The zip file containing this resource</td> | |||||
| <td align="center" valign="top">Yes</td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td valign="top">name</td> | |||||
| <td valign="top">The name of the archived resource</td> | |||||
| <td align="center" valign="top">Yes</td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td valign="top">encoding</td> | |||||
| <td valign="top">The encoding of the zipfile</td> | |||||
| <td align="center" valign="top">No; | |||||
| platform default used if unspecified</td> | |||||
| </tr> | |||||
| </table> | |||||
| <h4><a name="url">url</a></h4> | |||||
| <p>Represents a URL.</p> | |||||
| <table border="1" cellpadding="2" cellspacing="0"> | |||||
| <tr> | |||||
| <td valign="top"><b>Attribute</b></td> | |||||
| <td valign="top"><b>Description</b></td> | |||||
| <td align="center" valign="top"><b>Required</b></td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td valign="top">url</td> | |||||
| <td valign="top">The url to expose</td> | |||||
| <td rowspan="3" align="center" valign="middle">Exactly one of these</td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td valign="top">file</td> | |||||
| <td valign="top">The file to expose as a file: url</td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td valign="top">javaresource</td> | |||||
| <td valign="top">The Java resource to expose as a jar: url</td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td valign="top">classpath</td> | |||||
| <td valign="top">The classpath to use when establishing the URL | |||||
| for a Java resource</td> | |||||
| <td align="center" valign="top">No</td> | |||||
| </tr> | |||||
| </table> | |||||
| <p>The classpath along which to search for a Java resource | |||||
| can also be specified by means of one or more nested | |||||
| <code><a href="../using.html#path">classpath</a></code> elements. | |||||
| </p> | |||||
| <h4><a name="string">string</a></h4> | |||||
| <p>Represents a Java String. As such a string is readable but not writable.</p> | |||||
| <table border="1" cellpadding="2" cellspacing="0"> | |||||
| <tr> | |||||
| <td valign="top"><b>Attribute</b></td> | |||||
| <td valign="top"><b>Description</b></td> | |||||
| <td align="center" valign="top"><b>Required</b></td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td valign="top">value</td> | |||||
| <td valign="top">The value of this resource</td> | |||||
| <td align="center" valign="top">Yes</td> | |||||
| </tr> | |||||
| </table> | |||||
| <h4><a name="property">property</a></h4> | |||||
| <p>Represents an Ant property.</p> | |||||
| <table border="1" cellpadding="2" cellspacing="0"> | |||||
| <tr> | |||||
| <td valign="top"><b>Attribute</b></td> | |||||
| <td valign="top"><b>Description</b></td> | |||||
| <td align="center" valign="top"><b>Required</b></td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td valign="top">name</td> | |||||
| <td valign="top">The property name</td> | |||||
| <td align="center" valign="top">Yes</td> | |||||
| </tr> | |||||
| </table> | |||||
| <hr> | |||||
| <h2><a name="collection">Resource Collections</a></h2> | |||||
| <p> | |||||
| A Resource Collection is an abstraction of an entity that groups | |||||
| together a number of <a href="#resource">resources</a>. Several of | |||||
| Ant's "legacy" datatypes have been modified to behave as Resource Collections: | |||||
| <ul> | |||||
| <li><a href="fileset.html">fileset</a>, | |||||
| <a href="dirset.html">dirset</a>, | |||||
| <a href="filelist.html">filelist</a>, and | |||||
| <a href="../using.html#path">path</a> | |||||
| (and derivative types) expose <a href="#file">file</a> resources | |||||
| </li> | |||||
| <li><a href="zipfileset.html">zipfileset</a> | |||||
| can expose <a href="#file">file</a> or <a href="#zipentry">zipentry</a> | |||||
| resources depending on configuration | |||||
| </li> | |||||
| <li><a href="propertyset.html">propertyset</a> | |||||
| exposes <a href="#property">property</a> resources | |||||
| </li> | |||||
| </ul> | |||||
| </p> | |||||
| <h3>The additional built-in resource collections are:</h3> | |||||
| <ul> | |||||
| <li><a href="#resources">resources</a> - generic resource collection</li> | |||||
| <li><a href="#files">files</a> - collection of files similar to | |||||
| <a href="fileset.html">fileset</a></li> | |||||
| <li><a href="#restrict">restrict</a> - restrict a resource collection | |||||
| to include only resources meeting specified criteria</li> | |||||
| <li><a href="#sort">sort</a> - sorted resource collection</li> | |||||
| <li><a href="#union">union</a> - set union of nested resource collections</li> | |||||
| <li><a href="#intersect">intersect</a> - set intersection | |||||
| of nested resource collections</li> | |||||
| <li><a href="#difference">difference</a> - set difference | |||||
| of nested resource collections</li> | |||||
| </ul> | |||||
| <h4><a name="resources">resources</a></h4> | |||||
| <p>A generic resource collection, designed for use with | |||||
| <a href="../using.html#references">references</a>. | |||||
| For example, if a third-party Ant task generates a Resource Collection | |||||
| of an unknown type, it can still be accessed via a | |||||
| <code><resources></code> collection. The secondary use of this | |||||
| collection type is as a container of other resource collections, | |||||
| preserving the order of nested collections as well as | |||||
| duplicate resources (contrast with <a href="#union">union</a>). | |||||
| </p> | |||||
| <h4><a name="files">files</a></h4> | |||||
| <p>A group of files. These files are matched by <b>absolute</b> patterns | |||||
| taken from a number of <a href="patternset.html">PatternSets</a>. | |||||
| These can be specified as nested <code><patternset></code> | |||||
| elements. In addition, <code><files></code> holds an implicit | |||||
| PatternSet and supports the nested <code><include></code>, | |||||
| <code><includesfile></code>, <code><exclude></code> | |||||
| and <code><excludesfile></code> elements of PatternSet directly, | |||||
| as well as PatternSet's attributes. | |||||
| </p> | |||||
| <p><a href="selectors.html">File Selectors</a> are available as nested | |||||
| elements. A file must be selected by all selectors in order to be included; | |||||
| <code><files></code> is thus equivalent to an | |||||
| <code><and></code> file selector container. | |||||
| </p> | |||||
| <p><b>More simply put</b>, this type is equivalent to a | |||||
| <a href="fileset.html">fileset</a> with no base directory. | |||||
| <b>Please note</b> that without a base directory, | |||||
| filesystem scanning is based entirely on include and exclude patterns. | |||||
| A <a href="selectors.html#filenameselect">filename</a> (or any) | |||||
| selector can <i>only</i> influence the scanning process <i>after</i> | |||||
| the file has been included based on pattern-based selection. | |||||
| </p> | |||||
| <table border="1" cellpadding="2" cellspacing="0"> | |||||
| <tr> | |||||
| <td valign="top"><b>Attribute</b></td> | |||||
| <td valign="top"><b>Description</b></td> | |||||
| <td align="center" valign="top"><b>Required</b></td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td valign="top">includes</td> | |||||
| <td valign="top">comma- or space-separated list of patterns | |||||
| of files that must be included</td> | |||||
| <td rowspan="2" valign="middle" align="center">At least one of these</td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td valign="top">includesfile</td> | |||||
| <td valign="top">the name of a file; each line of this file is | |||||
| taken to be an include pattern.</td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td valign="top">excludes</td> | |||||
| <td valign="top">comma- or space-separated list of patterns | |||||
| of files that must be excluded</td> | |||||
| <td rowspan="2" valign="top" align="center">No, default none | |||||
| (except default excludes when true)</td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td valign="top">excludesfile</td> | |||||
| <td valign="top">the name of a file; each line of this file is | |||||
| taken to be an exclude pattern.</td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td valign="top">defaultexcludes</td> | |||||
| <td valign="top">Whether | |||||
| <a href="../dirtasks.html#defaultexcludes">default excludes</a> | |||||
| should be used</td> | |||||
| <td valign="top" align="center">No, default <i>true</i></td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td valign="top">casesensitive</td> | |||||
| <td valign="top">Whether patterns are case-sensitive</td> | |||||
| <td valign="top" align="center">No, default <i>true</i></td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td valign="top">followsymlinks</td> | |||||
| <td valign="top">Whether to follow symbolic links | |||||
| (see note <a href="#symlink">below</a>)</td> | |||||
| <td valign="top" align="center">No, default <i>true</i></td> | |||||
| </tr> | |||||
| </table> | |||||
| <p><a name="symlink"><b>Note</b></a>: All files/directories for which | |||||
| the canonical path is different from its path are considered symbolic | |||||
| links. On Unix systems this usually means the file really is a | |||||
| symbolic link but it may lead to false results on other | |||||
| platforms. | |||||
| </p> | |||||
| <h4><a name="restrict">restrict</a></h4> | |||||
| <p>Restricts another nested resource collection using resource selectors: | |||||
| <blockquote> | |||||
| <h4>Parameters specified as nested elements</h4> | |||||
| <p>A single resource collection is required.</p> | |||||
| <p>Nested resource selectors are used to "narrow down" the included | |||||
| resources. These are patterned after <a href="selectors.html">file | |||||
| selectors</a> but are, unsurprisingly, targeted to resources. | |||||
| Several built-in resource selectors are available in the internal | |||||
| <a href="antlib.html">antlib</a> | |||||
| <code>org.apache.tools.ant.types.resources.selectors</code>: | |||||
| </p> | |||||
| <ul> | |||||
| <li><a href="#rsel.name">name</a> - select resources by name.</li> | |||||
| <li><a href="#rsel.exists">exists</a> - select existing resources.</li> | |||||
| <li><a href="#rsel.date">date</a> - select resources by date.</li> | |||||
| <li><a href="#rsel.type">type</a> - select resources by type.</li> | |||||
| <li><a href="#rsel.size">size</a> - select resources by size.</li> | |||||
| <li><a href="#rsel.instanceof">instanceof</a> | |||||
| - select resources by class or Ant datatype.</li> | |||||
| <li><a href="#rsel.and">and</a> - "and" nested resource selectors.</li> | |||||
| <li><a href="#rsel.or">or</a> - "or" nested resource selectors.</li> | |||||
| <li><a href="#rsel.not">not</a> - "not" a nested resource selector.</li> | |||||
| <li><a href="#rsel.none">none</a> | |||||
| - select resources selected by no nested resource selectors.</li> | |||||
| <li><a href="#rsel.majority">majority</a> - select resources selected | |||||
| by a majority of nested resource selectors.</li> | |||||
| </ul> | |||||
| <h4><a name="rsel.name">name</a></h4> | |||||
| <p>Selects resources by name.</p> | |||||
| <table border="1" cellpadding="2" cellspacing="0"> | |||||
| <tr> | |||||
| <td valign="top"><b>Attribute</b></td> | |||||
| <td valign="top"><b>Description</b></td> | |||||
| <td align="center" valign="top"><b>Required</b></td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td valign="top">name</td> | |||||
| <td valign="top">The name pattern to test</td> | |||||
| <td align="center" valign="top">Yes</td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td valign="top">casesensitive</td> | |||||
| <td valign="top">Whether name comparisons are case-sensitive</td> | |||||
| <td align="center" valign="top">No, default <i>true</i></td> | |||||
| </tr> | |||||
| </table> | |||||
| <h4><a name="rsel.exists">exists</a></h4> | |||||
| <p>Selects existing resources.</p> | |||||
| <h4><a name="rsel.date">date</a></h4> | |||||
| <p>Selects resources by date.</p> | |||||
| <table border="1" cellpadding="2" cellspacing="0"> | |||||
| <tr> | |||||
| <td valign="top"><b>Attribute</b></td> | |||||
| <td valign="top"><b>Description</b></td> | |||||
| <td align="center" valign="top"><b>Required</b></td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td valign="top">millis</td> | |||||
| <td valign="top">The comparison date/time in ms since January 1, 1970</td> | |||||
| <td rowspan="2" align="center" valign="middle">One of these</td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td valign="top">datetime</td> | |||||
| <td valign="top">The formatted comparison date/time</td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td valign="top">pattern</td> | |||||
| <td valign="top">SimpleDateFormat-compatible pattern | |||||
| for use with the <code>datetime</code> attribute</td> | |||||
| <td align="center" valign="top"> | |||||
| No, default is "MM/DD/YYYY HH:MM AM_or_PM"</td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td valign="top">granularity</td> | |||||
| <td valign="top">The number of milliseconds leeway to use when | |||||
| comparing file modification times. This is needed because not | |||||
| every file system supports tracking the last modified time to | |||||
| the millisecond level.</td> | |||||
| <td align="center" valign="top">No; default varies by platform: | |||||
| FAT filesystems = 2 sec; Unix = 1 sec; NTFS = 1 ms.</td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td valign="top">when</td> | |||||
| <td valign="top">One of "before", "after", "equal"</td> | |||||
| <td align="center" valign="top">No, default "equal"</td> | |||||
| </tr> | |||||
| </table> | |||||
| <h4><a name="rsel.type">type</a></h4> | |||||
| <p>Selects resources by type (file or directory).</p> | |||||
| <table border="1" cellpadding="2" cellspacing="0"> | |||||
| <tr> | |||||
| <td valign="top"><b>Attribute</b></td> | |||||
| <td valign="top"><b>Description</b></td> | |||||
| <td align="center" valign="top"><b>Required</b></td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td valign="top">type</td> | |||||
| <td valign="top">One of "file", "dir"</td> | |||||
| <td align="center" valign="top">Yes</td> | |||||
| </tr> | |||||
| </table> | |||||
| <h4><a name="rsel.size">size</a></h4> | |||||
| <p>Selects resources by size.</p> | |||||
| <table border="1" cellpadding="2" cellspacing="0"> | |||||
| <tr> | |||||
| <td valign="top"><b>Attribute</b></td> | |||||
| <td valign="top"><b>Description</b></td> | |||||
| <td align="center" valign="top"><b>Required</b></td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td valign="top">size</td> | |||||
| <td valign="top">The size to compare</td> | |||||
| <td align="center" valign="top">Yes</td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td valign="top">when</td> | |||||
| <td valign="top">One of "equal", "eq", "greater", "gt", "less", "lt", | |||||
| "ge" (greater or equal), "ne" (not equal), "le" (less or equal)</td> | |||||
| <td align="center" valign="top">No, default "equal"</td> | |||||
| </tr> | |||||
| </table> | |||||
| <h4><a name="rsel.instanceof">instanceof</a></h4> | |||||
| <p>Selects resources by type.</p> | |||||
| <table border="1" cellpadding="2" cellspacing="0"> | |||||
| <tr> | |||||
| <td valign="top"><b>Attribute</b></td> | |||||
| <td valign="top"><b>Description</b></td> | |||||
| <td align="center" valign="top"><b>Required</b></td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td valign="top">class</td> | |||||
| <td valign="top">The class of which the resource must be an instance</td> | |||||
| <td rowspan="2" align="center" valign="middle">One of these</td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td valign="top">type</td> | |||||
| <td valign="top">The Ant type that must | |||||
| be assignable from the resource</td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td valign="top">uri</td> | |||||
| <td valign="top">The uri in which <i>type</i> must be defined</td> | |||||
| <td valign="top">No</td> | |||||
| </tr> | |||||
| </table> | |||||
| <h4><a name="rsel.and">and</a></h4> | |||||
| <p>Selects a resource if it is selected by all nested resource selectors.</p> | |||||
| <h4><a name="rsel.or">or</a></h4> | |||||
| <p>Selects a resource if it is selected | |||||
| by at least one nested resource selector.</p> | |||||
| <h4><a name="rsel.not">not</a></h4> | |||||
| <p>Negates the selection result of the single | |||||
| nested resource selector allowed.</p> | |||||
| <h4><a name="rsel.none">none</a></h4> | |||||
| <p>Selects a resource if it is selected | |||||
| by no nested resource selectors.</p> | |||||
| <h4><a name="rsel.majority">majority</a></h4> | |||||
| <p>Selects a resource if it is selected | |||||
| by the majority of nested resource selectors.</p> | |||||
| <table border="1" cellpadding="2" cellspacing="0"> | |||||
| <tr> | |||||
| <td valign="top"><b>Attribute</b></td> | |||||
| <td valign="top"><b>Description</b></td> | |||||
| <td align="center" valign="top"><b>Required</b></td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td valign="top">allowtie</td> | |||||
| <td valign="top">Whether a tie (when there is an even number | |||||
| of nested resource selectors) is considered a majority</td> | |||||
| <td valign="top">No, default <i>true</i></td> | |||||
| </tr> | |||||
| </table> | |||||
| </blockquote> | |||||
| <h4><a name="sort">sort</a></h4> | |||||
| <p>Sorts another nested resource collection according to the resources' | |||||
| natural order, or by one or more nested resource comparators:</p> | |||||
| <blockquote> | |||||
| <h4>Parameters specified as nested elements</h4> | |||||
| <p>A single resource collection is required.</p> | |||||
| <p>The sort can be controlled and customized by specifying one or more | |||||
| resource comparators. Resources can be sorted according to multiple | |||||
| criteria; the first specified is the "outermost", while the last | |||||
| specified is the "innermost". Several built-in resource comparators | |||||
| are available in the internal <a href="antlib.html">antlib</a> | |||||
| <code>org.apache.tools.ant.types.resources.comparators</code>: | |||||
| </p> | |||||
| <ul> | |||||
| <li><a href="#rcmp.name">name</a> - sort resources by name</li> | |||||
| <li><a href="#rcmp.exists">exists</a> - sort resources by existence</li> | |||||
| <li><a href="#rcmp.date">date</a> - sort resources by date</li> | |||||
| <li><a href="#rcmp.type">type</a> - sort resources by type</li> | |||||
| <li><a href="#rcmp.size">size</a> - sort resources by size</li> | |||||
| <li><a href="#rcmp.content">content</a> - sort resources by content</li> | |||||
| <li><a href="#rcmp.reverse">reverse</a> - reverse the natural sort order, | |||||
| or a single nested resource comparator</li> | |||||
| </ul> | |||||
| <h4><a name="rcmp.name">name</a></h4> | |||||
| <p>Sort resources by name.</p> | |||||
| <h4><a name="rcmp.exists">exists</a></h4> | |||||
| <p>Sort resources by existence. | |||||
| Not existing is considered "less than" existing.</p> | |||||
| <h4><a name="rcmp.date">date</a></h4> | |||||
| <p>Sort resources by date.</p> | |||||
| <h4><a name="rcmp.type">type</a></h4> | |||||
| <p>Sort resources by type (file or directory). | |||||
| Because directories contain files, they are considered "greater".</p> | |||||
| <h4><a name="rcmp.size">size</a></h4> | |||||
| <p>Sort resources by size.</p> | |||||
| <h4><a name="rcmp.content">content</a></h4> | |||||
| <p>Sort resources by content.</p> | |||||
| <table border="1" cellpadding="2" cellspacing="0"> | |||||
| <tr> | |||||
| <td valign="top"><b>Attribute</b></td> | |||||
| <td valign="top"><b>Description</b></td> | |||||
| <td align="center" valign="top"><b>Required</b></td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td valign="top">binary</td> | |||||
| <td valign="top">Whether content should be compared in binary mode. | |||||
| If <i>false<i>, content will be compared without regard to | |||||
| platform-specific line-ending conventions.</td> | |||||
| <td valign="top">No, default <i>true</i></td> | |||||
| </tr> | |||||
| </table> | |||||
| <h4><a name="rcmp.reverse">reverse</a></h4> | |||||
| <p>Reverse the natural sort order, or a single nested comparator.</p> | |||||
| </blockquote> | |||||
| <h4><a name="setlogic">Set operations</a></h4> | |||||
| <blockquote> | |||||
| <p>The following resource collections implement set operations:</p> | |||||
| <ul> | |||||
| <li><a href="#union">union</a></li> | |||||
| <li><a href="#intersect">intersect</a></li> | |||||
| <li><a href="#difference">difference</a></li> | |||||
| </ul> | |||||
| <h4><a name="union">union</a></h4> | |||||
| <p>Union of nested resource collections.</p> | |||||
| <h4><a name="intersect">intersect</a></h4> | |||||
| <p>Intersection of nested resource collections.</p> | |||||
| <h4><a name="difference">difference</a></h4> | |||||
| <p>Difference of nested resource collections.</p> | |||||
| </blockquote> | |||||
| <hr> | |||||
| <p align="center">Copyright © 2005 The Apache Software Foundation. All rights | |||||
| Reserved.</p> | |||||
| </body> | |||||
| </html> | |||||
| @@ -31,6 +31,8 @@ | |||||
| <a href="CoreTypes/propertyset.html">PropertySet</a><br> | <a href="CoreTypes/propertyset.html">PropertySet</a><br> | ||||
| <a href="CoreTypes/redirector.html">I/O Redirectors</a><br> | <a href="CoreTypes/redirector.html">I/O Redirectors</a><br> | ||||
| <a href="CoreTypes/regexp.html">Regexp</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/selectors.html">Selectors</a><br> | ||||
| <a href="CoreTypes/xmlcatalog.html">XMLCatalog</a><br> | <a href="CoreTypes/xmlcatalog.html">XMLCatalog</a><br> | ||||
| <a href="CoreTypes/zipfileset.html">ZipFileSet</a><br> | <a href="CoreTypes/zipfileset.html">ZipFileSet</a><br> | ||||
| @@ -15,6 +15,7 @@ | |||||
| <delete file="concat.noeol"/> | <delete file="concat.noeol"/> | ||||
| <delete file="concat.linecr"/> | <delete file="concat.linecr"/> | ||||
| <delete file="concat.utf8"/> | <delete file="concat.utf8"/> | ||||
| <delete file="concat.urls"/> | |||||
| </target> | </target> | ||||
| <target name="test1"> | <target name="test1"> | ||||
| @@ -185,4 +186,30 @@ | |||||
| </concat> | </concat> | ||||
| </target> | </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> | </project> | ||||
| @@ -82,6 +82,30 @@ | |||||
| <classfileset id="result" dir="${classes.dir}" rootclass="B"/> | <classfileset id="result" dir="${classes.dir}" rootclass="B"/> | ||||
| </target> | </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"> | <target name="testcomboset" depends="src1setup, compile"> | ||||
| <classfileset id="result" dir="${classes.dir}" rootclass="B"> | <classfileset id="result" dir="${classes.dir}" rootclass="B"> | ||||
| <include name="**/C.class"/> | <include name="**/C.class"/> | ||||
| @@ -0,0 +1,450 @@ | |||||
| <project default="all" | |||||
| xmlns:rsel="antlib:org.apache.tools.ant.types.resources.selectors"> | |||||
| <property name="dirname" value="work" /> | |||||
| <property name="dir" location="${dirname}" /> | |||||
| <property name="zip" location="${dirname}.zip" /> | |||||
| <property name="jar" location="${dirname}.jar" /> | |||||
| <property name="file" location="${dirname}/file.txt" /> | |||||
| <target name="init"> | |||||
| <touch mkdirs="true"> | |||||
| <filelist dir="${dir}/foo/a" files="x,y,z" /> | |||||
| </touch> | |||||
| <copy todir="${dir}/foo" enablemultiplemappings="true"> | |||||
| <fileset dir="${dir}/foo" /> | |||||
| <mapper> | |||||
| <globmapper handledirsep="true" from="a/*" to="b/*" /> | |||||
| <globmapper handledirsep="true" from="a/*" to="c/*" /> | |||||
| </mapper> | |||||
| </copy> | |||||
| <copy todir="${dir}/bar"> | |||||
| <fileset dir="${dir}/foo" /> | |||||
| </copy> | |||||
| <property name="foo" location="${dir}/foo" /> | |||||
| <property name="foo.a" location="${dir}/foo/a" /> | |||||
| <property name="foo.b" location="${dir}/foo/b" /> | |||||
| <property name="foo.c" location="${dir}/foo/c" /> | |||||
| <property name="bar" location="${dir}/bar" /> | |||||
| <property name="bar.a" location="${dir}/bar/a" /> | |||||
| <property name="bar.b" location="${dir}/bar/b" /> | |||||
| <property name="bar.c" location="${dir}/bar/c" /> | |||||
| </target> | |||||
| <target name="tearDown"> | |||||
| <delete dir="${dir}" /> | |||||
| <delete file="${zip}" /> | |||||
| <delete file="${jar}" deleteonexit="true" /> | |||||
| <delete file="${file}" /> | |||||
| </target> | |||||
| <target name="testfiles1" depends="init"> | |||||
| <fail> | |||||
| <condition> | |||||
| <not> | |||||
| <resourcecount count="26"> | |||||
| <files> | |||||
| <include name="${dir}/foo/" /> | |||||
| <include name="${dir}/bar/" /> | |||||
| </files> | |||||
| </resourcecount> | |||||
| </not> | |||||
| </condition> | |||||
| </fail> | |||||
| </target> | |||||
| <target name="testfiles2" depends="init"> | |||||
| <fail> | |||||
| <condition> | |||||
| <not> | |||||
| <resourcecount count="8"> | |||||
| <files> | |||||
| <include name="${dir}/foo/" /> | |||||
| <include name="${dir}/bar/" /> | |||||
| <type type="dir" /> | |||||
| </files> | |||||
| </resourcecount> | |||||
| </not> | |||||
| </condition> | |||||
| </fail> | |||||
| </target> | |||||
| <target name="testfiles3" depends="init"> | |||||
| <fail> | |||||
| <condition> | |||||
| <not> | |||||
| <resourcecount count="18"> | |||||
| <files> | |||||
| <include name="${dir}/foo/" /> | |||||
| <include name="${dir}/bar/" /> | |||||
| <type type="file" /> | |||||
| </files> | |||||
| </resourcecount> | |||||
| </not> | |||||
| </condition> | |||||
| </fail> | |||||
| </target> | |||||
| <target name="files" depends="testfiles1,testfiles2,testfiles3" /> | |||||
| <target name="testnestedresources" depends="init"> | |||||
| <fail> | |||||
| <condition> | |||||
| <not> | |||||
| <resourcecount count="27"><!-- include duplicates! --> | |||||
| <resources> | |||||
| <files> | |||||
| <include name="${dir}/foo/" /> | |||||
| <include name="${dir}/bar/" /> | |||||
| <type type="file" /> | |||||
| </files> | |||||
| <files> | |||||
| <include name="${dir}/foo/" /> | |||||
| <type type="file" /> | |||||
| </files> | |||||
| </resources> | |||||
| </resourcecount> | |||||
| </not> | |||||
| </condition> | |||||
| </fail> | |||||
| </target> | |||||
| <target name="testresourcesref" depends="init"> | |||||
| <files id="files"> | |||||
| <include name="${dir}/foo/" /> | |||||
| <include name="${dir}/bar/" /> | |||||
| <type type="file" /> | |||||
| </files> | |||||
| <fail> | |||||
| <condition> | |||||
| <not> | |||||
| <resourcecount count="18"> | |||||
| <resources refid="files" /> | |||||
| </resourcecount> | |||||
| </not> | |||||
| </condition> | |||||
| </fail> | |||||
| </target> | |||||
| <target name="resources" depends="testnestedresources,testresourcesref" /> | |||||
| <target name="testfileset" depends="init"> | |||||
| <fail> | |||||
| <condition> | |||||
| <not> | |||||
| <resourcecount count="9"> | |||||
| <fileset dir="${dir}/foo" /> | |||||
| </resourcecount> | |||||
| </not> | |||||
| </condition> | |||||
| </fail> | |||||
| </target> | |||||
| <target name="testdirset" depends="init"> | |||||
| <fail> | |||||
| <condition> | |||||
| <not> | |||||
| <resourcecount count="4"> | |||||
| <dirset dir="${dir}/foo" /> | |||||
| </resourcecount> | |||||
| </not> | |||||
| </condition> | |||||
| </fail> | |||||
| </target> | |||||
| <target name="testfilelist"> | |||||
| <fail> | |||||
| <condition> | |||||
| <not> | |||||
| <resourcecount count="5"> | |||||
| <filelist dir="${dir}/foo" files="1,2,3,4,5" /> | |||||
| </resourcecount> | |||||
| </not> | |||||
| </condition> | |||||
| </fail> | |||||
| </target> | |||||
| <target name="testpath" depends="init"> | |||||
| <fail> | |||||
| <condition> | |||||
| <not> | |||||
| <resourcecount count="24"> | |||||
| <path> | |||||
| <path id="p"> | |||||
| <fileset id="fs" dir="${foo.a}" /> <!-- 3 --> | |||||
| <dirset id="ds" dir="${foo}" /> <!-- 4 --> | |||||
| </path> | |||||
| <pathelement id="pe" location="${dir}" /> <!-- 1 --> | |||||
| <filelist id="fl" dir="${bar}" files="1,2,3,a,b,c" /> <!-- 6 --> | |||||
| <files id="f" includes="${bar}/" /> <!-- 13; 3 overlap fl --> | |||||
| </path> | |||||
| </resourcecount> | |||||
| </not> | |||||
| </condition> | |||||
| </fail> | |||||
| </target> | |||||
| <target name="createzip" depends="init"> | |||||
| <zip destfile="${zip}" basedir="${dir}" /> | |||||
| </target> | |||||
| <target name="testzipfileset" depends="createzip"> | |||||
| <fail> | |||||
| <condition> | |||||
| <not> | |||||
| <resourcecount count="9"> | |||||
| <zipfileset src="${zip}" includes="foo/" /> | |||||
| </resourcecount> | |||||
| </not> | |||||
| </condition> | |||||
| </fail> | |||||
| </target> | |||||
| <target name="testpropertyset"> | |||||
| <property name="testpropertyset.a" value="a" /> | |||||
| <property name="testpropertyset.aa" value="aa" /> | |||||
| <property name="testpropertyset.aaa" value="aaa" /> | |||||
| <propertyset id="testpropertyset"> | |||||
| <propertyref prefix="testpropertyset." /> | |||||
| </propertyset> | |||||
| <fail> | |||||
| <condition> | |||||
| <not> | |||||
| <and> | |||||
| <resourcecount refid="testpropertyset" count="3" /> | |||||
| <length length="12"> | |||||
| <resources> | |||||
| <resources refid="testpropertyset" /> | |||||
| <propertyset refid="testpropertyset" /> | |||||
| </resources> | |||||
| </length> | |||||
| </and> | |||||
| </not> | |||||
| </condition> | |||||
| </fail> | |||||
| </target> | |||||
| <target name="legacy" | |||||
| depends="testfileset,testdirset,testfilelist,testpath,testzipfileset,testpropertyset" /> | |||||
| <target name="testunion" depends="init"> | |||||
| <fail> | |||||
| <condition> | |||||
| <not> | |||||
| <resourcecount count="4"> | |||||
| <union> | |||||
| <files includes="${foo.a}/w,${foo.a}/x" /> <!-- 1 --> | |||||
| <fileset dir="${foo.a}" includes="x,y" /> <!-- 2; net 1 --> | |||||
| <filelist dir="${foo.a}" files="v" /> <!-- 1 --> | |||||
| <files includes="${foo.a}/y,${foo.a}/z" /> <!-- 2; net 1 --> | |||||
| </union> | |||||
| </resourcecount> | |||||
| </not> | |||||
| </condition> | |||||
| </fail> | |||||
| </target> | |||||
| <target name="testintersect"> | |||||
| <fail> | |||||
| <condition> | |||||
| <not> | |||||
| <resourcecount count="3"> | |||||
| <intersect> | |||||
| <filelist dir="${dir}" files="1,2,3,4,5" /> | |||||
| <filelist dir="${dir}" files="2,3,4,5,6" /> | |||||
| <filelist dir="${dir}" files="3,4,5,6,7" /> | |||||
| </intersect> | |||||
| </resourcecount> | |||||
| </not> | |||||
| </condition> | |||||
| </fail> | |||||
| </target> | |||||
| <target name="testdifference"> | |||||
| <fail> | |||||
| <condition> | |||||
| <not> | |||||
| <resourcecount count="2"> | |||||
| <difference id="diff"> | |||||
| <filelist dir="${dir}" files="1,2,3,4,5" /> | |||||
| <filelist dir="${dir}" files="2,3,4,5,6" /> | |||||
| <filelist dir="${dir}" files="3,4,5,6,7" /> | |||||
| </difference> | |||||
| </resourcecount> | |||||
| </not> | |||||
| </condition> | |||||
| </fail> | |||||
| </target> | |||||
| <target name="setlogic" depends="testunion,testintersect,testdifference" /> | |||||
| <target name="testfileurl"> | |||||
| <condition property="blah"> | |||||
| <length when="less" length="1"> | |||||
| <url file="${ant.file}" /> | |||||
| </length> | |||||
| </condition> | |||||
| <fail if="blah" /> | |||||
| </target> | |||||
| <target name="testfileurlref"> | |||||
| <url id="fileurl" file="${ant.file}" /> | |||||
| <condition property="blah"> | |||||
| <length when="less" length="1"> | |||||
| <url refid="fileurl" /> | |||||
| </length> | |||||
| </condition> | |||||
| <fail if="blah" /> | |||||
| </target> | |||||
| <target name="testhttpurl1" unless="offline"> | |||||
| <fail> | |||||
| <condition> | |||||
| <length when="less" length="1"> | |||||
| <url url="http://ant.apache.org/index.html" /> | |||||
| </length> | |||||
| </condition> | |||||
| </fail> | |||||
| </target> | |||||
| <target name="testhttpurl2" unless="offline"> | |||||
| <concat destfile="${file}" force="true" append="false"> | |||||
| <url id="httpurl" url="http://ant.apache.org/index.html" /> | |||||
| <url refid="httpurl" /> | |||||
| </concat> | |||||
| <length property="httpurl.length"> | |||||
| <url refid="httpurl" /> | |||||
| </length> | |||||
| <fail> | |||||
| <condition> | |||||
| <not> | |||||
| <length file="${file}" when="greater" length="${httpurl.length}" /> | |||||
| </not> | |||||
| </condition> | |||||
| </fail> | |||||
| </target> | |||||
| <target name="createjar" depends="init"> | |||||
| <jar destfile="${jar}" basedir="${dir}" /> | |||||
| </target> | |||||
| <target name="testjarurl" depends="createjar"> | |||||
| <pathconvert property="jarurl"> | |||||
| <url file="${jar}" /> | |||||
| </pathconvert> | |||||
| <fail> | |||||
| <condition> | |||||
| <length when="less" length="1"> | |||||
| <url url="jar:${jarurl}!/META-INF/MANIFEST.MF" /> | |||||
| </length> | |||||
| </condition> | |||||
| </fail> | |||||
| </target> | |||||
| <target name="testresourceurl" depends="createjar"> | |||||
| <!-- test ref while we're at it --> | |||||
| <url id="resourceurl" | |||||
| javaresource="foo/c/z" classpath="${jar}" /> | |||||
| <fail> | |||||
| <condition> | |||||
| <resourcecount count="0"> | |||||
| <restrict> | |||||
| <url refid="resourceurl" /> | |||||
| <rsel:exists /> | |||||
| </restrict> | |||||
| </resourcecount> | |||||
| </condition> | |||||
| </fail> | |||||
| </target> | |||||
| <target name="url" | |||||
| depends="testfileurl,testfileurlref,testhttpurl1,testhttpurl2,testjarurl,testresourceurl" /> | |||||
| <target name="testfile" depends="init"> | |||||
| <echo file="${file}">This is a test.</echo> | |||||
| <fail> | |||||
| <condition> | |||||
| <not> | |||||
| <length length="15"> | |||||
| <file file="${file}" /> | |||||
| </length> | |||||
| </not> | |||||
| </condition> | |||||
| </fail> | |||||
| </target> | |||||
| <target name="testzipentry" depends="createjar"> | |||||
| <fail> | |||||
| <condition> | |||||
| <not> | |||||
| <length when="greater" length="0"> | |||||
| <zipentry zipfile="${jar}" name="META-INF/MANIFEST.MF" /> | |||||
| </length> | |||||
| </not> | |||||
| </condition> | |||||
| </fail> | |||||
| </target> | |||||
| <target name="teststring1"> | |||||
| <fail> | |||||
| <condition> | |||||
| <not> | |||||
| <length length="15"> | |||||
| <string value="This is a test." /> | |||||
| </length> | |||||
| </not> | |||||
| </condition> | |||||
| </fail> | |||||
| </target> | |||||
| <target name="teststring2"> | |||||
| <property name="test" value="foo" /> | |||||
| <fail> | |||||
| <condition> | |||||
| <not> | |||||
| <length length="14"> | |||||
| <string value="This is a ${test}." /> | |||||
| </length> | |||||
| </not> | |||||
| </condition> | |||||
| </fail> | |||||
| </target> | |||||
| <target name="string" depends="teststring1,teststring2" /> | |||||
| <target name="testresource"> | |||||
| <fail> | |||||
| <condition> | |||||
| <not> | |||||
| <length length="4096"> | |||||
| <resource size="4096" /> | |||||
| </length> | |||||
| </not> | |||||
| </condition> | |||||
| </fail> | |||||
| </target> | |||||
| <target name="testproperty"> | |||||
| <property name="testproperty" value="abcdefghij" /> | |||||
| <fail> | |||||
| <condition> | |||||
| <not> | |||||
| <length length="10"> | |||||
| <propertyresource name="testproperty" /> | |||||
| </length> | |||||
| </not> | |||||
| </condition> | |||||
| </fail> | |||||
| </target> | |||||
| <target name="single" | |||||
| depends="testresource,url,testfile,string,testzipentry,testproperty" /> | |||||
| <target name="all" depends="legacy,files,resources,setlogic,single" /> | |||||
| </project> | |||||
| @@ -0,0 +1,326 @@ | |||||
| <project default="sort" | |||||
| xmlns:rcmp="antlib:org.apache.tools.ant.types.resources.comparators"> | |||||
| <property name="dirname" value="work" /> | |||||
| <property name="dir" location="${dirname}" /> | |||||
| <target name="tearDown"> | |||||
| <delete dir="${dir}" /> | |||||
| <delete file="${zip}" /> | |||||
| <delete file="${jar}" deleteonexit="true" /> | |||||
| <delete file="${file}" /> | |||||
| </target> | |||||
| <target name="sortsetup" unless="sortsetup.done"> | |||||
| <mkdir dir="${dir}" /> | |||||
| <echo file="${dir}/b" message="yyy" /> | |||||
| <echo file="${dir}/e" message="aaa" /> | |||||
| <sleep seconds="2" /> | |||||
| <echo file="${dir}/c" message="x" /> | |||||
| <echo file="${dir}/d" message="x" /> | |||||
| <sleep seconds="2" /> | |||||
| <echo file="${dir}/a" message="zz" /> | |||||
| <echo file="${dir}/f" message="zz" /> | |||||
| <mkdir dir="${dir}/a.dir" /> | |||||
| <mkdir dir="${dir}/b.dir" /> | |||||
| <mkdir dir="${dir}/c.dir" /> | |||||
| <macrodef name="mysort"> | |||||
| <attribute name="property" /> | |||||
| <attribute name="separator" default="," /> | |||||
| <element name="cmp" optional="true" implicit="true" /> | |||||
| <sequential> | |||||
| <pathconvert property="@{property}" pathsep="@{separator}"> | |||||
| <sort> | |||||
| <fileset dir="${dir}" includes="a,b,c" /> | |||||
| <cmp /> | |||||
| </sort> | |||||
| <flattenmapper /> | |||||
| </pathconvert> | |||||
| </sequential> | |||||
| </macrodef> | |||||
| <property name="sortsetup.done" value="true" /> | |||||
| </target> | |||||
| <target name="testsortdefault" depends="sortsetup"> | |||||
| <mysort property="sortdf" /> | |||||
| <fail> | |||||
| <condition> | |||||
| <not> | |||||
| <equals arg1="${sortdf}" arg2="a,b,c" /> | |||||
| </not> | |||||
| </condition> | |||||
| </fail> | |||||
| </target> | |||||
| <target name="testrvdefault" depends="sortsetup"> | |||||
| <mysort property="sortdf-rev"> | |||||
| <rcmp:reverse /> | |||||
| </mysort> | |||||
| <fail> | |||||
| <condition> | |||||
| <not> | |||||
| <equals arg1="${sortdf-rev}" arg2="c,b,a" /> | |||||
| </not> | |||||
| </condition> | |||||
| </fail> | |||||
| </target> | |||||
| <target name="testname" depends="sortsetup"> | |||||
| <mysort property="sortnm"> | |||||
| <rcmp:name /> | |||||
| </mysort> | |||||
| <fail> | |||||
| <condition> | |||||
| <not> | |||||
| <equals arg1="${sortnm}" arg2="a,b,c" /> | |||||
| </not> | |||||
| </condition> | |||||
| </fail> | |||||
| </target> | |||||
| <target name="testrvname" depends="sortsetup"> | |||||
| <mysort property="sortnm-rev"> | |||||
| <rcmp:reverse> | |||||
| <rcmp:name /> | |||||
| </rcmp:reverse> | |||||
| </mysort> | |||||
| <fail> | |||||
| <condition> | |||||
| <not> | |||||
| <equals arg1="${sortnm-rev}" arg2="c,b,a" /> | |||||
| </not> | |||||
| </condition> | |||||
| </fail> | |||||
| </target> | |||||
| <target name="testdate" depends="sortsetup"> | |||||
| <mysort property="sortlm"> | |||||
| <rcmp:date /> | |||||
| </mysort> | |||||
| <fail> | |||||
| <condition> | |||||
| <not> | |||||
| <equals arg1="${sortlm}" arg2="b,c,a" /> | |||||
| </not> | |||||
| </condition> | |||||
| </fail> | |||||
| </target> | |||||
| <target name="testrvdate" depends="sortsetup"> | |||||
| <mysort property="sortlm-rev"> | |||||
| <rcmp:reverse> | |||||
| <rcmp:date /> | |||||
| </rcmp:reverse> | |||||
| </mysort> | |||||
| <fail> | |||||
| <condition> | |||||
| <not> | |||||
| <equals arg1="${sortlm-rev}" arg2="a,c,b" /> | |||||
| </not> | |||||
| </condition> | |||||
| </fail> | |||||
| </target> | |||||
| <target name="testsize" depends="sortsetup"> | |||||
| <mysort property="sortsz"> | |||||
| <rcmp:size /> | |||||
| </mysort> | |||||
| <fail> | |||||
| <condition> | |||||
| <not> | |||||
| <equals arg1="${sortsz}" arg2="c,a,b" /> | |||||
| </not> | |||||
| </condition> | |||||
| </fail> | |||||
| </target> | |||||
| <target name="testrvsize" depends="sortsetup"> | |||||
| <mysort property="sortsz-rev"> | |||||
| <rcmp:reverse> | |||||
| <rcmp:size /> | |||||
| </rcmp:reverse> | |||||
| </mysort> | |||||
| <fail> | |||||
| <condition> | |||||
| <not> | |||||
| <equals arg1="${sortsz-rev}" arg2="b,a,c" /> | |||||
| </not> | |||||
| </condition> | |||||
| </fail> | |||||
| </target> | |||||
| <target name="testcontent" depends="sortsetup"> | |||||
| <mysort property="sortct"> | |||||
| <rcmp:content /> | |||||
| </mysort> | |||||
| <fail> | |||||
| <condition> | |||||
| <not> | |||||
| <equals arg1="${sortct}" arg2="c,b,a" /> | |||||
| </not> | |||||
| </condition> | |||||
| </fail> | |||||
| </target> | |||||
| <target name="testrvcontent" depends="sortsetup"> | |||||
| <mysort property="sortct-rev"> | |||||
| <rcmp:reverse> | |||||
| <rcmp:content /> | |||||
| </rcmp:reverse> | |||||
| </mysort> | |||||
| <fail> | |||||
| <condition> | |||||
| <not> | |||||
| <equals arg1="${sortct-rev}" arg2="a,b,c" /> | |||||
| </not> | |||||
| </condition> | |||||
| </fail> | |||||
| </target> | |||||
| <target name="testexists" depends="sortsetup"> | |||||
| <pathconvert property="sortex" pathsep=","> | |||||
| <sort> | |||||
| <resources> | |||||
| <file file="${dir}/a" /> | |||||
| <resource name="redherring" exists="false" /> | |||||
| </resources> | |||||
| <rcmp:exists /> | |||||
| </sort> | |||||
| <flattenmapper /> | |||||
| </pathconvert> | |||||
| <fail> | |||||
| <condition> | |||||
| <not> | |||||
| <equals arg1="${sortex}" arg2="redherring,a" /> | |||||
| </not> | |||||
| </condition> | |||||
| </fail> | |||||
| </target> | |||||
| <target name="testrvexists" depends="sortsetup"> | |||||
| <pathconvert property="sortex-rev" pathsep=","> | |||||
| <sort> | |||||
| <resources> | |||||
| <file file="${dir}/a" /> | |||||
| <resource name="redherring" exists="false" /> | |||||
| </resources> | |||||
| <rcmp:reverse> | |||||
| <rcmp:exists /> | |||||
| </rcmp:reverse> | |||||
| </sort> | |||||
| <flattenmapper /> | |||||
| </pathconvert> | |||||
| <fail> | |||||
| <condition> | |||||
| <not> | |||||
| <equals arg1="${sortex-rev}" arg2="a,redherring" /> | |||||
| </not> | |||||
| </condition> | |||||
| </fail> | |||||
| </target> | |||||
| <target name="testtype" depends="sortsetup"> | |||||
| <pathconvert property="sorttp" pathsep=","> | |||||
| <sort> | |||||
| <resources> | |||||
| <file file="${dir}/a" /> | |||||
| <file file="${dir}/a.dir" /> | |||||
| </resources> | |||||
| <rcmp:type /> | |||||
| </sort> | |||||
| <flattenmapper /> | |||||
| </pathconvert> | |||||
| <fail> | |||||
| <condition> | |||||
| <not> | |||||
| <equals arg1="${sorttp}" arg2="a,a.dir" /> | |||||
| </not> | |||||
| </condition> | |||||
| </fail> | |||||
| </target> | |||||
| <target name="testrvtype" depends="sortsetup"> | |||||
| <pathconvert property="sorttp-rev" pathsep=","> | |||||
| <sort> | |||||
| <resources> | |||||
| <file file="${dir}/a" /> | |||||
| <file file="${dir}/a.dir" /> | |||||
| </resources> | |||||
| <rcmp:reverse> | |||||
| <rcmp:type /> | |||||
| </rcmp:reverse> | |||||
| </sort> | |||||
| <flattenmapper /> | |||||
| </pathconvert> | |||||
| <fail> | |||||
| <condition> | |||||
| <not> | |||||
| <equals arg1="${sorttp-rev}" arg2="a.dir,a" /> | |||||
| </not> | |||||
| </condition> | |||||
| </fail> | |||||
| </target> | |||||
| <target name="forwardsort" | |||||
| depends="testsortdefault,testname,testdate,testsize,testcontent,testexists,testtype" /> | |||||
| <target name="reversesort" | |||||
| depends="testrvdefault,testrvname,testrvdate,testrvsize,testrvcontent,testrvexists,testrvtype" /> | |||||
| <target name="testcompoundsort1" depends="sortsetup"> | |||||
| <pathconvert property="sortcmp1" pathsep=","> | |||||
| <sort> | |||||
| <resources> | |||||
| <file file="${dir}/c" /> | |||||
| <file file="${dir}/b.dir" /> | |||||
| <file file="${dir}/a" /> | |||||
| <file file="${dir}/c.dir" /> | |||||
| <file file="${dir}/b" /> | |||||
| <file file="${dir}/a.dir" /> | |||||
| </resources> | |||||
| <rcmp:reverse> | |||||
| <rcmp:type /> | |||||
| </rcmp:reverse> | |||||
| <rcmp:name /> | |||||
| </sort> | |||||
| <flattenmapper /> | |||||
| </pathconvert> | |||||
| <fail> | |||||
| <condition> | |||||
| <not> | |||||
| <equals arg1="${sortcmp1}" arg2="a.dir,b.dir,c.dir,a,b,c" /> | |||||
| </not> | |||||
| </condition> | |||||
| </fail> | |||||
| </target> | |||||
| <target name="testcompoundsort2" depends="sortsetup"> | |||||
| <pathconvert property="sortcmp2" pathsep=","> | |||||
| <sort> | |||||
| <files includes="${dir}/?" /> | |||||
| <rcmp:size /> | |||||
| <rcmp:content /> | |||||
| <rcmp:reverse> | |||||
| <rcmp:name /> | |||||
| </rcmp:reverse> | |||||
| </sort> | |||||
| <flattenmapper /> | |||||
| </pathconvert> | |||||
| <fail> | |||||
| <condition> | |||||
| <not> | |||||
| <equals arg1="${sortcmp2}" arg2="d,c,f,a,e,b" /> | |||||
| </not> | |||||
| </condition> | |||||
| </fail> | |||||
| </target> | |||||
| <target name="compoundsort" depends="testcompoundsort1,testcompoundsort2" /> | |||||
| <target name="sort" depends="forwardsort,reversesort,compoundsort" /> | |||||
| </project> | |||||
| @@ -0,0 +1,410 @@ | |||||
| <project default="all" | |||||
| xmlns:rsel="antlib:org.apache.tools.ant.types.resources.selectors"> | |||||
| <target name="testname1"> | |||||
| <fail> | |||||
| <condition> | |||||
| <not> | |||||
| <resourcecount when="equal" count="2"> | |||||
| <restrict> | |||||
| <resources> | |||||
| <resource name="foo" /> | |||||
| <resource name="bar" /> | |||||
| <resource name="baz" /> | |||||
| <resource name="boo" /> | |||||
| <resource name="bang" /> | |||||
| </resources> | |||||
| <rsel:name name="ba?" /> | |||||
| </restrict> | |||||
| </resourcecount> | |||||
| </not> | |||||
| </condition> | |||||
| </fail> | |||||
| </target> | |||||
| <target name="testname2"> | |||||
| <fail> | |||||
| <condition> | |||||
| <not> | |||||
| <resourcecount when="equal" count="2"> | |||||
| <restrict> | |||||
| <resources> | |||||
| <file file="foo" /> | |||||
| <resource name="foo" /> | |||||
| <file file="foo" base="${basedir}" /> | |||||
| </resources> | |||||
| <rsel:name name="foo" /> | |||||
| </restrict> | |||||
| </resourcecount> | |||||
| </not> | |||||
| </condition> | |||||
| </fail> | |||||
| </target> | |||||
| <target name="name" depends="testname1,testname2" /> | |||||
| <target name="testexists"> | |||||
| <fail> | |||||
| <condition> | |||||
| <not> | |||||
| <resourcecount when="equal" count="1"> | |||||
| <restrict> | |||||
| <resources> | |||||
| <file file="idonotexist" /> | |||||
| <resource name="foo" /> | |||||
| <resource name="foo" exists="false" /> | |||||
| </resources> | |||||
| <rsel:exists /> | |||||
| </restrict> | |||||
| </resourcecount> | |||||
| </not> | |||||
| </condition> | |||||
| </fail> | |||||
| </target> | |||||
| <target name="testinstanceoftype1"> | |||||
| <fail> | |||||
| <condition> | |||||
| <not> | |||||
| <resourcecount when="equal" count="2"> | |||||
| <restrict> | |||||
| <resources> | |||||
| <file file="foo" /> | |||||
| <url url="http://ant.apache.org/index.html" /> | |||||
| <resource name="foo" /> | |||||
| <string value="foo" /> | |||||
| <file file="bar" /> | |||||
| </resources> | |||||
| <rsel:instanceof type="file" /> | |||||
| </restrict> | |||||
| </resourcecount> | |||||
| </not> | |||||
| </condition> | |||||
| </fail> | |||||
| </target> | |||||
| <target name="testinstanceoftype2"> | |||||
| <typedef name="file" uri="test" | |||||
| classname="org.apache.tools.ant.types.resources.FileResource" /> | |||||
| <fail> | |||||
| <condition> | |||||
| <not> | |||||
| <resourcecount when="equal" count="1"> | |||||
| <restrict> | |||||
| <resources> | |||||
| <url file="foo" /> | |||||
| <file file="bar" xmlns="test" /> | |||||
| </resources> | |||||
| <rsel:instanceof type="test:file" /> | |||||
| </restrict> | |||||
| </resourcecount> | |||||
| </not> | |||||
| </condition> | |||||
| </fail> | |||||
| </target> | |||||
| <target name="testinstanceoftype3"> | |||||
| <typedef name="file" uri="test" | |||||
| classname="org.apache.tools.ant.types.resources.FileResource" /> | |||||
| <fail> | |||||
| <condition> | |||||
| <not> | |||||
| <resourcecount when="equal" count="1"> | |||||
| <restrict> | |||||
| <resources> | |||||
| <url file="foo" /> | |||||
| <file file="bar" xmlns="test" /> | |||||
| </resources> | |||||
| <rsel:instanceof type="file" uri="test" /> | |||||
| </restrict> | |||||
| </resourcecount> | |||||
| </not> | |||||
| </condition> | |||||
| </fail> | |||||
| </target> | |||||
| <target name="testinstanceoftype" | |||||
| depends="testinstanceoftype1,testinstanceoftype2,testinstanceoftype3" /> | |||||
| <target name="testinstanceofclass"> | |||||
| <fail> | |||||
| <condition> | |||||
| <not> | |||||
| <resourcecount when="equal" count="7"> | |||||
| <restrict> | |||||
| <resources> | |||||
| <filelist dir="${basedir}" files="a,b,c,d,e,f,g" /> | |||||
| </resources> | |||||
| <rsel:instanceof class="org.apache.tools.ant.types.Resource" /> | |||||
| </restrict> | |||||
| </resourcecount> | |||||
| </not> | |||||
| </condition> | |||||
| </fail> | |||||
| </target> | |||||
| <target name="instanceof" depends="testinstanceoftype,testinstanceofclass" /> | |||||
| <target name="testtype"> | |||||
| <fail> | |||||
| <condition> | |||||
| <not> | |||||
| <resourcecount when="equal" count="2"> | |||||
| <restrict> | |||||
| <resources> | |||||
| <file file="${basedir}" /> | |||||
| <file file="${ant.file}" /> | |||||
| <resource directory="true" /> | |||||
| <resource directory="false" /> | |||||
| </resources> | |||||
| <rsel:type type="dir" /> | |||||
| </restrict> | |||||
| </resourcecount> | |||||
| </not> | |||||
| </condition> | |||||
| </fail> | |||||
| </target> | |||||
| <target name="testdate"> | |||||
| <fail> | |||||
| <condition> | |||||
| <not> | |||||
| <resourcecount when="equal" count="3"> | |||||
| <restrict> | |||||
| <resources> | |||||
| <resource lastmodified="4" /> | |||||
| <resource lastmodified="5" /> | |||||
| <resource lastmodified="6" /> | |||||
| <resource lastmodified="7" /> | |||||
| <resource lastmodified="8" /> | |||||
| </resources> | |||||
| <rsel:date when="after" millis="5" granularity="0" /> | |||||
| </restrict> | |||||
| </resourcecount> | |||||
| </not> | |||||
| </condition> | |||||
| </fail> | |||||
| </target> | |||||
| <target name="testsize"> | |||||
| <fail> | |||||
| <condition> | |||||
| <not> | |||||
| <resourcecount when="equal" count="4"> | |||||
| <restrict> | |||||
| <resources> | |||||
| <resource size="4" /> | |||||
| <resource size="5" /> | |||||
| <resource size="6" /> | |||||
| <resource size="7" /> | |||||
| <resource size="8" /> | |||||
| </resources> | |||||
| <rsel:size when="le" size="7" /> | |||||
| </restrict> | |||||
| </resourcecount> | |||||
| </not> | |||||
| </condition> | |||||
| </fail> | |||||
| </target> | |||||
| <target name="testand"> | |||||
| <fail> | |||||
| <condition> | |||||
| <not> | |||||
| <resourcecount when="equal" count="1"> | |||||
| <restrict> | |||||
| <resources> | |||||
| <string value="fee" /> | |||||
| <resource name="fi" size="3" /> | |||||
| <resource name="fo" /> | |||||
| <resource name="fum" /> | |||||
| </resources> | |||||
| <and xmlns="antlib:org.apache.tools.ant.types.resources.selectors"> | |||||
| <name name="f?" /> | |||||
| <size size="3" /> | |||||
| </and> | |||||
| </restrict> | |||||
| </resourcecount> | |||||
| </not> | |||||
| </condition> | |||||
| </fail> | |||||
| </target> | |||||
| <target name="testor"> | |||||
| <fail> | |||||
| <condition> | |||||
| <not> | |||||
| <resourcecount when="equal" count="3"> | |||||
| <restrict> | |||||
| <resources> | |||||
| <string value="fee" /> | |||||
| <resource name="fi" size="3" /> | |||||
| <resource name="fo" /> | |||||
| <resource name="fum" /> | |||||
| </resources> | |||||
| <or xmlns="antlib:org.apache.tools.ant.types.resources.selectors"> | |||||
| <name name="f?" /> | |||||
| <size size="3" /> | |||||
| </or> | |||||
| </restrict> | |||||
| </resourcecount> | |||||
| </not> | |||||
| </condition> | |||||
| </fail> | |||||
| </target> | |||||
| <target name="testnot"> | |||||
| <fail> | |||||
| <condition> | |||||
| <not> | |||||
| <resourcecount when="equal" count="2"> | |||||
| <restrict> | |||||
| <resources> | |||||
| <string value="fee" /> | |||||
| <resource name="fi" size="3" /> | |||||
| <resource name="fo" /> | |||||
| <resource name="fum" /> | |||||
| </resources> | |||||
| <not xmlns="antlib:org.apache.tools.ant.types.resources.selectors"> | |||||
| <size size="3" /> | |||||
| </not> | |||||
| </restrict> | |||||
| </resourcecount> | |||||
| </not> | |||||
| </condition> | |||||
| </fail> | |||||
| </target> | |||||
| <target name="testnone"> | |||||
| <fail> | |||||
| <condition> | |||||
| <not> | |||||
| <resourcecount when="equal" count="1"> | |||||
| <restrict> | |||||
| <resources> | |||||
| <string value="fee" /> | |||||
| <resource name="fi" size="3" /> | |||||
| <resource name="fo" /> | |||||
| <resource name="fum" /> | |||||
| </resources> | |||||
| <none xmlns="antlib:org.apache.tools.ant.types.resources.selectors"> | |||||
| <name name="f?" /> | |||||
| <size size="3" /> | |||||
| </none> | |||||
| </restrict> | |||||
| </resourcecount> | |||||
| </not> | |||||
| </condition> | |||||
| </fail> | |||||
| </target> | |||||
| <target name="testmajority1"> | |||||
| <fail> | |||||
| <condition> | |||||
| <not> | |||||
| <resourcecount when="equal" count="2"> | |||||
| <restrict> | |||||
| <resources> | |||||
| <string value="fee" /> | |||||
| <resource name="fi" size="3" /> | |||||
| <resource name="fo" /> | |||||
| <resource name="fum" /> | |||||
| </resources> | |||||
| <majority xmlns="antlib:org.apache.tools.ant.types.resources.selectors"> | |||||
| <name name="f?" /> | |||||
| <size size="3" /> | |||||
| <instanceof type="string" /> | |||||
| </majority> | |||||
| </restrict> | |||||
| </resourcecount> | |||||
| </not> | |||||
| </condition> | |||||
| </fail> | |||||
| </target> | |||||
| <target name="testmajority2"> | |||||
| <fail> | |||||
| <condition> | |||||
| <not> | |||||
| <resourcecount when="equal" count="3"> | |||||
| <restrict> | |||||
| <resources> | |||||
| <string value="fee" /> | |||||
| <resource name="fi" size="3" /> | |||||
| <resource name="fo" /> | |||||
| <resource name="fum" /> | |||||
| </resources> | |||||
| <majority xmlns="antlib:org.apache.tools.ant.types.resources.selectors"> | |||||
| <name name="f?" /> | |||||
| <size size="3" /> | |||||
| <instanceof type="resource" /> | |||||
| </majority> | |||||
| </restrict> | |||||
| </resourcecount> | |||||
| </not> | |||||
| </condition> | |||||
| </fail> | |||||
| </target> | |||||
| <target name="testmajority3"> | |||||
| <fail> | |||||
| <condition> | |||||
| <not> | |||||
| <resourcecount when="equal" count="3"> | |||||
| <restrict> | |||||
| <resources> | |||||
| <string value="fee" /> | |||||
| <resource name="fi" size="3" /> | |||||
| <resource name="fo" /> | |||||
| <resource name="fum" /> | |||||
| </resources> | |||||
| <majority allowtie="true" | |||||
| xmlns="antlib:org.apache.tools.ant.types.resources.selectors"> | |||||
| <name name="f?" /> | |||||
| <size size="3" /> | |||||
| <instanceof type="string" /> | |||||
| <exists /> | |||||
| </majority> | |||||
| </restrict> | |||||
| </resourcecount> | |||||
| </not> | |||||
| </condition> | |||||
| </fail> | |||||
| </target> | |||||
| <target name="testmajority4"> | |||||
| <fail> | |||||
| <condition> | |||||
| <not> | |||||
| <resourcecount when="equal" count="2"> | |||||
| <restrict> | |||||
| <resources> | |||||
| <string value="fee" /> | |||||
| <resource name="fi" size="3" /> | |||||
| <resource name="fo" /> | |||||
| <resource name="fum" /> | |||||
| </resources> | |||||
| <majority allowtie="false" | |||||
| xmlns="antlib:org.apache.tools.ant.types.resources.selectors"> | |||||
| <name name="f?" /> | |||||
| <size size="3" /> | |||||
| <instanceof type="string" /> | |||||
| <exists /> | |||||
| </majority> | |||||
| </restrict> | |||||
| </resourcecount> | |||||
| </not> | |||||
| </condition> | |||||
| </fail> | |||||
| </target> | |||||
| <target name="majority" | |||||
| depends="testmajority1,testmajority2,testmajority3,testmajority4" /> | |||||
| <target name="logical" | |||||
| depends="testand,testor,testnone,testnot,majority" /> | |||||
| <target name="all" | |||||
| depends="name,testexists,instanceof,testtype,testdate,testsize,logical" /> | |||||
| </project> | |||||
| @@ -17,34 +17,46 @@ | |||||
| package org.apache.tools.ant.taskdefs; | 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.BufferedReader; | ||||
| import java.io.BufferedWriter; | import java.io.BufferedWriter; | ||||
| import java.io.File; | |||||
| import java.io.FileInputStream; | import java.io.FileInputStream; | ||||
| import java.io.FileOutputStream; | import java.io.FileOutputStream; | ||||
| import java.io.FileReader; | |||||
| import java.io.IOException; | |||||
| import java.io.InputStreamReader; | import java.io.InputStreamReader; | ||||
| import java.io.OutputStream; | |||||
| import java.io.OutputStreamWriter; | 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.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.BuildException; | ||||
| import org.apache.tools.ant.DirectoryScanner; | import org.apache.tools.ant.DirectoryScanner; | ||||
| import org.apache.tools.ant.Project; | |||||
| import org.apache.tools.ant.ProjectComponent; | 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.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.FileSet; | ||||
| import org.apache.tools.ant.types.FileList; | |||||
| import org.apache.tools.ant.types.FilterChain; | 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.FileUtils; | ||||
| import org.apache.tools.ant.util.ConcatResourceInputStream; | |||||
| /** | /** | ||||
| * This class contains the 'concat' task, used to concatenate a series | * 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 | // The size of buffers to be used | ||||
| private static final int BUFFER_SIZE = 8192; | 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. | // Attributes. | ||||
| /** | /** | ||||
| * The destination of the stream. If <code>null</code>, the system | * The destination of the stream. If <code>null</code>, the system | ||||
| * console is used. | * console is used. | ||||
| */ | */ | ||||
| private File destinationFile = null; | |||||
| private File destinationFile; | |||||
| /** | /** | ||||
| * Whether or not the stream should be appended if the destination file | * Whether or not the stream should be appended if the destination file | ||||
| * exists. | * exists. | ||||
| * Defaults to <code>false</code>. | * Defaults to <code>false</code>. | ||||
| */ | */ | ||||
| private boolean append = false; | |||||
| private boolean append; | |||||
| /** | /** | ||||
| * Stores the input file encoding. | * Stores the input file encoding. | ||||
| */ | */ | ||||
| private String encoding = null; | |||||
| private String encoding; | |||||
| /** Stores the output file encoding. */ | /** Stores the output file encoding. */ | ||||
| private String outputEncoding = null; | |||||
| private String outputEncoding; | |||||
| /** Stores the binary attribute */ | /** Stores the binary attribute */ | ||||
| private boolean binary = false; | |||||
| private boolean binary; | |||||
| // Child elements. | // Child elements. | ||||
| @@ -106,25 +122,49 @@ public class Concat extends Task { | |||||
| * Stores a collection of file sets and/or file lists, used to | * Stores a collection of file sets and/or file lists, used to | ||||
| * select multiple files for concatenation. | * select multiple files for concatenation. | ||||
| */ | */ | ||||
| private Vector sources = new Vector(); | |||||
| private Resources rc; | |||||
| /** for filtering the concatenated */ | /** for filtering the concatenated */ | ||||
| private Vector filterChains = null; | |||||
| private Vector filterChains; | |||||
| /** ignore dates on input files */ | /** ignore dates on input files */ | ||||
| private boolean forceOverwrite = true; | |||||
| private boolean forceOverwrite = true; | |||||
| /** String to place at the start of the concatented stream */ | /** 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 */ | /** String to place at the end of the concatented stream */ | ||||
| private TextElement header; | |||||
| private TextElement header; | |||||
| /** add missing line.separator to files **/ | /** add missing line.separator to files **/ | ||||
| private boolean fixLastLine = false; | |||||
| private boolean fixLastLine = false; | |||||
| /** endofline for fixlast line */ | /** endofline for fixlast line */ | ||||
| private String eolString = System.getProperty("line.separator"); | |||||
| private String eolString; | |||||
| /** outputwriter */ | /** 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. | // Attribute setters. | ||||
| @@ -187,7 +227,7 @@ public class Concat extends Task { | |||||
| */ | */ | ||||
| public Path createPath() { | public Path createPath() { | ||||
| Path path = new Path(getProject()); | Path path = new Path(getProject()); | ||||
| sources.addElement(path); | |||||
| add(path); | |||||
| return path; | return path; | ||||
| } | } | ||||
| @@ -196,7 +236,7 @@ public class Concat extends Task { | |||||
| * @param set the set of files | * @param set the set of files | ||||
| */ | */ | ||||
| public void addFileset(FileSet set) { | 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 | * @param list the list of files | ||||
| */ | */ | ||||
| public void addFilelist(FileList list) { | 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 | * @since Ant 1.6 | ||||
| */ | */ | ||||
| public void setWriter(Writer outputWriter) { | 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) { | public void setBinary(boolean binary) { | ||||
| this.binary = 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 | // treat empty nested text as no text | ||||
| sanitizeText(); | sanitizeText(); | ||||
| @@ -319,9 +366,8 @@ public class Concat extends Task { | |||||
| if (binary) { | if (binary) { | ||||
| if (destinationFile == null) { | if (destinationFile == null) { | ||||
| throw new BuildException( | throw new BuildException( | ||||
| "DestFile attribute is required for binary concatenation"); | |||||
| "destfile attribute is required for binary concatenation"); | |||||
| } | } | ||||
| if (textBuffer != null) { | if (textBuffer != null) { | ||||
| throw new BuildException( | throw new BuildException( | ||||
| "Nested text is incompatible with binary concatenation"); | "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"); | "Nested header or footer is incompatible with binary concatenation"); | ||||
| } | } | ||||
| } | } | ||||
| if (destinationFile != null && outputWriter != null) { | if (destinationFile != null && outputWriter != null) { | ||||
| throw new BuildException( | throw new BuildException( | ||||
| "Cannot specify both a destination file and an output writer"); | "Cannot specify both a destination file and an output writer"); | ||||
| } | } | ||||
| // Sanity check our inputs. | // Sanity check our inputs. | ||||
| if (sources.size() == 0 && textBuffer == null) { | |||||
| if (rc == null && textBuffer == null) { | |||||
| // Nothing to concatenate! | // Nothing to concatenate! | ||||
| throw new BuildException( | 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) { | if (!outofdate) { | ||||
| log(destinationFile + " is up-to-date.", Project.MSG_VERBOSE); | 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 { | } 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() { | 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 */ | /** 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; | FileOutputStream out = null; | ||||
| FileInputStream in = null; | |||||
| InputStream in = null; | |||||
| byte[] buffer = new byte[BUFFER_SIZE]; | byte[] buffer = new byte[BUFFER_SIZE]; | ||||
| try { | try { | ||||
| try { | try { | ||||
| out = new FileOutputStream(destinationFile); | out = new FileOutputStream(destinationFile); | ||||
| } catch (Exception t) { | } 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 { | try { | ||||
| in.close(); | |||||
| } catch (Exception t) { | |||||
| throw new BuildException( | |||||
| "Unable to close " + sourceFile, t); | |||||
| t.join(); | |||||
| } catch (InterruptedException ee) { | |||||
| } | } | ||||
| in = null; | |||||
| } | } | ||||
| } finally { | } finally { | ||||
| FileUtils.close(in); | FileUtils.close(in); | ||||
| if (out != null) { | if (out != null) { | ||||
| try { | try { | ||||
| out.close(); | out.close(); | ||||
| @@ -537,13 +513,11 @@ public class Concat extends Task { | |||||
| } | } | ||||
| /** perform the concatenation */ | /** perform the concatenation */ | ||||
| private void cat() { | |||||
| private void cat(ResourceCollection c) { | |||||
| OutputStream os = null; | OutputStream os = null; | ||||
| Reader reader = null; | |||||
| char[] buffer = new char[BUFFER_SIZE]; | |||||
| char[] buffer = new char[BUFFER_SIZE]; | |||||
| try { | try { | ||||
| PrintWriter writer = null; | PrintWriter writer = null; | ||||
| if (outputWriter != null) { | if (outputWriter != null) { | ||||
| @@ -558,11 +532,9 @@ public class Concat extends Task { | |||||
| if (!parent.exists()) { | if (!parent.exists()) { | ||||
| parent.mkdirs(); | parent.mkdirs(); | ||||
| } | } | ||||
| os = new FileOutputStream(destinationFile.getAbsolutePath(), | os = new FileOutputStream(destinationFile.getAbsolutePath(), | ||||
| append); | append); | ||||
| } | } | ||||
| if (outputEncoding == null) { | if (outputEncoding == null) { | ||||
| writer = new PrintWriter( | writer = new PrintWriter( | ||||
| new BufferedWriter( | new BufferedWriter( | ||||
| @@ -573,7 +545,6 @@ public class Concat extends Task { | |||||
| new OutputStreamWriter(os, outputEncoding))); | new OutputStreamWriter(os, outputEncoding))); | ||||
| } | } | ||||
| } | } | ||||
| if (header != null) { | if (header != null) { | ||||
| if (header.getFiltering()) { | if (header.getFiltering()) { | ||||
| concatenate( | concatenate( | ||||
| @@ -582,16 +553,9 @@ public class Concat extends Task { | |||||
| writer.print(header.getValue()); | 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 != null) { | ||||
| if (footer.getFiltering()) { | if (footer.getFiltering()) { | ||||
| concatenate( | concatenate( | ||||
| @@ -600,34 +564,18 @@ public class Concat extends Task { | |||||
| writer.print(footer.getValue()); | writer.print(footer.getValue()); | ||||
| } | } | ||||
| } | } | ||||
| writer.flush(); | writer.flush(); | ||||
| if (os != null) { | if (os != null) { | ||||
| os.flush(); | os.flush(); | ||||
| } | } | ||||
| } catch (IOException ioex) { | } catch (IOException ioex) { | ||||
| throw new BuildException("Error while concatenating: " | throw new BuildException("Error while concatenating: " | ||||
| + ioex.getMessage(), ioex); | + ioex.getMessage(), ioex); | ||||
| } finally { | } 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 */ | /** Concatenate a single reader to the writer using buffer */ | ||||
| private void concatenate(char[] buffer, Writer writer, Reader in) | private void concatenate(char[] buffer, Writer writer, Reader in) | ||||
| throws IOException { | throws IOException { | ||||
| @@ -639,7 +587,6 @@ public class Concat extends Task { | |||||
| helper.setProject(getProject()); | helper.setProject(getProject()); | ||||
| in = new BufferedReader(helper.getAssembledReader()); | in = new BufferedReader(helper.getAssembledReader()); | ||||
| } | } | ||||
| while (true) { | while (true) { | ||||
| int nRead = in.read(buffer, 0, buffer.length); | int nRead = in.read(buffer, 0, buffer.length); | ||||
| if (nRead == -1) { | if (nRead == -1) { | ||||
| @@ -647,7 +594,6 @@ public class Concat extends Task { | |||||
| } | } | ||||
| writer.write(buffer, 0, nRead); | writer.write(buffer, 0, nRead); | ||||
| } | } | ||||
| writer.flush(); | writer.flush(); | ||||
| } | } | ||||
| @@ -796,34 +742,34 @@ public class Concat extends Task { | |||||
| * a single stream. | * a single stream. | ||||
| */ | */ | ||||
| private class MultiReader extends Reader { | private class MultiReader extends Reader { | ||||
| private int pos = 0; | |||||
| private Reader reader = null; | private Reader reader = null; | ||||
| private int lastPos = 0; | private int lastPos = 0; | ||||
| private char[] lastChars = new char[eolString.length()]; | private char[] lastChars = new char[eolString.length()]; | ||||
| private boolean needAddSeparator = false; | private boolean needAddSeparator = false; | ||||
| private Iterator i; | |||||
| private MultiReader(ResourceCollection c) { | |||||
| i = c.iterator(); | |||||
| } | |||||
| private Reader getReader() throws IOException { | 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; | return reader; | ||||
| } | } | ||||
| private void nextReader() throws IOException { | |||||
| close(); | |||||
| reader = null; | |||||
| } | |||||
| /** | /** | ||||
| * Read a character from the current reader object. Advance | * Read a character from the current reader object. Advance | ||||
| * to the next if the reader is finished. | * to the next if the reader is finished. | ||||
| @@ -840,12 +786,10 @@ public class Concat extends Task { | |||||
| } | } | ||||
| return ret; | return ret; | ||||
| } | } | ||||
| while (pos < sourceFiles.size()) { | |||||
| while (getReader() != null) { | |||||
| int ch = getReader().read(); | int ch = getReader().read(); | ||||
| if (ch == -1) { | if (ch == -1) { | ||||
| reader.close(); | |||||
| reader = null; | |||||
| nextReader(); | |||||
| if (fixLastLine && isMissingEndOfLine()) { | if (fixLastLine && isMissingEndOfLine()) { | ||||
| needAddSeparator = true; | needAddSeparator = true; | ||||
| lastPos = 0; | lastPos = 0; | ||||
| @@ -854,7 +798,6 @@ public class Concat extends Task { | |||||
| addLastChar((char) ch); | addLastChar((char) ch); | ||||
| return ch; | return ch; | ||||
| } | } | ||||
| pos++; | |||||
| } | } | ||||
| return -1; | return -1; | ||||
| } | } | ||||
| @@ -871,13 +814,12 @@ public class Concat extends Task { | |||||
| throws IOException { | throws IOException { | ||||
| int amountRead = 0; | int amountRead = 0; | ||||
| while (pos < sourceFiles.size() || (needAddSeparator)) { | |||||
| while (getReader() != null || needAddSeparator) { | |||||
| if (needAddSeparator) { | if (needAddSeparator) { | ||||
| cbuf[off] = eolString.charAt(lastPos++); | cbuf[off] = eolString.charAt(lastPos++); | ||||
| if (lastPos >= eolString.length()) { | if (lastPos >= eolString.length()) { | ||||
| lastPos = 0; | lastPos = 0; | ||||
| needAddSeparator = false; | needAddSeparator = false; | ||||
| pos++; | |||||
| } | } | ||||
| len--; | len--; | ||||
| off++; | off++; | ||||
| @@ -889,13 +831,10 @@ public class Concat extends Task { | |||||
| } | } | ||||
| int nRead = getReader().read(cbuf, off, len); | int nRead = getReader().read(cbuf, off, len); | ||||
| if (nRead == -1 || nRead == 0) { | if (nRead == -1 || nRead == 0) { | ||||
| reader.close(); | |||||
| reader = null; | |||||
| nextReader(); | |||||
| if (fixLastLine && isMissingEndOfLine()) { | if (fixLastLine && isMissingEndOfLine()) { | ||||
| needAddSeparator = true; | needAddSeparator = true; | ||||
| lastPos = 0; | lastPos = 0; | ||||
| } else { | |||||
| pos++; | |||||
| } | } | ||||
| } else { | } else { | ||||
| if (fixLastLine) { | if (fixLastLine) { | ||||
| @@ -931,6 +870,7 @@ public class Concat extends Task { | |||||
| reader.close(); | reader.close(); | ||||
| } | } | ||||
| } | } | ||||
| /** | /** | ||||
| * if checking for end of line at end of file | * if checking for end of line at end of file | ||||
| * add a character to the lastchars buffer | * add a character to the lastchars buffer | ||||
| @@ -21,18 +21,21 @@ import java.io.File; | |||||
| import java.io.PrintStream; | import java.io.PrintStream; | ||||
| import java.io.OutputStream; | import java.io.OutputStream; | ||||
| import java.io.ByteArrayOutputStream; | import java.io.ByteArrayOutputStream; | ||||
| import java.util.Vector; | |||||
| import java.util.Iterator; | import java.util.Iterator; | ||||
| import org.apache.tools.ant.Task; | import org.apache.tools.ant.Task; | ||||
| import org.apache.tools.ant.Project; | import org.apache.tools.ant.Project; | ||||
| import org.apache.tools.ant.BuildException; | 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.taskdefs.condition.Condition; | ||||
| import org.apache.tools.ant.types.FileSet; | import org.apache.tools.ant.types.FileSet; | ||||
| import org.apache.tools.ant.types.Resource; | 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.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.FileUtils; | ||||
| import org.apache.tools.ant.util.PropertyOutputStream; | |||||
| /** | /** | ||||
| * Gets lengths: of files/resources, byte size; of strings, length (optionally trimmed). | * 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 String string; | ||||
| private Boolean trim; | private Boolean trim; | ||||
| private String mode = ALL; | private String mode = ALL; | ||||
| private When when = When.EQUAL; | |||||
| private Comparison when = Comparison.EQUAL; | |||||
| private Long length; | private Long length; | ||||
| private Vector filesets; | |||||
| private Resources resources; | |||||
| /** | /** | ||||
| * The property in which the length will be stored. | * 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. | * @param file the <code>File</code> whose length to retrieve. | ||||
| */ | */ | ||||
| public synchronized void setFile(File file) { | 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. | * @param fs the <code>FileSet</code> to add. | ||||
| */ | */ | ||||
| public synchronized void add(FileSet fs) { | 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; | 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. | * @param w EnumeratedAttribute When. | ||||
| * @see org.apache.tools.ant.types.Comparison | |||||
| */ | */ | ||||
| public synchronized void setWhen(When w) { | 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() { | public void execute() { | ||||
| validate(); | validate(); | ||||
| PrintStream ps = new PrintStream((property != null) | PrintStream ps = new PrintStream((property != null) | ||||
| ? (OutputStream) new PropertyOutputStream() | |||||
| ? (OutputStream) new PropertyOutputStream(getProject(), property) | |||||
| : (OutputStream) new LogOutputStream(this, Project.MSG_INFO)); | : (OutputStream) new LogOutputStream(this, Project.MSG_INFO)); | ||||
| if (STRING.equals(mode)) { | if (STRING.equals(mode)) { | ||||
| @@ -173,27 +193,23 @@ public class Length extends Task implements Condition { | |||||
| handleResources(h); | handleResources(h); | ||||
| ell = new Long(h.getLength()); | 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() { | private void validate() { | ||||
| if (string != null) { | if (string != null) { | ||||
| if (filesets != null && filesets.size() > 0) { | |||||
| if (resources != null) { | |||||
| throw new BuildException("the string length function" | 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))) { | if (!(STRING.equals(mode))) { | ||||
| throw new BuildException("the mode attribute is for use" | throw new BuildException("the mode attribute is for use" | ||||
| + " with the file/resource length function"); | + " with the file/resource length function"); | ||||
| } | } | ||||
| } else if (filesets != null) { | |||||
| } else if (resources != null) { | |||||
| if (!(EACH.equals(mode) || ALL.equals(mode))) { | if (!(EACH.equals(mode) || ALL.equals(mode))) { | ||||
| throw new BuildException("invalid mode setting for" | throw new BuildException("invalid mode setting for" | ||||
| + " file length function: \"" + mode + "\""); | |||||
| + " file/resource length function: \"" + mode + "\""); | |||||
| } else if (trim != null) { | } else if (trim != null) { | ||||
| throw new BuildException("the trim attribute is" | throw new BuildException("the trim attribute is" | ||||
| + " for use with the string length function only"); | + " for use with the string length function only"); | ||||
| @@ -201,30 +217,20 @@ public class Length extends Task implements Condition { | |||||
| } else { | } else { | ||||
| throw new BuildException("you must set either the string attribute" | throw new BuildException("you must set either the string attribute" | ||||
| + " or specify one or more files using the file attribute or" | + " or specify one or more files using the file attribute or" | ||||
| + " nested filesets"); | |||||
| + " nested resource collections"); | |||||
| } | } | ||||
| } | } | ||||
| private void handleResources(Handler h) { | 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(); | h.complete(); | ||||
| @@ -251,27 +257,8 @@ public class Length extends Task implements Condition { | |||||
| /** | /** | ||||
| * EnumeratedAttribute for the when attribute. | * 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 { | private abstract class Handler { | ||||
| @@ -292,7 +279,7 @@ public class Length extends Task implements Condition { | |||||
| super(ps); | super(ps); | ||||
| } | } | ||||
| protected void handle(Resource r) { | protected void handle(Resource r) { | ||||
| ps.print(r.getName()); | |||||
| ps.print(r.toString()); | |||||
| ps.print(" : "); | ps.print(" : "); | ||||
| //when writing to the log, we'll see what's happening: | //when writing to the log, we'll see what's happening: | ||||
| long size = r.getSize(); | long size = r.getSize(); | ||||
| @@ -312,7 +299,7 @@ public class Length extends Task implements Condition { | |||||
| protected synchronized void handle(Resource r) { | protected synchronized void handle(Resource r) { | ||||
| long size = r.getSize(); | long size = r.getSize(); | ||||
| if (size == Resource.UNKNOWN_SIZE) { | if (size == Resource.UNKNOWN_SIZE) { | ||||
| log("Size unknown for " + r.getName(), Project.MSG_WARN); | |||||
| log("Size unknown for " + r.toString(), Project.MSG_WARN); | |||||
| } else { | } else { | ||||
| accum += size; | accum += size; | ||||
| } | } | ||||
| @@ -17,21 +17,23 @@ | |||||
| package org.apache.tools.ant.taskdefs; | package org.apache.tools.ant.taskdefs; | ||||
| import java.io.File; | import java.io.File; | ||||
| import java.util.StringTokenizer; | |||||
| import java.util.Vector; | |||||
| import java.util.List; | import java.util.List; | ||||
| import java.util.Vector; | |||||
| import java.util.ArrayList; | 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.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.taskdefs.condition.Os; | ||||
| import org.apache.tools.ant.types.Path; | |||||
| import org.apache.tools.ant.types.DirSet; | 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.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.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; | import org.apache.tools.ant.util.FileNameMapper; | ||||
| /** | /** | ||||
| @@ -43,11 +45,16 @@ import org.apache.tools.ant.util.FileNameMapper; | |||||
| */ | */ | ||||
| public class PathConvert extends Task { | public class PathConvert extends Task { | ||||
| /** | |||||
| * Set if we're running on windows | |||||
| */ | |||||
| private static boolean onWindows = Os.isFamily("dos"); | |||||
| // Members | // Members | ||||
| /** | /** | ||||
| * Path to be converted | * Path to be converted | ||||
| */ | */ | ||||
| private Path path = null; | |||||
| private Union path = null; | |||||
| /** | /** | ||||
| * Reference to path/fileset to convert | * Reference to path/fileset to convert | ||||
| */ | */ | ||||
| @@ -60,10 +67,6 @@ public class PathConvert extends Task { | |||||
| * Set when targetOS is set to windows | * Set when targetOS is set to windows | ||||
| */ | */ | ||||
| private boolean targetWindows = false; | 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 | * 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. | * Construct a new instance of the PathConvert task. | ||||
| */ | */ | ||||
| public PathConvert() { | 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. | * @return a Path to be used by Ant reflection. | ||||
| */ | */ | ||||
| public Path createPath() { | public Path createPath() { | ||||
| if (isReference()) { | if (isReference()) { | ||||
| throw noChildrenAllowed(); | 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) { | 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. | * @throws BuildException if something is invalid. | ||||
| */ | */ | ||||
| public void execute() throws BuildException { | public void execute() throws BuildException { | ||||
| Path savedPath = path; | |||||
| Union savedPath = path; | |||||
| String savedPathSep = pathSep; // may be altered in validateSetup | String savedPathSep = pathSep; // may be altered in validateSetup | ||||
| String savedDirSep = dirSep; // may be altered in validateSetup | String savedDirSep = dirSep; // may be altered in validateSetup | ||||
| try { | try { | ||||
| // If we are a reference, create a Path from the reference | // If we are a reference, create a Path from the reference | ||||
| if (isReference()) { | 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 | validateSetup(); // validate our setup | ||||
| @@ -355,9 +367,13 @@ public class PathConvert extends Task { | |||||
| // unless setonempty == false | // unless setonempty == false | ||||
| if (setonempty || rslt.length() > 0) { | if (setonempty || rslt.length() > 0) { | ||||
| String value = rslt.toString(); | 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 { | } finally { | ||||
| path = savedPath; | path = savedPath; | ||||
| @@ -423,7 +439,6 @@ public class PathConvert extends Task { | |||||
| addMapper(m); | addMapper(m); | ||||
| } | } | ||||
| /** | /** | ||||
| * Validate that all our parameters have been properly initialized. | * Validate that all our parameters have been properly initialized. | ||||
| * | * | ||||
| @@ -434,9 +449,6 @@ public class PathConvert extends Task { | |||||
| if (path == null) { | if (path == null) { | ||||
| throw new BuildException("You must specify a path to convert"); | 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 | // Determine the separator strings. The dirsep and pathsep attributes | ||||
| // override the targetOS settings. | // override the targetOS settings. | ||||
| String dsep = File.separator; | String dsep = File.separator; | ||||
| @@ -464,7 +476,7 @@ public class PathConvert extends Task { | |||||
| * @return BuildException. | * @return BuildException. | ||||
| */ | */ | ||||
| private BuildException noChildrenAllowed() { | 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."); | + "elements when using the refid attribute."); | ||||
| } | } | ||||
| @@ -0,0 +1,124 @@ | |||||
| /* | |||||
| * Copyright 2005 The Apache Software Foundation | |||||
| * | |||||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||||
| * you may not use this file except in compliance with the License. | |||||
| * You may obtain a copy of the License at | |||||
| * | |||||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||||
| * | |||||
| * Unless required by applicable law or agreed to in writing, software | |||||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
| * See the License for the specific language governing permissions and | |||||
| * limitations under the License. | |||||
| * | |||||
| */ | |||||
| package org.apache.tools.ant.taskdefs; | |||||
| import org.apache.tools.ant.Task; | |||||
| import org.apache.tools.ant.Project; | |||||
| import org.apache.tools.ant.BuildException; | |||||
| import org.apache.tools.ant.taskdefs.condition.Condition; | |||||
| import org.apache.tools.ant.types.Reference; | |||||
| import org.apache.tools.ant.types.Comparison; | |||||
| import org.apache.tools.ant.types.ResourceCollection; | |||||
| /** | |||||
| * Count resources from a ResourceCollection, storing to a property or | |||||
| * writing to the log. Can also be used as a Condition. | |||||
| * @since Ant 1.7 | |||||
| */ | |||||
| public class ResourceCount extends Task implements Condition { | |||||
| private static final String ONE_NESTED_MESSAGE | |||||
| = "ResourceCount can count resources from exactly one nested ResourceCollection."; | |||||
| private static final String COUNT_REQUIRED | |||||
| = "Use of the ResourceCount condition requires that the count attribute be set."; | |||||
| private ResourceCollection rc; | |||||
| private Comparison when = Comparison.EQUAL; | |||||
| private Integer count; | |||||
| private String property; | |||||
| /** | |||||
| * Add the ResourceCollection to count. | |||||
| * @param r the ResourceCollection to count. | |||||
| * @throws BuildException if already set. | |||||
| */ | |||||
| public void add(ResourceCollection r) { | |||||
| if (rc != null) { | |||||
| throw new BuildException(ONE_NESTED_MESSAGE); | |||||
| } | |||||
| rc = r; | |||||
| } | |||||
| /** | |||||
| * Set the ResourceCollection reference. | |||||
| * @param r the Reference. | |||||
| */ | |||||
| public void setRefid(Reference r) { | |||||
| Object o = r.getReferencedObject(); | |||||
| if (!(o instanceof ResourceCollection)) { | |||||
| throw new BuildException(r.getRefId() | |||||
| + " doesn\'t denote a ResourceCollection"); | |||||
| } | |||||
| add((ResourceCollection) o); | |||||
| } | |||||
| /** | |||||
| * Execute as a Task. | |||||
| */ | |||||
| public void execute() { | |||||
| if (rc == null) { | |||||
| throw new BuildException(ONE_NESTED_MESSAGE); | |||||
| } | |||||
| if (property == null) { | |||||
| log("resource count = " + rc.size()); | |||||
| } else { | |||||
| getProject().setNewProperty(property, Integer.toString(rc.size())); | |||||
| } | |||||
| } | |||||
| /** | |||||
| * Fulfill the condition contract. | |||||
| * @return true if the specified ResourceCollection satisfies the set criteria. | |||||
| * @throws BuildException if an error occurs. | |||||
| */ | |||||
| public boolean eval() { | |||||
| if (rc == null) { | |||||
| throw new BuildException(ONE_NESTED_MESSAGE); | |||||
| } | |||||
| if (count == null) { | |||||
| throw new BuildException(COUNT_REQUIRED); | |||||
| } | |||||
| return when.evaluate(new Integer(rc.size()).compareTo(count)); | |||||
| } | |||||
| /** | |||||
| * Set the target count number for use as a Condition. | |||||
| * @param c number of Resources as int. | |||||
| */ | |||||
| public void setCount(int c) { | |||||
| count = new Integer(c); | |||||
| } | |||||
| /** | |||||
| * Set the comparison for use as a Condition. | |||||
| * @param w EnumeratedAttribute When. | |||||
| * @see org.apache.tools.ant.types.Comparison | |||||
| */ | |||||
| public void setWhen(Comparison c) { | |||||
| when = c; | |||||
| } | |||||
| /** | |||||
| * Set the name of the property to set in task mode. | |||||
| * @param p the property name to set. | |||||
| */ | |||||
| public void setProperty(String p) { | |||||
| property = p; | |||||
| } | |||||
| } | |||||
| @@ -207,6 +207,7 @@ ildasm=org.apache.tools.ant.taskdefs.optional.dotnet.Ildasm | |||||
| apt=org.apache.tools.ant.taskdefs.Apt | apt=org.apache.tools.ant.taskdefs.Apt | ||||
| schemavalidate=org.apache.tools.ant.taskdefs.optional.SchemaValidate | schemavalidate=org.apache.tools.ant.taskdefs.optional.SchemaValidate | ||||
| verifyjar=org.apache.tools.ant.taskdefs.VerifyJar | verifyjar=org.apache.tools.ant.taskdefs.VerifyJar | ||||
| resourcecount=org.apache.tools.ant.taskdefs.ResourceCount | |||||
| # deprecated ant tasks (kept for back compatibility) | # deprecated ant tasks (kept for back compatibility) | ||||
| starteam=org.apache.tools.ant.taskdefs.optional.scm.AntStarTeamCheckOut | starteam=org.apache.tools.ant.taskdefs.optional.scm.AntStarTeamCheckOut | ||||
| @@ -0,0 +1,93 @@ | |||||
| /* | |||||
| * Copyright 2005 The Apache Software Foundation | |||||
| * | |||||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||||
| * you may not use this file except in compliance with the License. | |||||
| * You may obtain a copy of the License at | |||||
| * | |||||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||||
| * | |||||
| * Unless required by applicable law or agreed to in writing, software | |||||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
| * See the License for the specific language governing permissions and | |||||
| * limitations under the License. | |||||
| * | |||||
| */ | |||||
| package org.apache.tools.ant.types; | |||||
| import java.util.Arrays; | |||||
| import org.apache.tools.ant.BuildException; | |||||
| /** | |||||
| * EnumeratedAttribute for generic comparisons. Accepts values | |||||
| * "equal", "greater", "less", "ne" (not equal), "ge" (greater or equal), | |||||
| * "le" (less or equal), "eq" (equal), "gt" (greater), "lt" (less). | |||||
| * @since Ant 1.7 | |||||
| */ | |||||
| public class Comparison extends EnumeratedAttribute { | |||||
| private static final String[] VALUES | |||||
| = new String[] {"equal", "greater", "less", | |||||
| "ne", "ge", "le", "eq", "gt", "lt"}; | |||||
| /** Equal Comparison. */ | |||||
| public static final Comparison EQUAL = new Comparison("equal"); | |||||
| /** Not-Equal Comparison. */ | |||||
| public static final Comparison NOT_EQUAL = new Comparison("ne"); | |||||
| /** Greater Comparison. */ | |||||
| public static final Comparison GREATER = new Comparison("greater"); | |||||
| /** Less Comparison. */ | |||||
| public static final Comparison LESS = new Comparison("less"); | |||||
| /** Greater-or-Equal Comparison. */ | |||||
| public static final Comparison GREATER_EQUAL = new Comparison("ge"); | |||||
| /** Less-or-Equal Comparison. */ | |||||
| public static final Comparison LESS_EQUAL = new Comparison("le"); | |||||
| private static final int[] EQUAL_INDEX = {0, 4, 5, 6}; | |||||
| private static final int[] LESS_INDEX = {2, 3, 5, 8}; | |||||
| private static final int[] GREATER_INDEX = {1, 3, 4, 7}; | |||||
| /** | |||||
| * Default constructor. | |||||
| */ | |||||
| public Comparison() { | |||||
| } | |||||
| /** | |||||
| * Construct a new Comparison with the specified value. | |||||
| * @param value the EnumeratedAttribute value. | |||||
| */ | |||||
| public Comparison(String value) { | |||||
| setValue(value); | |||||
| } | |||||
| /** | |||||
| * Return the possible values. | |||||
| * @return String[] of EnumeratedAttribute values. | |||||
| */ | |||||
| public String[] getValues() { | |||||
| return VALUES; | |||||
| } | |||||
| /** | |||||
| * Evaluate a comparison result as from Comparator.compare() or Comparable.compareTo(). | |||||
| * @param comparisonResult the result to evaluate. | |||||
| * @return true if the comparison result fell within the parameters of this Comparison. | |||||
| */ | |||||
| public boolean evaluate(int comparisonResult) { | |||||
| if (getIndex() == -1) { | |||||
| throw new BuildException("Comparison value not set."); | |||||
| } | |||||
| int[] i = comparisonResult < 0 ? LESS_INDEX | |||||
| : comparisonResult > 0 ? GREATER_INDEX : EQUAL_INDEX; | |||||
| return Arrays.binarySearch(i, getIndex()) >= 0; | |||||
| } | |||||
| } | |||||
| @@ -17,13 +17,17 @@ | |||||
| package org.apache.tools.ant.types; | 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 | * Subclass as hint for supporting tasks that the included directories | ||||
| * instead of files should be used. | * instead of files should be used. | ||||
| * | * | ||||
| * @since Ant 1.5 | * @since Ant 1.5 | ||||
| */ | */ | ||||
| public class DirSet extends AbstractFileSet { | |||||
| public class DirSet extends AbstractFileSet implements ResourceCollection { | |||||
| /** | /** | ||||
| * Constructor for DirSet. | * Constructor for DirSet. | ||||
| @@ -53,4 +57,38 @@ public class DirSet extends AbstractFileSet { | |||||
| } | } | ||||
| } | } | ||||
| /** | |||||
| * Fulfill the ResourceCollection contract. | |||||
| * @return an Iterator of Resources. | |||||
| * @since Ant 1.7 | |||||
| */ | |||||
| public Iterator iterator() { | |||||
| if (isReference()) { | |||||
| return ((DirSet) getRef(getProject())).iterator(); | |||||
| } | |||||
| return new FileResourceIterator(getDir(getProject()), | |||||
| getDirectoryScanner(getProject()).getIncludedDirectories()); | |||||
| } | |||||
| /** | |||||
| * Fulfill the ResourceCollection contract. | |||||
| * @return number of elements as int. | |||||
| * @since Ant 1.7 | |||||
| */ | |||||
| public int size() { | |||||
| if (isReference()) { | |||||
| return ((DirSet) getRef(getProject())).size(); | |||||
| } | |||||
| return getDirectoryScanner(getProject()).getIncludedDirsCount(); | |||||
| } | |||||
| /** | |||||
| * Always returns true. | |||||
| * @return true indicating that all elements will be FileResources. | |||||
| * @since Ant 1.7 | |||||
| */ | |||||
| public boolean isFilesystemOnly() { | |||||
| return true; | |||||
| } | |||||
| } | } | ||||
| @@ -1,5 +1,5 @@ | |||||
| /* | /* | ||||
| * Copyright 2001-2002,2004 The Apache Software Foundation | |||||
| * Copyright 2001-2002,2004-2005 The Apache Software Foundation | |||||
| * | * | ||||
| * Licensed under the Apache License, Version 2.0 (the "License"); | * Licensed under the Apache License, Version 2.0 (the "License"); | ||||
| * you may not use this file except in compliance with 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.Stack; | ||||
| import java.util.StringTokenizer; | import java.util.StringTokenizer; | ||||
| import java.util.Vector; | 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.Project; | ||||
| import org.apache.tools.ant.BuildException; | |||||
| import org.apache.tools.ant.types.resources.FileResourceIterator; | |||||
| /** | /** | ||||
| * FileList represents an explicitly named list of files. FileLists | * 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 | * filter, only returning the name of a matched file if it currently | ||||
| * exists in the file system. | * exists in the file system. | ||||
| */ | */ | ||||
| public class FileList extends DataType { | |||||
| public class FileList extends DataType implements ResourceCollection { | |||||
| private Vector filenames = new Vector(); | private Vector filenames = new Vector(); | ||||
| private File dir; | private File dir; | ||||
| @@ -78,9 +81,7 @@ public class FileList extends DataType { | |||||
| * @exception BuildException if an error occurs | * @exception BuildException if an error occurs | ||||
| */ | */ | ||||
| public void setDir(File dir) throws BuildException { | public void setDir(File dir) throws BuildException { | ||||
| if (isReference()) { | |||||
| throw tooManyAttributes(); | |||||
| } | |||||
| checkAttributesAllowed(); | |||||
| this.dir = dir; | this.dir = dir; | ||||
| } | } | ||||
| @@ -102,9 +103,7 @@ public class FileList extends DataType { | |||||
| * by whitespace. | * by whitespace. | ||||
| */ | */ | ||||
| public void setFiles(String filenames) { | public void setFiles(String filenames) { | ||||
| if (isReference()) { | |||||
| throw tooManyAttributes(); | |||||
| } | |||||
| checkAttributesAllowed(); | |||||
| if (filenames != null && filenames.length() > 0) { | if (filenames != null && filenames.length() > 0) { | ||||
| StringTokenizer tok = new StringTokenizer( | StringTokenizer tok = new StringTokenizer( | ||||
| filenames, ", \t\n\r\f", false); | filenames, ", \t\n\r\f", false); | ||||
| @@ -144,19 +143,7 @@ public class FileList extends DataType { | |||||
| * @return the FileList represented by a referenced filelist. | * @return the FileList represented by a referenced filelist. | ||||
| */ | */ | ||||
| protected FileList getRef(Project p) { | 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()); | filenames.addElement(name.getName()); | ||||
| } | } | ||||
| /** | |||||
| * Fulfill the ResourceCollection contract. | |||||
| * @return an Iterator of Resources. | |||||
| * @since Ant 1.7 | |||||
| */ | |||||
| public Iterator iterator() { | |||||
| if (isReference()) { | |||||
| return ((FileList) getRef(getProject())).iterator(); | |||||
| } | |||||
| return new FileResourceIterator(dir, | |||||
| (String[]) (filenames.toArray(new String[filenames.size()]))); | |||||
| } | |||||
| /** | |||||
| * Fulfill the ResourceCollection contract. | |||||
| * @return number of elements as int. | |||||
| * @since Ant 1.7 | |||||
| */ | |||||
| public int size() { | |||||
| if (isReference()) { | |||||
| return ((FileList) getRef(getProject())).size(); | |||||
| } | |||||
| return filenames.size(); | |||||
| } | |||||
| /** | |||||
| * Always returns true. | |||||
| * @return true indicating that all elements will be FileResources. | |||||
| * @since Ant 1.7 | |||||
| */ | |||||
| public boolean isFilesystemOnly() { | |||||
| return true; | |||||
| } | |||||
| } | } | ||||
| @@ -17,12 +17,16 @@ | |||||
| package org.apache.tools.ant.types; | 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 | * Moved out of MatchingTask to make it a standalone object that could | ||||
| * be referenced (by scripts for example). | * be referenced (by scripts for example). | ||||
| * | * | ||||
| */ | */ | ||||
| public class FileSet extends AbstractFileSet { | |||||
| public class FileSet extends AbstractFileSet implements ResourceCollection { | |||||
| /** | /** | ||||
| * Constructor for FileSet. | * Constructor for FileSet. | ||||
| @@ -52,4 +56,38 @@ public class FileSet extends AbstractFileSet { | |||||
| } | } | ||||
| } | } | ||||
| /** | |||||
| * Fulfill the ResourceCollection contract. | |||||
| * @return an Iterator of Resources. | |||||
| * @since Ant 1.7 | |||||
| */ | |||||
| public Iterator iterator() { | |||||
| if (isReference()) { | |||||
| return ((FileSet) getRef(getProject())).iterator(); | |||||
| } | |||||
| return new FileResourceIterator(getDir(getProject()), | |||||
| getDirectoryScanner(getProject()).getIncludedFiles()); | |||||
| } | |||||
| /** | |||||
| * Fulfill the ResourceCollection contract. | |||||
| * @return number of elements as int. | |||||
| * @since Ant 1.7 | |||||
| */ | |||||
| public int size() { | |||||
| if (isReference()) { | |||||
| return ((FileSet) getRef(getProject())).size(); | |||||
| } | |||||
| return getDirectoryScanner(getProject()).getIncludedFilesCount(); | |||||
| } | |||||
| /** | |||||
| * Always returns true. | |||||
| * @return true indicating that all elements will be FileResources. | |||||
| * @since Ant 1.7 | |||||
| */ | |||||
| public boolean isFilesystemOnly() { | |||||
| return true; | |||||
| } | |||||
| } | } | ||||
| @@ -18,17 +18,22 @@ | |||||
| package org.apache.tools.ant.types; | package org.apache.tools.ant.types; | ||||
| import java.io.File; | import java.io.File; | ||||
| import java.util.Enumeration; | |||||
| import java.util.Locale; | |||||
| import java.util.Set; | |||||
| import java.util.Stack; | import java.util.Stack; | ||||
| import java.util.Locale; | |||||
| import java.util.Vector; | 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.BuildException; | ||||
| import org.apache.tools.ant.PathTokenizer; | import org.apache.tools.ant.PathTokenizer; | ||||
| import org.apache.tools.ant.Project; | 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.FileUtils; | ||||
| import org.apache.tools.ant.util.JavaEnvUtils; | import org.apache.tools.ant.util.JavaEnvUtils; | ||||
| /** | /** | ||||
| * This object represents a path as used by CLASSPATH or PATH | * This object represents a path as used by CLASSPATH or PATH | ||||
| * environment variable. | * 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 = | public static Path systemClasspath = | ||||
| new Path(null, System.getProperty("java.class.path")); | 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 | * @since Ant 1.6.2 | ||||
| */ | */ | ||||
| public static Path systemBootClasspath = | public static Path systemBootClasspath = | ||||
| new Path(null, System.getProperty("sun.boot.class.path")); | new Path(null, System.getProperty("sun.boot.class.path")); | ||||
| /** | /** | ||||
| * Helper class, holds the nested <code><pathelement></code> values. | * Helper class, holds the nested <code><pathelement></code> values. | ||||
| */ | */ | ||||
| public class PathElement { | |||||
| public class PathElement implements ResourceCollection { | |||||
| private String[] parts; | private String[] parts; | ||||
| /** | /** | ||||
| @@ -106,6 +108,19 @@ public class Path extends DataType implements Cloneable { | |||||
| public String[] getParts() { | public String[] getParts() { | ||||
| return parts; | 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) { | public Path(Project project) { | ||||
| setProject(project); | setProject(project); | ||||
| elements = new Vector(); | |||||
| } | } | ||||
| /** | /** | ||||
| @@ -135,22 +149,17 @@ public class Path extends DataType implements Cloneable { | |||||
| * @throws BuildException on error | * @throws BuildException on error | ||||
| */ | */ | ||||
| public void setLocation(File location) throws BuildException { | public void setLocation(File location) throws BuildException { | ||||
| if (isReference()) { | |||||
| throw tooManyAttributes(); | |||||
| } | |||||
| checkAttributesAllowed(); | |||||
| createPathElement().setLocation(location); | createPathElement().setLocation(location); | ||||
| } | } | ||||
| /** | /** | ||||
| * Parses a path definition and creates single PathElements. | * Parses a path definition and creates single PathElements. | ||||
| * @param path the <code>String</code> path definition. | * @param path the <code>String</code> path definition. | ||||
| * @throws BuildException on error | * @throws BuildException on error | ||||
| */ | */ | ||||
| public void setPath(String path) throws BuildException { | public void setPath(String path) throws BuildException { | ||||
| if (isReference()) { | |||||
| throw tooManyAttributes(); | |||||
| } | |||||
| checkAttributesAllowed(); | |||||
| createPathElement().setPath(path); | createPathElement().setPath(path); | ||||
| } | } | ||||
| @@ -163,10 +172,9 @@ public class Path extends DataType implements Cloneable { | |||||
| * @throws BuildException on error | * @throws BuildException on error | ||||
| */ | */ | ||||
| public void setRefid(Reference r) throws BuildException { | public void setRefid(Reference r) throws BuildException { | ||||
| if (!elements.isEmpty()) { | |||||
| if (!getResourceCollections().isEmpty()) { | |||||
| throw tooManyAttributes(); | throw tooManyAttributes(); | ||||
| } | } | ||||
| elements.addElement(r); | |||||
| super.setRefid(r); | super.setRefid(r); | ||||
| } | } | ||||
| @@ -180,7 +188,7 @@ public class Path extends DataType implements Cloneable { | |||||
| throw noChildrenAllowed(); | throw noChildrenAllowed(); | ||||
| } | } | ||||
| PathElement pe = new PathElement(); | PathElement pe = new PathElement(); | ||||
| elements.addElement(pe); | |||||
| add(pe); | |||||
| return pe; | return pe; | ||||
| } | } | ||||
| @@ -190,11 +198,7 @@ public class Path extends DataType implements Cloneable { | |||||
| * @throws BuildException on error | * @throws BuildException on error | ||||
| */ | */ | ||||
| public void addFileset(FileSet fs) throws BuildException { | 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 | * @throws BuildException on error | ||||
| */ | */ | ||||
| public void addFilelist(FileList fl) throws BuildException { | 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 | * @throws BuildException on error | ||||
| */ | */ | ||||
| public void addDirset(DirSet dset) throws BuildException { | 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 | * @since Ant 1.6 | ||||
| */ | */ | ||||
| public void add(Path path) throws BuildException { | 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 | * @throws BuildException on error | ||||
| */ | */ | ||||
| public Path createPath() throws BuildException { | public Path createPath() throws BuildException { | ||||
| if (isReference()) { | |||||
| throw noChildrenAllowed(); | |||||
| } | |||||
| Path p = new Path(getProject()); | Path p = new Path(getProject()); | ||||
| elements.addElement(p); | |||||
| setChecked(false); | |||||
| add(p); | |||||
| return p; | return p; | ||||
| } | } | ||||
| @@ -261,17 +248,12 @@ public class Path extends DataType implements Cloneable { | |||||
| if (other == null) { | if (other == null) { | ||||
| return; | 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 | * 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 | * @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) { | if (p.getProject() == null) { | ||||
| p.setProject(getProject()); | 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; | 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. | * 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); | (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 | * Concatenates the system class path in the order specified by | ||||
| * the ${build.sysclasspath} property - using "last" as | * the ${build.sysclasspath} property - using "last" as | ||||
| @@ -737,4 +579,5 @@ public class Path extends DataType implements Cloneable { | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| @@ -30,6 +30,8 @@ import java.util.Vector; | |||||
| import org.apache.tools.ant.BuildException; | import org.apache.tools.ant.BuildException; | ||||
| import org.apache.tools.ant.Project; | 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.FileNameMapper; | ||||
| import org.apache.tools.ant.util.regexp.RegexpMatcher; | import org.apache.tools.ant.util.regexp.RegexpMatcher; | ||||
| import org.apache.tools.ant.util.regexp.RegexpMatcherFactory; | import org.apache.tools.ant.util.regexp.RegexpMatcherFactory; | ||||
| @@ -39,7 +41,7 @@ import org.apache.tools.ant.util.regexp.RegexpMatcherFactory; | |||||
| * | * | ||||
| * @since Ant 1.6 | * @since Ant 1.6 | ||||
| */ | */ | ||||
| public class PropertySet extends DataType { | |||||
| public class PropertySet extends DataType implements ResourceCollection { | |||||
| private boolean dynamic = true; | private boolean dynamic = true; | ||||
| private boolean negate = false; | private boolean negate = false; | ||||
| @@ -463,4 +465,40 @@ public class PropertySet extends DataType { | |||||
| return b.toString(); | return b.toString(); | ||||
| } | } | ||||
| /** | |||||
| * Fulfill the ResourceCollection interface. | |||||
| * @return an Iterator of Resources. | |||||
| * @since Ant 1.7 | |||||
| */ | |||||
| public Iterator iterator() { | |||||
| final Enumeration e = getProperties().propertyNames(); | |||||
| return new Iterator() { | |||||
| public boolean hasNext() { | |||||
| return e.hasMoreElements(); | |||||
| } | |||||
| public Object next() { | |||||
| return new PropertyResource(getProject(), (String) e.nextElement()); | |||||
| } | |||||
| public void remove() { | |||||
| throw new UnsupportedOperationException(); | |||||
| } | |||||
| }; | |||||
| } | |||||
| /** | |||||
| * Fulfill the ResourceCollection contract. | |||||
| * @return the size of this ResourceCollection. | |||||
| */ | |||||
| public int size() { | |||||
| return isReference() ? getRef().size() : getProperties().size(); | |||||
| } | |||||
| /** | |||||
| * Fulfill the ResourceCollection contract. | |||||
| * @return whether this is a filesystem-only resource collection. | |||||
| */ | |||||
| public boolean isFilesystemOnly() { | |||||
| return isReference() && getRef().isFilesystemOnly(); | |||||
| } | |||||
| } | } | ||||
| @@ -16,24 +16,51 @@ | |||||
| */ | */ | ||||
| package org.apache.tools.ant.types; | 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 | * 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 | * and date/time information about a file, a zip entry or some similar | ||||
| * resource (URL, archive in a version control repository, ...). | * resource (URL, archive in a version control repository, ...). | ||||
| * | * | ||||
| * @since Ant 1.5.2 | * @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 */ | /** Constant unknown size */ | ||||
| public static final long UNKNOWN_SIZE = -1; | 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 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. | * Default constructor. | ||||
| @@ -112,7 +139,7 @@ public class Resource implements Cloneable, Comparable { | |||||
| * @return the name of this resource. | * @return the name of this resource. | ||||
| */ | */ | ||||
| public String getName() { | public String getName() { | ||||
| return name; | |||||
| return isReference() ? ((Resource) getCheckedRef()).getName() : name; | |||||
| } | } | ||||
| /** | /** | ||||
| @@ -121,6 +148,7 @@ public class Resource implements Cloneable, Comparable { | |||||
| * "/" to be used as the directory separator. | * "/" to be used as the directory separator. | ||||
| */ | */ | ||||
| public void setName(String name) { | public void setName(String name) { | ||||
| checkAttributesAllowed(); | |||||
| this.name = name; | this.name = name; | ||||
| } | } | ||||
| @@ -129,7 +157,11 @@ public class Resource implements Cloneable, Comparable { | |||||
| * @return true if this resource exists. | * @return true if this resource exists. | ||||
| */ | */ | ||||
| public boolean isExists() { | 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. | * @param exists if true, this resource exists. | ||||
| */ | */ | ||||
| public void setExists(boolean 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}. | * of {@link java.io.File File}. | ||||
| */ | */ | ||||
| public long getLastModified() { | 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. | * @param lastmodified the modification time in milliseconds since 01.01.1970. | ||||
| */ | */ | ||||
| public void setLastModified(long lastmodified) { | 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. | * @return boolean flag indicating if the resource is a directory. | ||||
| */ | */ | ||||
| public boolean isDirectory() { | 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. | * @param directory if true, this resource is a directory. | ||||
| */ | */ | ||||
| public void setDirectory(boolean directory) { | public void setDirectory(boolean directory) { | ||||
| this.directory = directory; | |||||
| checkAttributesAllowed(); | |||||
| this.directory = directory ? Boolean.TRUE : Boolean.FALSE; | |||||
| } | } | ||||
| /** | /** | ||||
| * Set the size of this Resource. | * Set the size of this Resource. | ||||
| * @param size the size, as a long. | * @param size the size, as a long. | ||||
| * @since Ant 1.7 | |||||
| * @since Ant 1.6.3 | |||||
| */ | */ | ||||
| public void setSize(long size) { | 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. | * Get the size of this Resource. | ||||
| * @return the size, as a long, 0 if the Resource does not exist (for | * @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. | * compatibility with java.io.File), or UNKNOWN_SIZE if not known. | ||||
| * @since Ant 1.7 | |||||
| * @since Ant 1.6.3 | |||||
| */ | */ | ||||
| public long getSize() { | 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 | * @since Ant 1.6 | ||||
| */ | */ | ||||
| public int compareTo(Object other) { | public int compareTo(Object other) { | ||||
| if (isReference()) { | |||||
| return ((Comparable) getCheckedRef()).compareTo(other); | |||||
| } | |||||
| if (!(other instanceof Resource)) { | 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; | Resource r = (Resource) other; | ||||
| return getName().compareTo(r.getName()); | |||||
| String name = getName(); | |||||
| String oname = r.getName(); | |||||
| if (name == null && oname == null) { | |||||
| return 0; | |||||
| } | |||||
| if (name == null) { | |||||
| return -1; | |||||
| } | |||||
| return oname == null ? 1 : name.compareTo(oname); | |||||
| } | |||||
| /** | |||||
| * Implement basic Resource equality. | |||||
| * @return true if the specified Object is equal to this Resource. | |||||
| * @since Ant 1.7 | |||||
| */ | |||||
| public boolean equals(Object other) { | |||||
| if (isReference()) { | |||||
| return getCheckedRef().equals(other); | |||||
| } | |||||
| return other.getClass().equals(getClass()) && compareTo(other) == 0; | |||||
| } | |||||
| /** | |||||
| * Get the hash code for this Resource. | |||||
| * @return hash code as int. | |||||
| * @since Ant 1.7 | |||||
| */ | |||||
| public int hashCode() { | |||||
| if (isReference()) { | |||||
| return getCheckedRef().hashCode(); | |||||
| } | |||||
| String name = getName(); | |||||
| return MAGIC * (name == null ? name.hashCode() : NULL_NAME); | |||||
| } | |||||
| /** | |||||
| * Get an InputStream for the Resource. | |||||
| * @return an InputStream containing this Resource's content. | |||||
| * @throws IOException if unable to provide the content of this | |||||
| * Resource as a stream. | |||||
| * @throws UnsupportedOperationException if InputStreams are not | |||||
| * supported for this Resource type. | |||||
| * @since Ant 1.7 | |||||
| */ | |||||
| public InputStream getInputStream() throws IOException { | |||||
| if (isReference()) { | |||||
| return ((Resource) getCheckedRef()).getInputStream(); | |||||
| } | |||||
| throw new UnsupportedOperationException(); | |||||
| } | |||||
| /** | |||||
| * Get an OutputStream for the Resource. | |||||
| * @return an OutputStream to which content can be written. | |||||
| * @throws IOException if unable to provide the content of this | |||||
| * Resource as a stream. | |||||
| * @throws UnsupportedOperationException if OutputStreams are not | |||||
| * supported for this Resource type. | |||||
| * @since Ant 1.7 | |||||
| */ | |||||
| public OutputStream getOutputStream() throws IOException { | |||||
| if (isReference()) { | |||||
| return ((Resource) getCheckedRef()).getOutputStream(); | |||||
| } | |||||
| throw new UnsupportedOperationException(); | |||||
| } | |||||
| /** | |||||
| * Fulfill the ResourceCollection contract. | |||||
| * @return an Iterator of Resources. | |||||
| * @since Ant 1.7 | |||||
| */ | |||||
| public Iterator iterator() { | |||||
| return isReference() ? ((Resource) getCheckedRef()).iterator() | |||||
| : new Iterator() { | |||||
| boolean done = false; | |||||
| public boolean hasNext() { | |||||
| return !done; | |||||
| } | |||||
| public Object next() { | |||||
| if (done) { | |||||
| throw new NoSuchElementException(); | |||||
| } | |||||
| done = true; | |||||
| return Resource.this; | |||||
| } | |||||
| public void remove() { | |||||
| throw new UnsupportedOperationException(); | |||||
| } | |||||
| }; | |||||
| } | |||||
| /** | |||||
| * Fulfill the ResourceCollection contract. | |||||
| * @return the size of this ResourceCollection. | |||||
| * @since Ant 1.7 | |||||
| */ | |||||
| public int size() { | |||||
| return isReference() ? ((Resource) getCheckedRef()).size() : 1; | |||||
| } | |||||
| /** | |||||
| * Fulfill the ResourceCollection contract. | |||||
| * @return whether this Resource is a FileResource. | |||||
| * @since Ant 1.7 | |||||
| */ | |||||
| public boolean isFilesystemOnly() { | |||||
| //default false: | |||||
| return isReference() && ((Resource) getCheckedRef()).isFilesystemOnly(); | |||||
| } | |||||
| /** | |||||
| * Get the string representation of this Resource. | |||||
| * @return this Resource formatted as a String. | |||||
| * @since Ant 1.7 | |||||
| */ | |||||
| public String toString() { | |||||
| if (isReference()) { | |||||
| return getCheckedRef().toString(); | |||||
| } | |||||
| String n = getName(); | |||||
| if (n != null) { | |||||
| return n; | |||||
| } | |||||
| String classname = getClass().getName(); | |||||
| return "anonymous " + classname.substring(classname.lastIndexOf('.') + 1); | |||||
| } | |||||
| /** | |||||
| * Get a long String representation of this Resource. | |||||
| * This typically should be the value of <code>toString()</code> | |||||
| * prefixed by a type description. | |||||
| * @return this Resource formatted as a long String. | |||||
| * @since Ant 1.7 | |||||
| */ | |||||
| public final String toLongString() { | |||||
| return isReference() ? ((Resource) getCheckedRef()).toLongString() | |||||
| : getDataTypeName() + " \"" + toString() + '"'; | |||||
| } | |||||
| /** | |||||
| * Overrides the base version. | |||||
| * @param r the Reference to set. | |||||
| */ | |||||
| public void setRefid(Reference r) { | |||||
| if (name != null | |||||
| || exists != null | |||||
| || lastmodified != null | |||||
| || directory != null | |||||
| || size != null) { | |||||
| throw tooManyAttributes(); | |||||
| } | |||||
| super.setRefid(r); | |||||
| } | } | ||||
| } | } | ||||
| @@ -0,0 +1,49 @@ | |||||
| /* | |||||
| * Copyright 2005 The Apache Software Foundation | |||||
| * | |||||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||||
| * you may not use this file except in compliance with the License. | |||||
| * You may obtain a copy of the License at | |||||
| * | |||||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||||
| * | |||||
| * Unless required by applicable law or agreed to in writing, software | |||||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
| * See the License for the specific language governing permissions and | |||||
| * limitations under the License. | |||||
| * | |||||
| */ | |||||
| package org.apache.tools.ant.types; | |||||
| import java.util.Iterator; | |||||
| /** | |||||
| * Interface describing a collection of Resources. | |||||
| * @since Ant 1.7 | |||||
| */ | |||||
| public interface ResourceCollection { | |||||
| /** | |||||
| * Get an Iterator over the contents of this ResourceCollection, whose elements | |||||
| * are <code>org.apache.tools.ant.types.Resource</code> instances. | |||||
| * @return an Iterator of Resources. | |||||
| */ | |||||
| public Iterator iterator(); | |||||
| /** | |||||
| * Learn the number of contained Resources. | |||||
| * @return number of elements as int. | |||||
| */ | |||||
| public int size(); | |||||
| /** | |||||
| * Indicate whether this ResourceCollection is composed entirely of | |||||
| * Resources accessible via local filesystem conventions. If true, | |||||
| * all Resources returned from this ResourceCollection should be | |||||
| * instances of FileResource. | |||||
| * @return whether this is a filesystem-only resource collection. | |||||
| */ | |||||
| public boolean isFilesystemOnly(); | |||||
| } | |||||
| @@ -18,6 +18,7 @@ package org.apache.tools.ant.types; | |||||
| import java.io.File; | import java.io.File; | ||||
| import java.util.Stack; | import java.util.Stack; | ||||
| import java.util.Iterator; | |||||
| import org.apache.tools.ant.BuildException; | import org.apache.tools.ant.BuildException; | ||||
| import org.apache.tools.ant.DirectoryScanner; | import org.apache.tools.ant.DirectoryScanner; | ||||
| import org.apache.tools.ant.Project; | import org.apache.tools.ant.Project; | ||||
| @@ -62,6 +63,8 @@ public class ZipFileSet extends FileSet { | |||||
| private boolean fileModeHasBeenSet = false; | private boolean fileModeHasBeenSet = false; | ||||
| private boolean dirModeHasBeenSet = false; | private boolean dirModeHasBeenSet = false; | ||||
| private String encoding = null; | |||||
| /** Constructor for ZipFileSet */ | /** Constructor for ZipFileSet */ | ||||
| public ZipFileSet() { | public ZipFileSet() { | ||||
| super(); | super(); | ||||
| @@ -89,6 +92,7 @@ public class ZipFileSet extends FileSet { | |||||
| dirMode = fileset.dirMode; | dirMode = fileset.dirMode; | ||||
| fileModeHasBeenSet = fileset.fileModeHasBeenSet; | fileModeHasBeenSet = fileset.fileModeHasBeenSet; | ||||
| dirModeHasBeenSet = fileset.dirModeHasBeenSet; | dirModeHasBeenSet = fileset.dirModeHasBeenSet; | ||||
| encoding = fileset.encoding; | |||||
| } | } | ||||
| /** | /** | ||||
| @@ -98,9 +102,7 @@ public class ZipFileSet extends FileSet { | |||||
| * @throws BuildException on error | * @throws BuildException on error | ||||
| */ | */ | ||||
| public void setDir(File dir) throws BuildException { | public void setDir(File dir) throws BuildException { | ||||
| if (isReference()) { | |||||
| throw tooManyAttributes(); | |||||
| } | |||||
| checkAttributesAllowed(); | |||||
| if (srcFile != null) { | if (srcFile != null) { | ||||
| throw new BuildException("Cannot set both dir and src attributes"); | throw new BuildException("Cannot set both dir and src attributes"); | ||||
| } else { | } else { | ||||
| @@ -116,9 +118,7 @@ public class ZipFileSet extends FileSet { | |||||
| * @param srcFile The zip file from which to extract entries. | * @param srcFile The zip file from which to extract entries. | ||||
| */ | */ | ||||
| public void setSrc(File srcFile) { | public void setSrc(File srcFile) { | ||||
| if (isReference()) { | |||||
| throw tooManyAttributes(); | |||||
| } | |||||
| checkAttributesAllowed(); | |||||
| if (hasDir) { | if (hasDir) { | ||||
| throw new BuildException("Cannot set both dir and src attributes"); | throw new BuildException("Cannot set both dir and src attributes"); | ||||
| } | } | ||||
| @@ -189,6 +189,24 @@ public class ZipFileSet extends FileSet { | |||||
| return fullpath; | 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. | * Return the DirectoryScanner associated with this FileSet. | ||||
| * If the ZipFileSet defines a source Zip file, then a ZipScanner | * If the ZipFileSet defines a source Zip file, then a ZipScanner | ||||
| @@ -200,16 +218,60 @@ public class ZipFileSet extends FileSet { | |||||
| if (isReference()) { | if (isReference()) { | ||||
| return getRef(p).getDirectoryScanner(p); | 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); | 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 | * @return the abstract fileset instance | ||||
| */ | */ | ||||
| protected AbstractFileSet getRef(Project p) { | protected AbstractFileSet getRef(Project p) { | ||||
| if (!isChecked()) { | |||||
| Stack stk = new Stack(); | |||||
| stk.push(this); | |||||
| dieOnCircularReference(stk, p); | |||||
| } | |||||
| dieOnCircularReference(p); | |||||
| Object o = getRefid().getReferencedObject(p); | Object o = getRefid().getReferencedObject(p); | ||||
| if (o instanceof ZipFileSet) { | if (o instanceof ZipFileSet) { | ||||
| return (AbstractFileSet) o; | return (AbstractFileSet) o; | ||||
| @@ -319,6 +377,7 @@ public class ZipFileSet extends FileSet { | |||||
| throw new BuildException(msg); | throw new BuildException(msg); | ||||
| } | } | ||||
| } | } | ||||
| /** | /** | ||||
| * Return a ZipFileSet that has the same properties | * Return a ZipFileSet that has the same properties | ||||
| * as this one. | * as this one. | ||||
| @@ -19,14 +19,20 @@ package org.apache.tools.ant.types; | |||||
| import java.io.File; | import java.io.File; | ||||
| import java.io.IOException; | 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.Hashtable; | ||||
| import java.util.Comparator; | |||||
| import java.util.Collections; | |||||
| import java.util.Enumeration; | import java.util.Enumeration; | ||||
| import java.util.zip.ZipException; | import java.util.zip.ZipException; | ||||
| import org.apache.tools.ant.BuildException; | import org.apache.tools.ant.BuildException; | ||||
| import org.apache.tools.ant.DirectoryScanner; | 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.ZipEntry; | ||||
| import org.apache.tools.zip.ZipFile; | import org.apache.tools.zip.ZipFile; | ||||
| @@ -44,14 +50,31 @@ public class ZipScanner extends DirectoryScanner { | |||||
| * The zip file which should be scanned. | * The zip file which should be scanned. | ||||
| */ | */ | ||||
| protected File srcFile; | protected File srcFile; | ||||
| /** | /** | ||||
| * to record the last scanned zip file with its modification date | * to record the last scanned zip file with its modification date | ||||
| */ | */ | ||||
| private Resource lastScannedResource; | 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. | * encoding of file names. | ||||
| @@ -60,6 +83,17 @@ public class ZipScanner extends DirectoryScanner { | |||||
| */ | */ | ||||
| private String encoding; | 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 | * Sets the srcFile for scanning. This is the jar or zip file that | ||||
| * is scanned for matching entries. | * is scanned for matching entries. | ||||
| @@ -88,23 +122,25 @@ public class ZipScanner extends DirectoryScanner { | |||||
| * include patterns and none of the exclude patterns. | * include patterns and none of the exclude patterns. | ||||
| */ | */ | ||||
| public String[] getIncludedFiles() { | 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(); | 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. | * include patterns and none of the exclude patterns. | ||||
| */ | */ | ||||
| public String[] getIncludedDirectories() { | 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(); | 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 | * @param name path name of the file sought in the archive | ||||
| * @return the resource | * @return the resource | ||||
| * @since Ant 1.5.2 | * @since Ant 1.5.2 | ||||
| @@ -172,34 +237,35 @@ public class ZipScanner extends DirectoryScanner { | |||||
| public Resource getResource(String name) { | public Resource getResource(String name) { | ||||
| if (srcFile == null) { | if (srcFile == null) { | ||||
| return super.getResource(name); | return super.getResource(name); | ||||
| } else if (name.equals("")) { | |||||
| } | |||||
| if (name.equals("")) { | |||||
| // special case in ZIPs, we do not want this thing included | // special case in ZIPs, we do not want this thing included | ||||
| return new Resource("", true, Long.MAX_VALUE, true); | return new Resource("", true, Long.MAX_VALUE, true); | ||||
| } | } | ||||
| // first check if the archive needs to be scanned again | // first check if the archive needs to be scanned again | ||||
| scanme(); | 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 | * if the datetime of the archive did not change since | ||||
| * lastScannedResource was initialized returns immediately else if | * lastScannedResource was initialized returns immediately else if | ||||
| * the archive has not been scanned yet, then all the zip entries | * 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() { | private void scanme() { | ||||
| //do not use a FileResource b/c it pulls File info from the filesystem: | |||||
| Resource thisresource = new Resource(srcFile.getAbsolutePath(), | Resource thisresource = new Resource(srcFile.getAbsolutePath(), | ||||
| srcFile.exists(), | srcFile.exists(), | ||||
| srcFile.lastModified()); | srcFile.lastModified()); | ||||
| // spare scanning again and again | // spare scanning again and again | ||||
| if (lastScannedResource != null | if (lastScannedResource != null | ||||
| && lastScannedResource.getName().equals(thisresource.getName()) | && lastScannedResource.getName().equals(thisresource.getName()) | ||||
| @@ -207,10 +273,15 @@ public class ZipScanner extends DirectoryScanner { | |||||
| == thisresource.getLastModified()) { | == thisresource.getLastModified()) { | ||||
| return; | return; | ||||
| } | } | ||||
| init(); | |||||
| ZipEntry entry = null; | ZipEntry entry = null; | ||||
| ZipFile zf = null; | ZipFile zf = null; | ||||
| myentries = new Hashtable(); | |||||
| fileEntries.clear(); | |||||
| dirEntries.clear(); | |||||
| matchFileEntries.clear(); | |||||
| matchDirEntries.clear(); | |||||
| try { | try { | ||||
| try { | try { | ||||
| zf = new ZipFile(srcFile, encoding); | zf = new ZipFile(srcFile, encoding); | ||||
| @@ -219,15 +290,23 @@ public class ZipScanner extends DirectoryScanner { | |||||
| } catch (IOException ex) { | } catch (IOException ex) { | ||||
| throw new BuildException("problem opening " + srcFile, ex); | throw new BuildException("problem opening " + srcFile, ex); | ||||
| } | } | ||||
| Enumeration e = zf.getEntries(); | Enumeration e = zf.getEntries(); | ||||
| while (e.hasMoreElements()) { | while (e.hasMoreElements()) { | ||||
| entry = (ZipEntry) e.nextElement(); | 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 { | } finally { | ||||
| if (zf != null) { | if (zf != null) { | ||||
| @@ -241,4 +320,9 @@ public class ZipScanner extends DirectoryScanner { | |||||
| // record data about the last scanned resource | // record data about the last scanned resource | ||||
| lastScannedResource = thisresource; | lastScannedResource = thisresource; | ||||
| } | } | ||||
| private static String trimSeparator(String s) { | |||||
| return s.endsWith("/") ? s.substring(0, s.length() - 1) : s; | |||||
| } | |||||
| } | } | ||||
| @@ -1,8 +1,4 @@ | |||||
| classfileset=org.apache.tools.ant.types.optional.depend.ClassfileSet | |||||
| description=org.apache.tools.ant.types.Description | 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 | filterchain=org.apache.tools.ant.types.FilterChain | ||||
| filterreader=org.apache.tools.ant.types.AntFilterReader | filterreader=org.apache.tools.ant.types.AntFilterReader | ||||
| filterset=org.apache.tools.ant.types.FilterSet | 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 | chainedmapper=org.apache.tools.ant.util.ChainedMapper | ||||
| filtermapper=org.apache.tools.ant.types.mappers.FilterMapper | filtermapper=org.apache.tools.ant.types.mappers.FilterMapper | ||||
| path=org.apache.tools.ant.types.Path | |||||
| patternset=org.apache.tools.ant.types.PatternSet | patternset=org.apache.tools.ant.types.PatternSet | ||||
| regexp=org.apache.tools.ant.types.RegularExpression | regexp=org.apache.tools.ant.types.RegularExpression | ||||
| substitution=org.apache.tools.ant.types.Substitution | substitution=org.apache.tools.ant.types.Substitution | ||||
| xmlcatalog=org.apache.tools.ant.types.XMLCatalog | xmlcatalog=org.apache.tools.ant.types.XMLCatalog | ||||
| extensionSet=org.apache.tools.ant.taskdefs.optional.extension.ExtensionSet | extensionSet=org.apache.tools.ant.taskdefs.optional.extension.ExtensionSet | ||||
| extension=org.apache.tools.ant.taskdefs.optional.extension.ExtensionAdapter | 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 | selector=org.apache.tools.ant.types.selectors.SelectSelector | ||||
| signedselector=org.apache.tools.ant.types.selectors.SignedSelector | signedselector=org.apache.tools.ant.types.selectors.SignedSelector | ||||
| zipfileset=org.apache.tools.ant.types.ZipFileSet | |||||
| scriptfilter=org.apache.tools.ant.types.optional.ScriptFilter | scriptfilter=org.apache.tools.ant.types.optional.ScriptFilter | ||||
| propertyset=org.apache.tools.ant.types.PropertySet | |||||
| assertions=org.apache.tools.ant.types.Assertions | assertions=org.apache.tools.ant.types.Assertions | ||||
| concatfilter=org.apache.tools.ant.filters.ConcatFilter | concatfilter=org.apache.tools.ant.filters.ConcatFilter | ||||
| issigned=org.apache.tools.ant.taskdefs.condition.IsSigned | 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 | parsersupports=org.apache.tools.ant.taskdefs.condition.ParserSupports | ||||
| scriptmapper=org.apache.tools.ant.types.optional.ScriptMapper | scriptmapper=org.apache.tools.ant.types.optional.ScriptMapper | ||||
| isfailure=org.apache.tools.ant.taskdefs.condition.IsFailure | isfailure=org.apache.tools.ant.taskdefs.condition.IsFailure | ||||
| #ResourceCollections: | |||||
| dirset=org.apache.tools.ant.types.DirSet | |||||
| filelist=org.apache.tools.ant.types.FileList | |||||
| fileset=org.apache.tools.ant.types.FileSet | |||||
| path=org.apache.tools.ant.types.Path | |||||
| propertyset=org.apache.tools.ant.types.PropertySet | |||||
| zipfileset=org.apache.tools.ant.types.ZipFileSet | |||||
| classfileset=org.apache.tools.ant.types.optional.depend.ClassfileSet | |||||
| libfileset=org.apache.tools.ant.taskdefs.optional.extension.LibFileSet | |||||
| files=org.apache.tools.ant.types.resources.Files | |||||
| restrict=org.apache.tools.ant.types.resources.Restrict | |||||
| union=org.apache.tools.ant.types.resources.Union | |||||
| difference=org.apache.tools.ant.types.resources.Difference | |||||
| intersect=org.apache.tools.ant.types.resources.Intersect | |||||
| sort=org.apache.tools.ant.types.resources.Sort | |||||
| resources=org.apache.tools.ant.types.resources.Resources | |||||
| #Resources (single-element ResourceCollections): | |||||
| resource=org.apache.tools.ant.types.Resource | |||||
| file=org.apache.tools.ant.types.resources.FileResource | |||||
| url=org.apache.tools.ant.types.resources.URLResource | |||||
| string=org.apache.tools.ant.types.resources.StringResource | |||||
| zipentry=org.apache.tools.ant.types.resources.ZipResource | |||||
| propertyresource=org.apache.tools.ant.types.resources.PropertyResource | |||||
| @@ -0,0 +1,223 @@ | |||||
| /* | |||||
| * Copyright 2005 The Apache Software Foundation | |||||
| * | |||||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||||
| * you may not use this file except in compliance with the License. | |||||
| * You may obtain a copy of the License at | |||||
| * | |||||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||||
| * | |||||
| * Unless required by applicable law or agreed to in writing, software | |||||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
| * See the License for the specific language governing permissions and | |||||
| * limitations under the License. | |||||
| * | |||||
| */ | |||||
| package org.apache.tools.ant.types.resources; | |||||
| import java.io.File; | |||||
| import java.util.List; | |||||
| import java.util.Stack; | |||||
| import java.util.HashSet; | |||||
| import java.util.Iterator; | |||||
| import java.util.ArrayList; | |||||
| import java.util.Hashtable; | |||||
| import java.util.Collection; | |||||
| import java.util.Collections; | |||||
| import java.util.NoSuchElementException; | |||||
| import java.util.ConcurrentModificationException; | |||||
| import org.apache.tools.ant.Project; | |||||
| import org.apache.tools.ant.BuildException; | |||||
| import org.apache.tools.ant.types.DataType; | |||||
| import org.apache.tools.ant.types.Resource; | |||||
| import org.apache.tools.ant.types.ResourceCollection; | |||||
| /** | |||||
| * Base class for ResourceCollections that nest multiple ResourceCollections. | |||||
| * @since Ant 1.7 | |||||
| */ | |||||
| public abstract class BaseResourceCollectionContainer | |||||
| extends DataType implements ResourceCollection, Cloneable { | |||||
| private List rc = new ArrayList(); | |||||
| private Collection coll = null; | |||||
| /** | |||||
| * Add a ResourceCollection to the container. | |||||
| * @param c the ResourceCollection to add. | |||||
| * @throws BuildException on error. | |||||
| */ | |||||
| public synchronized void add(ResourceCollection c) throws BuildException { | |||||
| if (isReference()) { | |||||
| throw noChildrenAllowed(); | |||||
| } | |||||
| if (c == null) { | |||||
| return; | |||||
| } | |||||
| rc.add(c); | |||||
| FailFast.invalidate(this); | |||||
| coll = null; | |||||
| setChecked(false); | |||||
| } | |||||
| /** | |||||
| * Add the Collection of ResourceCollections to the container. | |||||
| * @param c the Collection whose elements to add. | |||||
| * @throws BuildException on error. | |||||
| */ | |||||
| public synchronized void addAll(Collection c) throws BuildException { | |||||
| if (isReference()) { | |||||
| throw noChildrenAllowed(); | |||||
| } | |||||
| try { | |||||
| for (Iterator i = c.iterator(); i.hasNext();) { | |||||
| add((ResourceCollection) i.next()); | |||||
| } | |||||
| } catch (ClassCastException e) { | |||||
| throw new BuildException(e); | |||||
| } | |||||
| } | |||||
| /** | |||||
| * Fulfill the ResourceCollection contract. The Iterator returned | |||||
| * will throw ConcurrentModificationExceptions if ResourceCollections | |||||
| * are added to this container while the Iterator is in use. | |||||
| * @return a "fail-fast" Iterator. | |||||
| */ | |||||
| public synchronized final Iterator iterator() { | |||||
| if (isReference()) { | |||||
| return ((BaseResourceCollectionContainer) getCheckedRef()).iterator(); | |||||
| } | |||||
| dieOnCircularReference(); | |||||
| cacheCollection(); | |||||
| return new FailFast(this, coll.iterator()); | |||||
| } | |||||
| /** | |||||
| * Fulfill the ResourceCollection contract. | |||||
| * @return number of elements as int. | |||||
| */ | |||||
| public synchronized int size() { | |||||
| if (isReference()) { | |||||
| return ((BaseResourceCollectionContainer) getCheckedRef()).size(); | |||||
| } | |||||
| dieOnCircularReference(); | |||||
| cacheCollection(); | |||||
| return coll.size(); | |||||
| } | |||||
| /** | |||||
| * Fulfill the ResourceCollection contract. | |||||
| * @return whether this is a filesystem-only resource collection. | |||||
| */ | |||||
| public synchronized boolean isFilesystemOnly() { | |||||
| if (isReference()) { | |||||
| return ((BaseResourceCollectionContainer) getCheckedRef()).isFilesystemOnly(); | |||||
| } | |||||
| dieOnCircularReference(); | |||||
| //first the easy way, if all children are filesystem-only, return true: | |||||
| boolean goEarly = true; | |||||
| for (Iterator i = rc.iterator(); goEarly && i.hasNext();) { | |||||
| goEarly &= ((ResourceCollection) i.next()).isFilesystemOnly(); | |||||
| } | |||||
| if (goEarly) { | |||||
| return true; | |||||
| } | |||||
| /* now check each Resource in case the child only | |||||
| lets through files from any children IT may have: */ | |||||
| cacheCollection(); | |||||
| for (Iterator i = coll.iterator(); i.hasNext();) { | |||||
| if (!(i.next() instanceof FileResource)) { | |||||
| return false; | |||||
| } | |||||
| } | |||||
| return true; | |||||
| } | |||||
| /** | |||||
| * Overrides the version of DataType to recurse on all DataType | |||||
| * child elements that may have been added. | |||||
| * @param stk the stack of data types to use (recursively). | |||||
| * @param p the project to use to dereference the references. | |||||
| * @throws BuildException on error. | |||||
| */ | |||||
| protected void dieOnCircularReference(Stack stk, Project p) | |||||
| throws BuildException { | |||||
| if (isChecked()) { | |||||
| return; | |||||
| } | |||||
| if (isReference()) { | |||||
| super.dieOnCircularReference(stk, p); | |||||
| } else { | |||||
| for (Iterator i = rc.iterator(); i.hasNext();) { | |||||
| Object o = i.next(); | |||||
| if (o instanceof DataType) { | |||||
| stk.push(o); | |||||
| invokeCircularReferenceCheck((DataType) o, stk, p); | |||||
| stk.pop(); | |||||
| } | |||||
| } | |||||
| setChecked(true); | |||||
| } | |||||
| } | |||||
| /** | |||||
| * Get the nested ResourceCollections. | |||||
| * @return List. | |||||
| */ | |||||
| protected synchronized final List getResourceCollections() { | |||||
| dieOnCircularReference(); | |||||
| return Collections.unmodifiableList(rc); | |||||
| } | |||||
| /** | |||||
| * Template method for subclasses to return a Collection object of Resources. | |||||
| * @return Collection. | |||||
| */ | |||||
| protected abstract Collection getCollection(); | |||||
| /** | |||||
| * Implement clone. The set of nested resource | |||||
| * collections is shallowly cloned. | |||||
| * @return a cloned instance. | |||||
| */ | |||||
| public Object clone() { | |||||
| try { | |||||
| BaseResourceCollectionContainer c | |||||
| = (BaseResourceCollectionContainer) super.clone(); | |||||
| c.rc = new ArrayList(rc); | |||||
| c.coll = null; | |||||
| return c; | |||||
| } catch (CloneNotSupportedException e) { | |||||
| throw new BuildException(e); | |||||
| } | |||||
| } | |||||
| /** | |||||
| * Format this BaseResourceCollectionContainer as a String. | |||||
| * @return a descriptive <code>String</code>. | |||||
| */ | |||||
| public String toString() { | |||||
| if (isReference()) { | |||||
| return getCheckedRef().toString(); | |||||
| } | |||||
| cacheCollection(); | |||||
| if (coll.size() == 0) { | |||||
| return ""; | |||||
| } | |||||
| StringBuffer sb = new StringBuffer(); | |||||
| for (Iterator i = coll.iterator(); i.hasNext();) { | |||||
| if (sb.length() > 0) { | |||||
| sb.append(File.pathSeparatorChar); | |||||
| } | |||||
| sb.append(i.next()); | |||||
| } | |||||
| return sb.toString(); | |||||
| } | |||||
| private synchronized void cacheCollection() { | |||||
| coll = (coll == null) ? getCollection() : coll; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,67 @@ | |||||
| /* | |||||
| * Copyright 2005 The Apache Software Foundation | |||||
| * | |||||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||||
| * you may not use this file except in compliance with the License. | |||||
| * You may obtain a copy of the License at | |||||
| * | |||||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||||
| * | |||||
| * Unless required by applicable law or agreed to in writing, software | |||||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
| * See the License for the specific language governing permissions and | |||||
| * limitations under the License. | |||||
| * | |||||
| */ | |||||
| package org.apache.tools.ant.types.resources; | |||||
| import java.util.List; | |||||
| import java.util.HashSet; | |||||
| import java.util.Iterator; | |||||
| import java.util.ArrayList; | |||||
| import java.util.Collection; | |||||
| import org.apache.tools.ant.Project; | |||||
| import org.apache.tools.ant.BuildException; | |||||
| import org.apache.tools.ant.types.ResourceCollection; | |||||
| /** | |||||
| * ResourceCollection representing the difference between | |||||
| * two or more nested ResourceCollections. | |||||
| * @since Ant 1.7 | |||||
| */ | |||||
| public class Difference extends BaseResourceCollectionContainer { | |||||
| /** | |||||
| * Calculate the difference of the nested ResourceCollections. | |||||
| * @return a Collection of Resources. | |||||
| */ | |||||
| protected Collection getCollection() { | |||||
| List rc = getResourceCollections(); | |||||
| int size = rc.size(); | |||||
| if (size < 2) { | |||||
| throw new BuildException("The difference of " + size | |||||
| + " resource collection" + ((size == 1) ? "" : "s") | |||||
| + " is undefined."); | |||||
| } | |||||
| HashSet hs = new HashSet(); | |||||
| ArrayList al = new ArrayList(); | |||||
| for (Iterator rcIter = rc.iterator(); rcIter.hasNext();) { | |||||
| for (Iterator r = nextRC(rcIter).iterator(); r.hasNext();) { | |||||
| Object next = r.next(); | |||||
| if (hs.add(next)) { | |||||
| al.add(next); | |||||
| } else { | |||||
| al.remove(next); | |||||
| } | |||||
| } | |||||
| } | |||||
| return al; | |||||
| } | |||||
| private static ResourceCollection nextRC(Iterator i) { | |||||
| return (ResourceCollection) i.next(); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,132 @@ | |||||
| /* | |||||
| * Copyright 2005 The Apache Software Foundation | |||||
| * | |||||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||||
| * you may not use this file except in compliance with the License. | |||||
| * You may obtain a copy of the License at | |||||
| * | |||||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||||
| * | |||||
| * Unless required by applicable law or agreed to in writing, software | |||||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
| * See the License for the specific language governing permissions and | |||||
| * limitations under the License. | |||||
| * | |||||
| */ | |||||
| package org.apache.tools.ant.types.resources; | |||||
| import java.util.Set; | |||||
| import java.util.HashSet; | |||||
| import java.util.Iterator; | |||||
| import java.util.WeakHashMap; | |||||
| import java.util.NoSuchElementException; | |||||
| import java.util.ConcurrentModificationException; | |||||
| /** | |||||
| * Helper class for ResourceCollections to return Iterators | |||||
| * that fail on changes to the object. | |||||
| * @since Ant 1.7 | |||||
| */ | |||||
| /*package-private*/ class FailFast implements Iterator { | |||||
| private static final WeakHashMap map = new WeakHashMap(); | |||||
| /** | |||||
| * Invalidate any in-use Iterators from the specified Object. | |||||
| * @param o the parent Object. | |||||
| */ | |||||
| static synchronized void invalidate(Object o) { | |||||
| Set s = (Set) (map.get(o)); | |||||
| if (s != null) { | |||||
| s.clear(); | |||||
| } | |||||
| } | |||||
| private static synchronized void add(FailFast f) { | |||||
| Set s = (Set) (map.get(f.parent)); | |||||
| if (s == null) { | |||||
| s = new HashSet(); | |||||
| map.put(f.parent, s); | |||||
| } | |||||
| s.add(f); | |||||
| } | |||||
| private static synchronized void remove(FailFast f) { | |||||
| Set s = (Set) (map.get(f.parent)); | |||||
| if (s != null) { | |||||
| s.remove(f); | |||||
| } | |||||
| } | |||||
| private static synchronized void failFast(FailFast f) { | |||||
| Set s = (Set) (map.get(f.parent)); | |||||
| if (!s.contains(f)) { | |||||
| throw new ConcurrentModificationException(); | |||||
| } | |||||
| } | |||||
| private Object parent; | |||||
| private Iterator wrapped; | |||||
| /** | |||||
| * Construct a new FailFast Iterator wrapping the specified Iterator | |||||
| * and dependent upon the specified parent Object. | |||||
| * @param o the parent Object. | |||||
| * @param i the wrapped Iterator. | |||||
| */ | |||||
| FailFast(Object o, Iterator i) { | |||||
| if (o == null) { | |||||
| throw new IllegalArgumentException("parent object is null"); | |||||
| } | |||||
| if (i == null) { | |||||
| throw new IllegalArgumentException("cannot wrap null iterator"); | |||||
| } | |||||
| parent = o; | |||||
| if (i.hasNext()) { | |||||
| wrapped = i; | |||||
| add(this); | |||||
| } | |||||
| } | |||||
| /** | |||||
| * Fulfill the Iterator contract. | |||||
| * @return true if there are more elements. | |||||
| */ | |||||
| public boolean hasNext() { | |||||
| if (wrapped == null) { | |||||
| return false; | |||||
| } | |||||
| failFast(this); | |||||
| return wrapped.hasNext(); | |||||
| } | |||||
| /** | |||||
| * Fulfill the Iterator contract. | |||||
| * @return the next element. | |||||
| * @throws NoSuchElementException if no more elements. | |||||
| */ | |||||
| public Object next() { | |||||
| if (wrapped == null || !wrapped.hasNext()) { | |||||
| throw new NoSuchElementException(); | |||||
| } | |||||
| failFast(this); | |||||
| try { | |||||
| return wrapped.next(); | |||||
| } finally { | |||||
| if (!wrapped.hasNext()) { | |||||
| wrapped = null; | |||||
| remove(this); | |||||
| } | |||||
| } | |||||
| } | |||||
| /** | |||||
| * Fulfill the Iterator contract. | |||||
| * @throws UnsupportedOperationException always. | |||||
| */ | |||||
| public void remove() { | |||||
| throw new UnsupportedOperationException(); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,300 @@ | |||||
| /* | |||||
| * Copyright 2005 The Apache Software Foundation | |||||
| * | |||||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||||
| * you may not use this file except in compliance with the License. | |||||
| * You may obtain a copy of the License at | |||||
| * | |||||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||||
| * | |||||
| * Unless required by applicable law or agreed to in writing, software | |||||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
| * See the License for the specific language governing permissions and | |||||
| * limitations under the License. | |||||
| * | |||||
| */ | |||||
| package org.apache.tools.ant.types.resources; | |||||
| import java.io.File; | |||||
| import java.io.IOException; | |||||
| import java.io.InputStream; | |||||
| import java.io.OutputStream; | |||||
| import java.io.FileInputStream; | |||||
| import java.io.FileOutputStream; | |||||
| import org.apache.tools.ant.Project; | |||||
| import org.apache.tools.ant.BuildException; | |||||
| import org.apache.tools.ant.util.FileUtils; | |||||
| import org.apache.tools.ant.types.Resource; | |||||
| import org.apache.tools.ant.types.Reference; | |||||
| /** | |||||
| * A Resource representation of a File. | |||||
| * @since Ant 1.7 | |||||
| */ | |||||
| public class FileResource extends Resource implements Touchable { | |||||
| private static final FileUtils FILE_UTILS = FileUtils.getFileUtils(); | |||||
| private static final int NULL_FILE | |||||
| = Resource.getMagicNumber("null file".getBytes()); | |||||
| private File file; | |||||
| private File base; | |||||
| /** | |||||
| * Default constructor. | |||||
| */ | |||||
| public FileResource() { | |||||
| } | |||||
| /** | |||||
| * Construct a new FileResource using the specified base File and relative name. | |||||
| * @param b the base File (directory). | |||||
| * @param name the relative filename. | |||||
| */ | |||||
| public FileResource(File b, String name) { | |||||
| setFile(FILE_UTILS.resolveFile(b, name)); | |||||
| setBase(b); | |||||
| } | |||||
| /** | |||||
| * Construct a new FileResource from a File. | |||||
| * @param f the File represented. | |||||
| */ | |||||
| public FileResource(File f) { | |||||
| setFile(f); | |||||
| } | |||||
| /** | |||||
| * Constructor for Ant attribute introspection. | |||||
| * @param p the Project against which to resolve <code>s</code>. | |||||
| * @param s the absolute or Project-relative filename as a String. | |||||
| * @see org.apache.tools.ant.IntrospectionHelper | |||||
| */ | |||||
| public FileResource(Project p, String s) { | |||||
| this(p.resolveFile(s)); | |||||
| setProject(p); | |||||
| } | |||||
| /** | |||||
| * Set the File for this FileResource. | |||||
| * @param f the File to be represented. | |||||
| */ | |||||
| public void setFile(File f) { | |||||
| checkAttributesAllowed(); | |||||
| file = f; | |||||
| } | |||||
| /** | |||||
| * Get the file represented by this FileResource. | |||||
| * @return the File. | |||||
| */ | |||||
| public File getFile() { | |||||
| return isReference() ? ((FileResource) getCheckedRef()).getFile() : file; | |||||
| } | |||||
| /** | |||||
| * Set the base File for this FileResource. | |||||
| * @param b the base File. | |||||
| */ | |||||
| public void setBase(File b) { | |||||
| checkAttributesAllowed(); | |||||
| base = b; | |||||
| } | |||||
| /** | |||||
| * Return the base to which the name is relative. | |||||
| * @return the base File. | |||||
| */ | |||||
| public File getBase() { | |||||
| return isReference() | |||||
| ? ((FileResource) getCheckedRef()).getBase() : base; | |||||
| } | |||||
| /** | |||||
| * Overrides the super version. | |||||
| * @param r the Reference to set. | |||||
| */ | |||||
| public void setRefid(Reference r) { | |||||
| if (file != null || base != null) { | |||||
| throw tooManyAttributes(); | |||||
| } | |||||
| super.setRefid(r); | |||||
| } | |||||
| /** | |||||
| * Get the name of this FileResource relative to its base, if any. | |||||
| * @return the name of this resource. | |||||
| */ | |||||
| public String getName() { | |||||
| if (isReference()) { | |||||
| return ((Resource) getCheckedRef()).getName(); | |||||
| } | |||||
| File b = getBase(); | |||||
| return b == null ? getNotNullFile().getAbsolutePath() | |||||
| : FILE_UTILS.removeLeadingPath(b, getNotNullFile()); | |||||
| } | |||||
| /** | |||||
| * Learn whether this file exists. | |||||
| * @return true if this resource exists. | |||||
| */ | |||||
| public boolean isExists() { | |||||
| return isReference() ? ((Resource) getCheckedRef()).isExists() | |||||
| : getNotNullFile().exists(); | |||||
| } | |||||
| /** | |||||
| * Get the modification time in milliseconds since 01.01.1970 . | |||||
| * @return 0 if the resource does not exist. | |||||
| */ | |||||
| public long getLastModified() { | |||||
| return isReference() | |||||
| ? ((Resource) getCheckedRef()).getLastModified() | |||||
| : getNotNullFile().lastModified(); | |||||
| } | |||||
| /** | |||||
| * Learn whether the resource is a directory. | |||||
| * @return boolean flag indicating if the resource is a directory. | |||||
| */ | |||||
| public boolean isDirectory() { | |||||
| return isReference() ? ((Resource) getCheckedRef()).isDirectory() | |||||
| : getNotNullFile().isDirectory(); | |||||
| } | |||||
| /** | |||||
| * Get the size of this Resource. | |||||
| * @return the size, as a long, 0 if the Resource does not exist. | |||||
| */ | |||||
| public long getSize() { | |||||
| return isReference() ? ((Resource) getCheckedRef()).getSize() | |||||
| : getNotNullFile().length(); | |||||
| } | |||||
| /** | |||||
| * Return an InputStream for reading the contents of this Resource. | |||||
| * @return an InputStream object. | |||||
| * @throws IOException if an error occurs. | |||||
| */ | |||||
| public InputStream getInputStream() throws IOException { | |||||
| return isReference() | |||||
| ? ((Resource) getCheckedRef()).getInputStream() | |||||
| : new FileInputStream(getNotNullFile()); | |||||
| } | |||||
| /** | |||||
| * Get an OutputStream for the Resource. | |||||
| * @return an OutputStream to which content can be written. | |||||
| * @throws IOException if unable to provide the content of this | |||||
| * Resource as a stream. | |||||
| * @throws UnsupportedOperationException if OutputStreams are not | |||||
| * supported for this Resource type. | |||||
| */ | |||||
| public OutputStream getOutputStream() throws IOException { | |||||
| if (isReference()) { | |||||
| return ((Resource) getCheckedRef()).getOutputStream(); | |||||
| } | |||||
| File f = getNotNullFile(); | |||||
| if (f.exists()) { | |||||
| if (f.isFile()) { | |||||
| f.delete(); | |||||
| } | |||||
| } else { | |||||
| File p = f.getParentFile(); | |||||
| if (p != null && !(p.exists())) { | |||||
| p.mkdirs(); | |||||
| } | |||||
| } | |||||
| return new FileOutputStream(f); | |||||
| } | |||||
| /** | |||||
| * Compare this FileResource to another Resource. | |||||
| * @param another the other Resource against which to compare. | |||||
| * @return a negative integer, zero, or a positive integer as this FileResource | |||||
| * is less than, equal to, or greater than the specified Resource. | |||||
| */ | |||||
| public int compareTo(Object another) { | |||||
| if (isReference()) { | |||||
| return ((Comparable) getCheckedRef()).compareTo(another); | |||||
| } | |||||
| return this.equals(another) ? 0 : super.compareTo(another); | |||||
| } | |||||
| /** | |||||
| * Compare another Object to this FileResource for equality. | |||||
| * @param another the other Object to compare. | |||||
| * @return true if another is a FileResource representing the same file. | |||||
| */ | |||||
| public boolean equals(Object another) { | |||||
| if (this == another) { | |||||
| return true; | |||||
| } | |||||
| if (isReference()) { | |||||
| return getCheckedRef().equals(another); | |||||
| } | |||||
| if (!(another.getClass().equals(getClass()))) { | |||||
| return false; | |||||
| } | |||||
| FileResource otherfr = (FileResource) another; | |||||
| return getFile() == null | |||||
| ? otherfr.getFile() == null | |||||
| : getFile().equals(otherfr.getFile()); | |||||
| } | |||||
| /** | |||||
| * Get the hash code for this Resource. | |||||
| * @return hash code as int. | |||||
| */ | |||||
| public int hashCode() { | |||||
| if (isReference()) { | |||||
| return getCheckedRef().hashCode(); | |||||
| } | |||||
| return MAGIC * (getFile() == null ? NULL_FILE : getFile().hashCode()); | |||||
| } | |||||
| /** | |||||
| * Get the string representation of this Resource. | |||||
| * @return this FileResource formatted as a String. | |||||
| */ | |||||
| public String toString() { | |||||
| return isReference() ? getCheckedRef().toString() | |||||
| : FILE_UTILS.normalize(file.getAbsolutePath()).getAbsolutePath(); | |||||
| } | |||||
| /** | |||||
| * Fulfill the ResourceCollection contract. | |||||
| * @return whether this Resource is a FileResource. | |||||
| */ | |||||
| public boolean isFilesystemOnly() { | |||||
| return !isReference() | |||||
| || ((FileResource) getCheckedRef()).isFilesystemOnly(); | |||||
| } | |||||
| /** | |||||
| * Implement the Touchable interface. | |||||
| * @param modTime new last modification time. | |||||
| */ | |||||
| public void touch(long modTime) { | |||||
| if (isReference()) { | |||||
| ((FileResource) getCheckedRef()).touch(modTime); | |||||
| return; | |||||
| } | |||||
| getNotNullFile().setLastModified(modTime); | |||||
| } | |||||
| /** | |||||
| * Get the file represented by this FileResource, ensuring it is not null. | |||||
| * @return the not-null File. | |||||
| * @throws BuildException if file is null. | |||||
| */ | |||||
| protected File getNotNullFile() { | |||||
| if (getFile() == null) { | |||||
| throw new BuildException("file attribute is null!"); | |||||
| } | |||||
| return getFile(); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,108 @@ | |||||
| /* | |||||
| * Copyright 2005 The Apache Software Foundation | |||||
| * | |||||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||||
| * you may not use this file except in compliance with the License. | |||||
| * You may obtain a copy of the License at | |||||
| * | |||||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||||
| * | |||||
| * Unless required by applicable law or agreed to in writing, software | |||||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
| * See the License for the specific language governing permissions and | |||||
| * limitations under the License. | |||||
| * | |||||
| */ | |||||
| package org.apache.tools.ant.types.resources; | |||||
| import java.io.File; | |||||
| import java.util.Arrays; | |||||
| import java.util.Iterator; | |||||
| import java.util.ArrayList; | |||||
| import java.util.NoSuchElementException; | |||||
| /** | |||||
| * Iterator of FileResources from filenames. | |||||
| * @since Ant 1.7 | |||||
| */ | |||||
| public class FileResourceIterator implements Iterator { | |||||
| private File basedir; | |||||
| private String[] files; | |||||
| private int pos = 0; | |||||
| /** | |||||
| * Construct a new FileResourceIterator. | |||||
| */ | |||||
| public FileResourceIterator() { | |||||
| } | |||||
| /** | |||||
| * Construct a new FileResourceIterator relative to the specified | |||||
| * base directory. | |||||
| * @param f the base directory of this instance. | |||||
| */ | |||||
| public FileResourceIterator(File f) { | |||||
| basedir = f; | |||||
| } | |||||
| /** | |||||
| * Construct a new FileResourceIterator over the specified filenames, | |||||
| * relative to the specified base directory. | |||||
| * @param f the base directory of this instance. | |||||
| * @param files the String[] of filenames. | |||||
| */ | |||||
| public FileResourceIterator(File f, String[] s) { | |||||
| this(f); | |||||
| addFiles(s); | |||||
| } | |||||
| /** | |||||
| * Add an array of filenames to this FileResourceIterator. | |||||
| * @param s the filenames to add. | |||||
| */ | |||||
| public void addFiles(String[] s) { | |||||
| int start = (files == null) ? 0 : files.length; | |||||
| String[] newfiles = new String[start + s.length]; | |||||
| if (start > 0) { | |||||
| System.arraycopy(files, 0, newfiles, 0, start); | |||||
| } | |||||
| files = newfiles; | |||||
| System.arraycopy(s, 0, files, start, s.length); | |||||
| } | |||||
| /** | |||||
| * Find out whether this FileResourceIterator has more elements. | |||||
| * @return whether there are more Resources to iterate over. | |||||
| */ | |||||
| public boolean hasNext() { | |||||
| return pos < files.length; | |||||
| } | |||||
| /** | |||||
| * Get the next element from this FileResourceIterator. | |||||
| * @return the next Object. | |||||
| */ | |||||
| public Object next() { | |||||
| return nextResource(); | |||||
| } | |||||
| /** | |||||
| * Not implemented. | |||||
| */ | |||||
| public void remove() { | |||||
| throw new UnsupportedOperationException(); | |||||
| } | |||||
| /** | |||||
| * Convenience method to return the next resource. | |||||
| * @return the next File. | |||||
| */ | |||||
| public FileResource nextResource() { | |||||
| if (!hasNext()) { | |||||
| throw new NoSuchElementException(); | |||||
| } | |||||
| return new FileResource(basedir, files[pos++]); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,503 @@ | |||||
| /* | |||||
| * Copyright 2005 The Apache Software Foundation | |||||
| * | |||||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||||
| * you may not use this file except in compliance with the License. | |||||
| * You may obtain a copy of the License at | |||||
| * | |||||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||||
| * | |||||
| * Unless required by applicable law or agreed to in writing, software | |||||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
| * See the License for the specific language governing permissions and | |||||
| * limitations under the License. | |||||
| * | |||||
| */ | |||||
| package org.apache.tools.ant.types.resources; | |||||
| import java.io.File; | |||||
| import java.util.Stack; | |||||
| import java.util.Arrays; | |||||
| import java.util.Vector; | |||||
| import java.util.Iterator; | |||||
| import java.util.ArrayList; | |||||
| import java.util.Collections; | |||||
| import java.util.Enumeration; | |||||
| import org.apache.tools.ant.Project; | |||||
| import org.apache.tools.ant.BuildException; | |||||
| import org.apache.tools.ant.DirectoryScanner; | |||||
| import org.apache.tools.ant.types.Reference; | |||||
| import org.apache.tools.ant.types.PatternSet; | |||||
| import org.apache.tools.ant.types.ResourceCollection; | |||||
| import org.apache.tools.ant.types.selectors.FileSelector; | |||||
| import org.apache.tools.ant.types.selectors.AbstractSelectorContainer; | |||||
| /** | |||||
| * ResourceCollection implementation; like AbstractFileSet with absolute paths. | |||||
| * @since Ant 1.7 | |||||
| */ | |||||
| public class Files extends AbstractSelectorContainer | |||||
| implements Cloneable, ResourceCollection { | |||||
| private static final Iterator EMPTY_ITERATOR | |||||
| = Collections.EMPTY_SET.iterator(); | |||||
| private PatternSet defaultPatterns = new PatternSet(); | |||||
| private Vector additionalPatterns = new Vector(); | |||||
| private Vector selectors = new Vector(); | |||||
| private boolean useDefaultExcludes = true; | |||||
| private boolean caseSensitive = true; | |||||
| private boolean followSymlinks = true; | |||||
| /* cached DirectoryScanner instance */ | |||||
| private DirectoryScanner ds = null; | |||||
| /** | |||||
| * Construct a new <code>Files</code> collection. | |||||
| */ | |||||
| public Files() { | |||||
| super(); | |||||
| } | |||||
| /** | |||||
| * Construct a new <code>Files</code> collection, shallowly cloned | |||||
| * from the specified <code>Files</code>. | |||||
| * @param f the <code>Files</code> to use as a template. | |||||
| */ | |||||
| protected Files(Files f) { | |||||
| this.defaultPatterns = f.defaultPatterns; | |||||
| this.additionalPatterns = f.additionalPatterns; | |||||
| this.selectors = f.selectors; | |||||
| this.useDefaultExcludes = f.useDefaultExcludes; | |||||
| this.caseSensitive = f.caseSensitive; | |||||
| this.followSymlinks = f.followSymlinks; | |||||
| this.ds = f.ds; | |||||
| setProject(f.getProject()); | |||||
| } | |||||
| /** | |||||
| * Make this instance in effect a reference to another instance. | |||||
| * | |||||
| * <p>You must not set another attribute or nest elements inside | |||||
| * this element if you make it a reference.</p> | |||||
| * @param r the <code>Reference</code> to use. | |||||
| */ | |||||
| public void setRefid(Reference r) throws BuildException { | |||||
| if (hasPatterns(defaultPatterns)) { | |||||
| throw tooManyAttributes(); | |||||
| } | |||||
| if (!additionalPatterns.isEmpty()) { | |||||
| throw noChildrenAllowed(); | |||||
| } | |||||
| if (!selectors.isEmpty()) { | |||||
| throw noChildrenAllowed(); | |||||
| } | |||||
| super.setRefid(r); | |||||
| } | |||||
| /** | |||||
| * Create a nested patternset. | |||||
| * @return <code>PatternSet</code>. | |||||
| */ | |||||
| public synchronized PatternSet createPatternSet() { | |||||
| if (isReference()) { | |||||
| throw noChildrenAllowed(); | |||||
| } | |||||
| PatternSet patterns = new PatternSet(); | |||||
| additionalPatterns.addElement(patterns); | |||||
| ds = null; | |||||
| return patterns; | |||||
| } | |||||
| /** | |||||
| * Add a name entry to the include list. | |||||
| * @return <code>PatternSet.NameEntry</code>. | |||||
| */ | |||||
| public synchronized PatternSet.NameEntry createInclude() { | |||||
| if (isReference()) { | |||||
| throw noChildrenAllowed(); | |||||
| } | |||||
| ds = null; | |||||
| return defaultPatterns.createInclude(); | |||||
| } | |||||
| /** | |||||
| * Add a name entry to the include files list. | |||||
| * @return <code>PatternSet.NameEntry</code>. | |||||
| */ | |||||
| public synchronized PatternSet.NameEntry createIncludesFile() { | |||||
| if (isReference()) { | |||||
| throw noChildrenAllowed(); | |||||
| } | |||||
| ds = null; | |||||
| return defaultPatterns.createIncludesFile(); | |||||
| } | |||||
| /** | |||||
| * Add a name entry to the exclude list. | |||||
| * @return <code>PatternSet.NameEntry</code>. | |||||
| */ | |||||
| public synchronized PatternSet.NameEntry createExclude() { | |||||
| if (isReference()) { | |||||
| throw noChildrenAllowed(); | |||||
| } | |||||
| ds = null; | |||||
| return defaultPatterns.createExclude(); | |||||
| } | |||||
| /** | |||||
| * Add a name entry to the excludes files list. | |||||
| * @return <code>PatternSet.NameEntry</code>. | |||||
| */ | |||||
| public synchronized PatternSet.NameEntry createExcludesFile() { | |||||
| if (isReference()) { | |||||
| throw noChildrenAllowed(); | |||||
| } | |||||
| ds = null; | |||||
| return defaultPatterns.createExcludesFile(); | |||||
| } | |||||
| /** | |||||
| * Append <code>includes</code> to the current list of include | |||||
| * patterns. | |||||
| * | |||||
| * <p>Patterns may be separated by a comma or a space.</p> | |||||
| * | |||||
| * @param includes the <code>String</code> containing the include patterns. | |||||
| */ | |||||
| public synchronized void setIncludes(String includes) { | |||||
| checkAttributesAllowed(); | |||||
| defaultPatterns.setIncludes(includes); | |||||
| ds = null; | |||||
| } | |||||
| /** | |||||
| * Append <code>includes</code> to the current list of include | |||||
| * patterns. | |||||
| * | |||||
| * @param includes array containing the include patterns. | |||||
| */ | |||||
| public synchronized void appendIncludes(String[] includes) { | |||||
| checkAttributesAllowed(); | |||||
| if (includes != null) { | |||||
| for (int i = 0; i < includes.length; i++) { | |||||
| defaultPatterns.createInclude().setName(includes[i]); | |||||
| } | |||||
| ds = null; | |||||
| } | |||||
| } | |||||
| /** | |||||
| * Append <code>excludes</code> to the current list of exclude | |||||
| * patterns. | |||||
| * | |||||
| * <p>Patterns may be separated by a comma or a space.</p> | |||||
| * | |||||
| * @param excludes the <code>String</code> containing the exclude patterns. | |||||
| */ | |||||
| public synchronized void setExcludes(String excludes) { | |||||
| checkAttributesAllowed(); | |||||
| defaultPatterns.setExcludes(excludes); | |||||
| ds = null; | |||||
| } | |||||
| /** | |||||
| * Append <code>excludes</code> to the current list of include | |||||
| * patterns. | |||||
| * | |||||
| * @param excludes array containing the exclude patterns. | |||||
| */ | |||||
| public synchronized void appendExcludes(String[] excludes) { | |||||
| checkAttributesAllowed(); | |||||
| if (excludes != null) { | |||||
| for (int i = 0; i < excludes.length; i++) { | |||||
| defaultPatterns.createExclude().setName(excludes[i]); | |||||
| } | |||||
| ds = null; | |||||
| } | |||||
| } | |||||
| /** | |||||
| * Set the <code>File</code> containing the includes patterns. | |||||
| * | |||||
| * @param incl <code>File</code> instance. | |||||
| */ | |||||
| public synchronized void setIncludesfile(File incl) throws BuildException { | |||||
| checkAttributesAllowed(); | |||||
| defaultPatterns.setIncludesfile(incl); | |||||
| ds = null; | |||||
| } | |||||
| /** | |||||
| * Set the <code>File</code> containing the excludes patterns. | |||||
| * | |||||
| * @param excl <code>File</code> instance. | |||||
| */ | |||||
| public synchronized void setExcludesfile(File excl) throws BuildException { | |||||
| checkAttributesAllowed(); | |||||
| defaultPatterns.setExcludesfile(excl); | |||||
| ds = null; | |||||
| } | |||||
| /** | |||||
| * Set whether default exclusions should be used or not. | |||||
| * | |||||
| * @param useDefaultExcludes <code>boolean</code>. | |||||
| */ | |||||
| public synchronized void setDefaultexcludes(boolean useDefaultExcludes) { | |||||
| checkAttributesAllowed(); | |||||
| this.useDefaultExcludes = useDefaultExcludes; | |||||
| ds = null; | |||||
| } | |||||
| /** | |||||
| * Get whether default exclusions should be used or not. | |||||
| */ | |||||
| public synchronized boolean getDefaultexcludes() { | |||||
| return (isReference()) | |||||
| ? getRef().getDefaultexcludes() : useDefaultExcludes; | |||||
| } | |||||
| /** | |||||
| * Set case-sensitivity of the Files collection. | |||||
| * | |||||
| * @param caseSensitive <code>boolean</code>. | |||||
| */ | |||||
| public synchronized void setCaseSensitive(boolean caseSensitive) { | |||||
| checkAttributesAllowed(); | |||||
| this.caseSensitive = caseSensitive; | |||||
| ds = null; | |||||
| } | |||||
| /** | |||||
| * Find out if this Files collection is case-sensitive. | |||||
| * | |||||
| * @return <code>boolean</code> indicating whether the Files | |||||
| * collection is case-sensitive. | |||||
| */ | |||||
| public synchronized boolean isCaseSensitive() { | |||||
| return (isReference()) | |||||
| ? getRef().isCaseSensitive() : caseSensitive; | |||||
| } | |||||
| /** | |||||
| * Set whether or not symbolic links should be followed. | |||||
| * | |||||
| * @param followSymlinks whether or not symbolic links should be followed. | |||||
| */ | |||||
| public synchronized void setFollowSymlinks(boolean followSymlinks) { | |||||
| checkAttributesAllowed(); | |||||
| this.followSymlinks = followSymlinks; | |||||
| ds = null; | |||||
| } | |||||
| /** | |||||
| * Find out whether symbolic links should be followed. | |||||
| * | |||||
| * @return <code>boolean</code> indicating whether symbolic links | |||||
| * should be followed. | |||||
| */ | |||||
| public synchronized boolean isFollowSymlinks() { | |||||
| return (isReference()) | |||||
| ? getRef().isFollowSymlinks() : followSymlinks; | |||||
| } | |||||
| /** | |||||
| * Fulfill the ResourceCollection contract. | |||||
| * @return an Iterator of Resources. | |||||
| */ | |||||
| public synchronized Iterator iterator() { | |||||
| if (isReference()) { | |||||
| return getRef().iterator(); | |||||
| } | |||||
| ensureDirectoryScannerSetup(); | |||||
| ds.scan(); | |||||
| int fct = ds.getIncludedFilesCount(); | |||||
| int dct = ds.getIncludedDirsCount(); | |||||
| if (fct + dct == 0) { | |||||
| return EMPTY_ITERATOR; | |||||
| } | |||||
| FileResourceIterator result = new FileResourceIterator(); | |||||
| if (fct > 0) { | |||||
| result.addFiles(ds.getIncludedFiles()); | |||||
| } | |||||
| if (dct > 0) { | |||||
| result.addFiles(ds.getIncludedDirectories()); | |||||
| } | |||||
| return result; | |||||
| } | |||||
| /** | |||||
| * Fulfill the ResourceCollection contract. | |||||
| * @return number of elements as int. | |||||
| */ | |||||
| public synchronized int size() { | |||||
| if (isReference()) { | |||||
| return getRef().size(); | |||||
| } | |||||
| ensureDirectoryScannerSetup(); | |||||
| ds.scan(); | |||||
| return ds.getIncludedFilesCount() + ds.getIncludedDirsCount(); | |||||
| } | |||||
| /** | |||||
| * Find out whether this Files collection has patterns. | |||||
| * | |||||
| * @return whether any patterns are in this container. | |||||
| */ | |||||
| public synchronized boolean hasPatterns() { | |||||
| if (isReference()) { | |||||
| return getRef().hasPatterns(); | |||||
| } | |||||
| if (hasPatterns(defaultPatterns)) { | |||||
| return true; | |||||
| } | |||||
| for (Iterator i = additionalPatterns.iterator(); i.hasNext();) { | |||||
| if (hasPatterns((PatternSet) i.next())) { | |||||
| return true; | |||||
| } | |||||
| } | |||||
| return false; | |||||
| } | |||||
| /** | |||||
| * Add a new selector into this container. | |||||
| * | |||||
| * @param selector the new <code>FileSelector</code> to add. | |||||
| */ | |||||
| public synchronized void appendSelector(FileSelector selector) { | |||||
| if (isReference()) { | |||||
| throw noChildrenAllowed(); | |||||
| } | |||||
| super.appendSelector(selector); | |||||
| ds = null; | |||||
| } | |||||
| /** | |||||
| * Format this Files collection as a String. | |||||
| * @return a descriptive <code>String</code>. | |||||
| */ | |||||
| public String toString() { | |||||
| if (isReference()) { | |||||
| return getRef().toString(); | |||||
| } | |||||
| Iterator i = iterator(); | |||||
| if (!i.hasNext()) { | |||||
| return ""; | |||||
| } | |||||
| StringBuffer sb = new StringBuffer(); | |||||
| while (i.hasNext()) { | |||||
| if (sb.length() > 0) { | |||||
| sb.append(File.pathSeparatorChar); | |||||
| } | |||||
| sb.append(i.next()); | |||||
| } | |||||
| return sb.toString(); | |||||
| } | |||||
| /** | |||||
| * Create a deep clone of this instance, except for the nested selectors | |||||
| * (the list of selectors is a shallow clone of this instance's list). | |||||
| * @return a cloned Object. | |||||
| */ | |||||
| public synchronized Object clone() { | |||||
| if (isReference()) { | |||||
| return getRef().clone(); | |||||
| } | |||||
| try { | |||||
| Files f = (Files) super.clone(); | |||||
| f.defaultPatterns = (PatternSet) defaultPatterns.clone(); | |||||
| f.additionalPatterns = new Vector(additionalPatterns.size()); | |||||
| for (Iterator iter = additionalPatterns.iterator(); iter.hasNext();) { | |||||
| PatternSet ps = (PatternSet) iter.next(); | |||||
| f.additionalPatterns.add(ps.clone()); | |||||
| } | |||||
| f.selectors = new Vector(selectors); | |||||
| return f; | |||||
| } catch (CloneNotSupportedException e) { | |||||
| throw new BuildException(e); | |||||
| } | |||||
| } | |||||
| /** | |||||
| * Get the merged include patterns for this Files collection. | |||||
| * @param p Project instance. | |||||
| * @return the include patterns of the default pattern set and all | |||||
| * nested patternsets. | |||||
| */ | |||||
| public String[] mergeIncludes(Project p) { | |||||
| return mergePatterns(p).getIncludePatterns(p); | |||||
| } | |||||
| /** | |||||
| * Get the merged exclude patterns for this Files collection. | |||||
| * @param p Project instance. | |||||
| * @return the exclude patterns of the default pattern set and all | |||||
| * nested patternsets. | |||||
| */ | |||||
| public String[] mergeExcludes(Project p) { | |||||
| return mergePatterns(p).getExcludePatterns(p); | |||||
| } | |||||
| /** | |||||
| * Get the merged patterns for this Files collection. | |||||
| * @param p Project instance. | |||||
| * @return the default patternset merged with the additional sets | |||||
| * in a new PatternSet instance. | |||||
| */ | |||||
| public synchronized PatternSet mergePatterns(Project p) { | |||||
| if (isReference()) { | |||||
| return getRef().mergePatterns(p); | |||||
| } | |||||
| PatternSet ps = new PatternSet(); | |||||
| ps.append(defaultPatterns, p); | |||||
| final int count = additionalPatterns.size(); | |||||
| for (int i = 0; i < count; i++) { | |||||
| Object o = additionalPatterns.elementAt(i); | |||||
| ps.append((PatternSet) o, p); | |||||
| } | |||||
| return ps; | |||||
| } | |||||
| /** | |||||
| * Always returns true. | |||||
| * @return true indicating that all elements of a Files collection | |||||
| * will be FileResources. | |||||
| */ | |||||
| public boolean isFilesystemOnly() { | |||||
| return true; | |||||
| } | |||||
| /** | |||||
| * Perform the check for circular references and return the | |||||
| * referenced Files collection. | |||||
| * @return <code>FileCollection</code>. | |||||
| */ | |||||
| protected Files getRef() { | |||||
| return (Files) getCheckedRef(); | |||||
| } | |||||
| private synchronized void ensureDirectoryScannerSetup() { | |||||
| if (ds == null) { | |||||
| ds = new DirectoryScanner(); | |||||
| PatternSet ps = mergePatterns(getProject()); | |||||
| ds.setIncludes(ps.getIncludePatterns(getProject())); | |||||
| ds.setExcludes(ps.getExcludePatterns(getProject())); | |||||
| ds.setSelectors(getSelectors(getProject())); | |||||
| if (useDefaultExcludes) { | |||||
| ds.addDefaultExcludes(); | |||||
| } | |||||
| ds.setCaseSensitive(caseSensitive); | |||||
| ds.setFollowSymlinks(followSymlinks); | |||||
| } | |||||
| } | |||||
| private boolean hasPatterns(PatternSet ps) { | |||||
| return ps.getIncludePatterns(getProject()).length > 0 | |||||
| || ps.getExcludePatterns(getProject()).length > 0; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,44 @@ | |||||
| /* | |||||
| * Copyright 2005 The Apache Software Foundation | |||||
| * | |||||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||||
| * you may not use this file except in compliance with the License. | |||||
| * You may obtain a copy of the License at | |||||
| * | |||||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||||
| * | |||||
| * Unless required by applicable law or agreed to in writing, software | |||||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
| * See the License for the specific language governing permissions and | |||||
| * limitations under the License. | |||||
| * | |||||
| */ | |||||
| package org.apache.tools.ant.types.resources; | |||||
| import java.io.IOException; | |||||
| /** | |||||
| * Exception thrown when an attempt is made to get an OutputStream | |||||
| * from an immutable Resource. | |||||
| * @since Ant 1.7 | |||||
| */ | |||||
| public class ImmutableResourceException extends IOException { | |||||
| /** | |||||
| * Default constructor. | |||||
| */ | |||||
| public ImmutableResourceException() { | |||||
| super(); | |||||
| } | |||||
| /** | |||||
| * Construct a new ImmutableResourceException with the specified message. | |||||
| * @param s the message String. | |||||
| */ | |||||
| public ImmutableResourceException(String s) { | |||||
| super(s); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,62 @@ | |||||
| /* | |||||
| * Copyright 2005 The Apache Software Foundation | |||||
| * | |||||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||||
| * you may not use this file except in compliance with the License. | |||||
| * You may obtain a copy of the License at | |||||
| * | |||||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||||
| * | |||||
| * Unless required by applicable law or agreed to in writing, software | |||||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
| * See the License for the specific language governing permissions and | |||||
| * limitations under the License. | |||||
| * | |||||
| */ | |||||
| package org.apache.tools.ant.types.resources; | |||||
| import java.util.List; | |||||
| import java.util.Iterator; | |||||
| import java.util.ArrayList; | |||||
| import java.util.Collection; | |||||
| import org.apache.tools.ant.BuildException; | |||||
| import org.apache.tools.ant.types.ResourceCollection; | |||||
| /** | |||||
| * ResourceCollection representing the intersection | |||||
| * of multiple nested ResourceCollections. | |||||
| * @since Ant 1.7 | |||||
| */ | |||||
| public class Intersect extends BaseResourceCollectionContainer { | |||||
| /** | |||||
| * Calculate the intersection of the nested ResourceCollections. | |||||
| * @return a Collection of Resources. | |||||
| */ | |||||
| protected Collection getCollection() { | |||||
| List rcs = getResourceCollections(); | |||||
| int size = rcs.size(); | |||||
| if (size < 2) { | |||||
| throw new BuildException("The intersection of " + size | |||||
| + " resource collection" + ((size == 1) ? "" : "s") | |||||
| + " is undefined."); | |||||
| } | |||||
| ArrayList al = new ArrayList(); | |||||
| Iterator rc = rcs.iterator(); | |||||
| al.addAll(collect(rc.next())); | |||||
| while (rc.hasNext()) { | |||||
| al.retainAll(collect(rc.next())); | |||||
| } | |||||
| return al; | |||||
| } | |||||
| private ArrayList collect(Object o) { | |||||
| ArrayList result = new ArrayList(); | |||||
| for (Iterator i = ((ResourceCollection) o).iterator(); i.hasNext();) { | |||||
| result.add(i.next()); | |||||
| } | |||||
| return result; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,133 @@ | |||||
| /* | |||||
| * Copyright 2005 The Apache Software Foundation | |||||
| * | |||||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||||
| * you may not use this file except in compliance with the License. | |||||
| * You may obtain a copy of the License at | |||||
| * | |||||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||||
| * | |||||
| * Unless required by applicable law or agreed to in writing, software | |||||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
| * See the License for the specific language governing permissions and | |||||
| * limitations under the License. | |||||
| * | |||||
| */ | |||||
| package org.apache.tools.ant.types.resources; | |||||
| import java.io.IOException; | |||||
| import java.io.InputStream; | |||||
| import java.io.OutputStream; | |||||
| import java.io.ByteArrayInputStream; | |||||
| import org.apache.tools.ant.Project; | |||||
| import org.apache.tools.ant.types.Resource; | |||||
| import org.apache.tools.ant.util.PropertyOutputStream; | |||||
| /** | |||||
| * Exposes an Ant property as a Resource. | |||||
| * @since Ant 1.7 | |||||
| */ | |||||
| public class PropertyResource extends Resource { | |||||
| /** Magic number */ | |||||
| private static final int PROPERTY_MAGIC | |||||
| = Resource.getMagicNumber("PropertyResource".getBytes()); | |||||
| private static final InputStream UNSET = new InputStream() { | |||||
| public int read() { | |||||
| return -1; | |||||
| } | |||||
| }; | |||||
| /** | |||||
| * Default constructor. | |||||
| */ | |||||
| public PropertyResource() { | |||||
| } | |||||
| /** | |||||
| * Construct a new PropertyResource with the specified name. | |||||
| * @param n the String name of this PropertyResource (Ant property name/key). | |||||
| */ | |||||
| public PropertyResource(Project p, String n) { | |||||
| super(n); | |||||
| setProject(p); | |||||
| } | |||||
| /** | |||||
| * Get the value of this PropertyResource. | |||||
| * @return the value of the specified Property. | |||||
| */ | |||||
| public String getValue() { | |||||
| Project p = getProject(); | |||||
| return p == null ? null : p.getProperty(getName()); | |||||
| } | |||||
| /** | |||||
| * Find out whether this Resource exists. | |||||
| * @return true if the Property is set, false otherwise. | |||||
| */ | |||||
| public boolean isExists() { | |||||
| return getValue() != null; | |||||
| } | |||||
| /** | |||||
| * Get the size of this Resource. | |||||
| * @return the size, as a long, 0 if the Resource does not exist (for | |||||
| * compatibility with java.io.File), or UNKNOWN_SIZE if not known. | |||||
| */ | |||||
| public long getSize() { | |||||
| if (isReference()) { | |||||
| return ((Resource) getCheckedRef()).getSize(); | |||||
| } | |||||
| return isExists() ? (long) getValue().length() : 0L; | |||||
| } | |||||
| /** | |||||
| * Get the hash code for this Resource. | |||||
| * @return hash code as int. | |||||
| */ | |||||
| public int hashCode() { | |||||
| if (isReference()) { | |||||
| return getCheckedRef().hashCode(); | |||||
| } | |||||
| return super.hashCode() * PROPERTY_MAGIC; | |||||
| } | |||||
| /** | |||||
| * Get an InputStream for the Resource. | |||||
| * @return an InputStream containing this Resource's content. | |||||
| * @throws IOException if unable to provide the content of this | |||||
| * Resource as a stream. | |||||
| * @throws UnsupportedOperationException if InputStreams are not | |||||
| * supported for this Resource type. | |||||
| */ | |||||
| public InputStream getInputStream() throws IOException { | |||||
| if (isReference()) { | |||||
| return ((Resource) getCheckedRef()).getInputStream(); | |||||
| } | |||||
| return isExists() ? new ByteArrayInputStream(getValue().getBytes()) : UNSET; | |||||
| } | |||||
| /** | |||||
| * Get an OutputStream for the Resource. | |||||
| * @return an OutputStream to which content can be written. | |||||
| * @throws IOException if unable to provide the content of this | |||||
| * Resource as a stream. | |||||
| * @throws UnsupportedOperationException if OutputStreams are not | |||||
| * supported for this Resource type. | |||||
| */ | |||||
| public OutputStream getOutputStream() throws IOException { | |||||
| if (isReference()) { | |||||
| return ((Resource) getCheckedRef()).getOutputStream(); | |||||
| } | |||||
| if (isExists()) { | |||||
| throw new ImmutableResourceException(); | |||||
| } | |||||
| return new PropertyOutputStream(getProject(), getName()); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,187 @@ | |||||
| /* | |||||
| * Copyright 2005 The Apache Software Foundation | |||||
| * | |||||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||||
| * you may not use this file except in compliance with the License. | |||||
| * You may obtain a copy of the License at | |||||
| * | |||||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||||
| * | |||||
| * Unless required by applicable law or agreed to in writing, software | |||||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
| * See the License for the specific language governing permissions and | |||||
| * limitations under the License. | |||||
| * | |||||
| */ | |||||
| package org.apache.tools.ant.types.resources; | |||||
| import java.util.List; | |||||
| import java.util.Stack; | |||||
| import java.util.Vector; | |||||
| import java.util.Iterator; | |||||
| import java.util.Collection; | |||||
| import java.util.AbstractCollection; | |||||
| import java.util.NoSuchElementException; | |||||
| import org.apache.tools.ant.Project; | |||||
| import org.apache.tools.ant.BuildException; | |||||
| import org.apache.tools.ant.types.DataType; | |||||
| import org.apache.tools.ant.types.ResourceCollection; | |||||
| /** | |||||
| * Generic ResourceCollection: Either stores nested ResourceCollections, | |||||
| * making no attempt to remove duplicates, or references another ResourceCollection. | |||||
| * @since Ant 1.7 | |||||
| */ | |||||
| public class Resources extends DataType implements ResourceCollection { | |||||
| private class MyCollection extends AbstractCollection { | |||||
| int size; | |||||
| MyCollection() { | |||||
| size = 0; | |||||
| for (Iterator rci = rc.iterator(); rci.hasNext();) { | |||||
| size += ((ResourceCollection) rci.next()).size(); | |||||
| } | |||||
| } | |||||
| public int size() { | |||||
| return size; | |||||
| } | |||||
| public Iterator iterator() { | |||||
| return new MyIterator(); | |||||
| } | |||||
| private class MyIterator implements Iterator { | |||||
| Iterator rci = rc.iterator(); | |||||
| Iterator ri = null; | |||||
| public boolean hasNext() { | |||||
| if ((ri == null || !ri.hasNext()) && rci.hasNext()) { | |||||
| ri = ((ResourceCollection) rci.next()).iterator(); | |||||
| } | |||||
| return ri != null && ri.hasNext(); | |||||
| } | |||||
| public Object next() { | |||||
| if (!hasNext()) { | |||||
| throw new NoSuchElementException(); | |||||
| } | |||||
| return ri.next(); | |||||
| } | |||||
| public void remove() { | |||||
| throw new UnsupportedOperationException(); | |||||
| } | |||||
| } | |||||
| } | |||||
| private Vector rc = null; | |||||
| private Collection coll = null; | |||||
| /** | |||||
| * Add a ResourceCollection. | |||||
| * @param c the ResourceCollection to add. | |||||
| */ | |||||
| public synchronized void add(ResourceCollection c) { | |||||
| if (isReference()) { | |||||
| throw noChildrenAllowed(); | |||||
| } | |||||
| rc = (rc == null) ? new Vector() : rc; | |||||
| rc.add(c); | |||||
| FailFast.invalidate(this); | |||||
| coll = null; | |||||
| setChecked(false); | |||||
| } | |||||
| /** | |||||
| * Fulfill the ResourceCollection contract. | |||||
| * @return an Iterator of Resources. | |||||
| */ | |||||
| public synchronized Iterator iterator() { | |||||
| if (isReference()) { | |||||
| return getRef().iterator(); | |||||
| } | |||||
| validate(); | |||||
| return new FailFast(this, coll.iterator()); | |||||
| } | |||||
| /** | |||||
| * Fulfill the ResourceCollection contract. | |||||
| * @return number of elements as int. | |||||
| */ | |||||
| public synchronized int size() { | |||||
| if (isReference()) { | |||||
| return getRef().size(); | |||||
| } | |||||
| validate(); | |||||
| return coll.size(); | |||||
| } | |||||
| /** | |||||
| * Fulfill the ResourceCollection contract. | |||||
| * @return true if all Resources represent files. | |||||
| */ | |||||
| public boolean isFilesystemOnly() { | |||||
| if (isReference()) { | |||||
| return getRef().isFilesystemOnly(); | |||||
| } | |||||
| validate(); | |||||
| //first the easy way, if all children are filesystem-only, return true: | |||||
| boolean goEarly = true; | |||||
| for (Iterator i = rc.iterator(); goEarly && i.hasNext();) { | |||||
| goEarly &= ((ResourceCollection) i.next()).isFilesystemOnly(); | |||||
| } | |||||
| if (goEarly) { | |||||
| return true; | |||||
| } | |||||
| /* now check each Resource in case the child only | |||||
| lets through files from any children IT may have: */ | |||||
| for (Iterator i = coll.iterator(); i.hasNext();) { | |||||
| if (!(i.next() instanceof FileResource)) { | |||||
| return false; | |||||
| } | |||||
| } | |||||
| return true; | |||||
| } | |||||
| /** | |||||
| * Overrides the version of DataType to recurse on all DataType | |||||
| * child elements that may have been added. | |||||
| * @param stk the stack of data types to use (recursively). | |||||
| * @param p the project to use to dereference the references. | |||||
| * @throws BuildException on error. | |||||
| */ | |||||
| protected void dieOnCircularReference(Stack stk, Project p) | |||||
| throws BuildException { | |||||
| if (isChecked()) { | |||||
| return; | |||||
| } | |||||
| if (isReference()) { | |||||
| super.dieOnCircularReference(stk, p); | |||||
| } else { | |||||
| for (Iterator i = rc.iterator(); i.hasNext();) { | |||||
| Object o = i.next(); | |||||
| if (o instanceof DataType) { | |||||
| invokeCircularReferenceCheck((DataType) o, stk, p); | |||||
| } | |||||
| } | |||||
| setChecked(true); | |||||
| } | |||||
| } | |||||
| /** | |||||
| * Resolves references, allowing any ResourceCollection. | |||||
| * @return the referenced ResourceCollection. | |||||
| */ | |||||
| private ResourceCollection getRef() { | |||||
| return (ResourceCollection) getCheckedRef( | |||||
| ResourceCollection.class, "ResourceCollection"); | |||||
| } | |||||
| private synchronized void validate() { | |||||
| dieOnCircularReference(); | |||||
| if (rc == null || rc.size() == 0) { | |||||
| throw new BuildException("Resources: no resources specified."); | |||||
| } | |||||
| coll = (coll == null) ? new MyCollection() : coll; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,137 @@ | |||||
| /* | |||||
| * Copyright 2005 The Apache Software Foundation | |||||
| * | |||||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||||
| * you may not use this file except in compliance with the License. | |||||
| * You may obtain a copy of the License at | |||||
| * | |||||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||||
| * | |||||
| * Unless required by applicable law or agreed to in writing, software | |||||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
| * See the License for the specific language governing permissions and | |||||
| * limitations under the License. | |||||
| * | |||||
| */ | |||||
| package org.apache.tools.ant.types.resources; | |||||
| import java.util.Iterator; | |||||
| import java.util.ArrayList; | |||||
| import java.util.Collection; | |||||
| import org.apache.tools.ant.BuildException; | |||||
| import org.apache.tools.ant.types.Resource; | |||||
| import org.apache.tools.ant.types.ResourceCollection; | |||||
| import org.apache.tools.ant.types.resources.selectors.ResourceSelector; | |||||
| import org.apache.tools.ant.types.resources.selectors.ResourceSelectorContainer; | |||||
| /** | |||||
| * ResourceCollection that allows a number of selectors to be | |||||
| * applied to a single ResourceCollection for the purposes of | |||||
| * restricting or narrowing results. | |||||
| * @since Ant 1.7 | |||||
| */ | |||||
| public class Restrict | |||||
| extends ResourceSelectorContainer implements ResourceCollection { | |||||
| private static final String ONE_NESTED_MESSAGE | |||||
| = "Restriction is to be applied to exactly one nested resource collection."; | |||||
| private ResourceCollection rc; | |||||
| /** | |||||
| * Add the ResourceCollection. | |||||
| * @param c the ResourceCollection to add. | |||||
| */ | |||||
| public synchronized void add(ResourceCollection c) { | |||||
| if (isReference()) { | |||||
| throw noChildrenAllowed(); | |||||
| } | |||||
| if (rc != null) { | |||||
| throw new BuildException(ONE_NESTED_MESSAGE); | |||||
| } | |||||
| rc = c; | |||||
| } | |||||
| /** | |||||
| * Add a ResourceSelector. | |||||
| * @param the ResourceSelector to add. | |||||
| */ | |||||
| public synchronized void add(ResourceSelector s) { | |||||
| super.add(s); | |||||
| FailFast.invalidate(this); | |||||
| } | |||||
| /** | |||||
| * Fulfill the ResourceCollection contract. | |||||
| * @return an Iterator of Resources. | |||||
| */ | |||||
| public final synchronized Iterator iterator() { | |||||
| if (isReference()) { | |||||
| return ((Restrict) getCheckedRef()).iterator(); | |||||
| } | |||||
| dieOnCircularReference(); | |||||
| if (rc == null) { | |||||
| throw new BuildException(ONE_NESTED_MESSAGE); | |||||
| } | |||||
| return new FailFast(this, getCollection().iterator()); | |||||
| } | |||||
| /** | |||||
| * Fulfill the ResourceCollection contract. | |||||
| * @return number of elements as int. | |||||
| */ | |||||
| public synchronized int size() { | |||||
| if (isReference()) { | |||||
| return ((Restrict) getCheckedRef()).size(); | |||||
| } | |||||
| dieOnCircularReference(); | |||||
| return getCollection().size(); | |||||
| } | |||||
| /** | |||||
| * Fulfill the ResourceCollection contract. | |||||
| * @return whether this is a filesystem-only resource collection. | |||||
| */ | |||||
| public synchronized boolean isFilesystemOnly() { | |||||
| if (isReference()) { | |||||
| return ((Restrict) getCheckedRef()).isFilesystemOnly(); | |||||
| } | |||||
| dieOnCircularReference(); | |||||
| if (rc == null) { | |||||
| throw new BuildException(ONE_NESTED_MESSAGE); | |||||
| } | |||||
| //first the easy way, if child is filesystem-only, return true: | |||||
| if (rc.isFilesystemOnly()) { | |||||
| return true; | |||||
| } | |||||
| /* now check each Resource in case the child only | |||||
| lets through files from any children IT may have: */ | |||||
| for (Iterator i = getCollection().iterator(); i.hasNext();) { | |||||
| if (!(i.next() instanceof FileResource)) { | |||||
| return false; | |||||
| } | |||||
| } | |||||
| return true; | |||||
| } | |||||
| /** | |||||
| * Restrict the nested ResourceCollection based on the nested selectors. | |||||
| * @return a Collection of Resources. | |||||
| */ | |||||
| protected Collection getCollection() { | |||||
| ArrayList result = new ArrayList(); | |||||
| outer: for (Iterator ri = rc.iterator(); ri.hasNext();) { | |||||
| Resource r = (Resource) ri.next(); | |||||
| for (Iterator i = getSelectors(); i.hasNext();) { | |||||
| if (!((ResourceSelector) (i.next())).isSelected(r)) { | |||||
| continue outer; | |||||
| } | |||||
| } | |||||
| result.add(r); | |||||
| } | |||||
| return result; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,107 @@ | |||||
| /* | |||||
| * Copyright 2005 The Apache Software Foundation | |||||
| * | |||||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||||
| * you may not use this file except in compliance with the License. | |||||
| * You may obtain a copy of the License at | |||||
| * | |||||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||||
| * | |||||
| * Unless required by applicable law or agreed to in writing, software | |||||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
| * See the License for the specific language governing permissions and | |||||
| * limitations under the License. | |||||
| * | |||||
| */ | |||||
| package org.apache.tools.ant.types.resources; | |||||
| import java.util.List; | |||||
| import java.util.Stack; | |||||
| import java.util.Iterator; | |||||
| import java.util.ArrayList; | |||||
| import java.util.Collection; | |||||
| import java.util.Collections; | |||||
| import org.apache.tools.ant.Project; | |||||
| import org.apache.tools.ant.BuildException; | |||||
| import org.apache.tools.ant.types.DataType; | |||||
| import org.apache.tools.ant.types.ResourceCollection; | |||||
| import org.apache.tools.ant.types.resources.comparators.ResourceComparator; | |||||
| /** | |||||
| * ResourceCollection that sorts another ResourceCollection. | |||||
| * @since Ant 1.7 | |||||
| */ | |||||
| public class Sort extends BaseResourceCollectionContainer { | |||||
| private static final String ONE_NESTED_MESSAGE | |||||
| = "Sorting is to be applied to exactly one nested resource collection."; | |||||
| private Stack compStack = new Stack(); | |||||
| /** | |||||
| * Sort the contained elements. | |||||
| * @return a Collection of Resources. | |||||
| */ | |||||
| protected Collection getCollection() { | |||||
| List rcs = getResourceCollections(); | |||||
| if (rcs.size() != 1) { | |||||
| throw new BuildException(ONE_NESTED_MESSAGE); | |||||
| } | |||||
| Iterator nested = ((ResourceCollection) (rcs.get(0))).iterator(); | |||||
| if (!(nested.hasNext())) { | |||||
| return Collections.EMPTY_SET; | |||||
| } | |||||
| ArrayList al = new ArrayList(); | |||||
| while (nested.hasNext()) { | |||||
| al.add(nested.next()); | |||||
| } | |||||
| if (compStack.empty()) { | |||||
| Collections.sort(al); | |||||
| } else { | |||||
| for (Stack s = (Stack) compStack.clone(); !s.empty();) { | |||||
| Collections.sort(al, (ResourceComparator) s.pop()); | |||||
| } | |||||
| } | |||||
| return al; | |||||
| } | |||||
| /** | |||||
| * Add a ResourceComparator to this Sort ResourceCollection. | |||||
| * If multiple ResourceComparator are added, they will be processed in LIFO order. | |||||
| * @param c the ResourceComparator to add. | |||||
| */ | |||||
| public void add(ResourceComparator c) { | |||||
| if (isReference()) { | |||||
| throw noChildrenAllowed(); | |||||
| } | |||||
| compStack.push(c); | |||||
| } | |||||
| /** | |||||
| * Overrides the BaseResourceCollectionContainer version | |||||
| * to recurse on nested ResourceComparators. | |||||
| * @param stk the stack of data types to use (recursively). | |||||
| * @param p the project to use to dereference the references. | |||||
| * @throws BuildException on error. | |||||
| */ | |||||
| protected void dieOnCircularReference(Stack stk, Project p) | |||||
| throws BuildException { | |||||
| if (isChecked()) { | |||||
| return; | |||||
| } | |||||
| if (isReference()) { | |||||
| super.dieOnCircularReference(stk, p); | |||||
| } else { | |||||
| for (Iterator i = compStack.iterator(); i.hasNext();) { | |||||
| Object o = i.next(); | |||||
| if (o instanceof DataType) { | |||||
| stk.push(o); | |||||
| invokeCircularReferenceCheck((DataType) o, stk, p); | |||||
| } | |||||
| } | |||||
| setChecked(true); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,204 @@ | |||||
| /* | |||||
| * Copyright 2005 The Apache Software Foundation | |||||
| * | |||||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||||
| * you may not use this file except in compliance with the License. | |||||
| * You may obtain a copy of the License at | |||||
| * | |||||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||||
| * | |||||
| * Unless required by applicable law or agreed to in writing, software | |||||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
| * See the License for the specific language governing permissions and | |||||
| * limitations under the License. | |||||
| * | |||||
| */ | |||||
| package org.apache.tools.ant.types.resources; | |||||
| import java.io.IOException; | |||||
| import java.io.InputStream; | |||||
| import java.io.OutputStream; | |||||
| import java.io.FilterOutputStream; | |||||
| import java.io.ByteArrayInputStream; | |||||
| import java.io.ByteArrayOutputStream; | |||||
| import org.apache.tools.ant.Project; | |||||
| import org.apache.tools.ant.BuildException; | |||||
| import org.apache.tools.ant.types.Resource; | |||||
| import org.apache.tools.ant.types.Reference; | |||||
| /** | |||||
| * Exposes a string as a Resource. | |||||
| * @since Ant 1.7 | |||||
| */ | |||||
| public class StringResource extends Resource { | |||||
| /** Magic number */ | |||||
| private static final int STRING_MAGIC | |||||
| = Resource.getMagicNumber("StringResource".getBytes()); | |||||
| private String encoding = null; | |||||
| /** | |||||
| * Default constructor. | |||||
| */ | |||||
| public StringResource() { | |||||
| } | |||||
| /** | |||||
| * Construct a StringResource with the supplied value. | |||||
| * @param value the value of this StringResource. | |||||
| */ | |||||
| public StringResource(String value) { | |||||
| setValue(value); | |||||
| } | |||||
| /** | |||||
| * Enforce String immutability. | |||||
| * @param s the new name/value for this StringResource. | |||||
| */ | |||||
| public synchronized void setName(String s) { | |||||
| if (getName() != null) { | |||||
| throw new BuildException(new ImmutableResourceException()); | |||||
| } | |||||
| super.setName(s); | |||||
| } | |||||
| /** | |||||
| * The value attribute is a semantically superior alias for the name attribute. | |||||
| * @param s the String's value. | |||||
| */ | |||||
| public synchronized void setValue(String s) { | |||||
| setName(s); | |||||
| } | |||||
| /** | |||||
| * Synchronize access. | |||||
| * @return the name/value of this StringResource. | |||||
| */ | |||||
| public synchronized String getName() { | |||||
| return super.getName(); | |||||
| } | |||||
| /** | |||||
| * Get the value of this StringResource. | |||||
| * @return the represented String. | |||||
| */ | |||||
| public synchronized String getValue() { | |||||
| return getName(); | |||||
| } | |||||
| /** | |||||
| * Set the encoding to be used for this StringResource. | |||||
| * @param s the encoding name. | |||||
| */ | |||||
| public synchronized void setEncoding(String s) { | |||||
| encoding = s; | |||||
| } | |||||
| /** | |||||
| * Get the encoding used by this StringResource. | |||||
| * @return the encoding name. | |||||
| */ | |||||
| public synchronized String getEncoding() { | |||||
| return encoding; | |||||
| } | |||||
| /** | |||||
| * Get the size of this Resource. | |||||
| * @return the size, as a long, 0 if the Resource does not exist (for | |||||
| * compatibility with java.io.File), or UNKNOWN_SIZE if not known. | |||||
| */ | |||||
| public synchronized long getSize() { | |||||
| return isReference() | |||||
| ? ((Resource) getCheckedRef()).getSize() | |||||
| : (long) getContent().length(); | |||||
| } | |||||
| /** | |||||
| * Get the hash code for this Resource. | |||||
| * @return hash code as int. | |||||
| */ | |||||
| public synchronized int hashCode() { | |||||
| if (isReference()) { | |||||
| return getCheckedRef().hashCode(); | |||||
| } | |||||
| return super.hashCode() * STRING_MAGIC; | |||||
| } | |||||
| /** | |||||
| * Get an InputStream for the Resource. | |||||
| * @return an InputStream containing this Resource's content. | |||||
| * @throws IOException if unable to provide the content of this | |||||
| * Resource as a stream. | |||||
| * @throws UnsupportedOperationException if InputStreams are not | |||||
| * supported for this Resource type. | |||||
| */ | |||||
| public synchronized InputStream getInputStream() throws IOException { | |||||
| if (isReference()) { | |||||
| return ((Resource) getCheckedRef()).getInputStream(); | |||||
| } | |||||
| //I can't get my head around this; is encoding treatment needed here? | |||||
| return | |||||
| //new oata.util.ReaderInputStream(new InputStreamReader( | |||||
| new ByteArrayInputStream(getContent().getBytes()) | |||||
| //, encoding), encoding) | |||||
| ; | |||||
| } | |||||
| /** | |||||
| * Get an OutputStream for the Resource. | |||||
| * @return an OutputStream to which content can be written. | |||||
| * @throws IOException if unable to provide the content of this | |||||
| * Resource as a stream. | |||||
| * @throws UnsupportedOperationException if OutputStreams are not | |||||
| * supported for this Resource type. | |||||
| */ | |||||
| public synchronized OutputStream getOutputStream() throws IOException { | |||||
| if (isReference()) { | |||||
| return ((Resource) getCheckedRef()).getOutputStream(); | |||||
| } | |||||
| if (getValue() != null) { | |||||
| throw new ImmutableResourceException(); | |||||
| } | |||||
| final ByteArrayOutputStream baos = new ByteArrayOutputStream(); | |||||
| return new FilterOutputStream(baos) { | |||||
| public void close() throws IOException { | |||||
| super.close(); | |||||
| StringResource.this.setValue(encoding == null | |||||
| ? baos.toString() : baos.toString(encoding)); | |||||
| } | |||||
| }; | |||||
| } | |||||
| /** | |||||
| * Overrides the super version. | |||||
| * @param r the Reference to set. | |||||
| */ | |||||
| public void setRefid(Reference r) { | |||||
| if (encoding != null) { | |||||
| throw tooManyAttributes(); | |||||
| } | |||||
| super.setRefid(r); | |||||
| } | |||||
| /** | |||||
| * Get the content of this StringResource. | |||||
| * @return a String; if the Project has been set properties | |||||
| * replacement will be attempted. | |||||
| */ | |||||
| protected synchronized String getContent() { | |||||
| if (isReference()) { | |||||
| return ((StringResource) getCheckedRef()).getContent(); | |||||
| } | |||||
| String value = getValue(); | |||||
| if (value == null) { | |||||
| return value; | |||||
| } | |||||
| return getProject() == null | |||||
| ? value : getProject().replaceProperties(value); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,26 @@ | |||||
| /* | |||||
| * Copyright 2005 The Apache Software Foundation | |||||
| * | |||||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||||
| * you may not use this file except in compliance with the License. | |||||
| * You may obtain a copy of the License at | |||||
| * | |||||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||||
| * | |||||
| * Unless required by applicable law or agreed to in writing, software | |||||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
| * See the License for the specific language governing permissions and | |||||
| * limitations under the License. | |||||
| * | |||||
| */ | |||||
| package org.apache.tools.ant.types.resources; | |||||
| /** | |||||
| * Interface to be implemented by "touchable" resources; i.e. those | |||||
| * whose modification time can be altered. | |||||
| * @since Ant 1.7 | |||||
| */ | |||||
| public interface Touchable { | |||||
| void touch(long modTime); | |||||
| } | |||||
| @@ -0,0 +1,373 @@ | |||||
| /* | |||||
| * Copyright 2005 The Apache Software Foundation | |||||
| * | |||||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||||
| * you may not use this file except in compliance with the License. | |||||
| * You may obtain a copy of the License at | |||||
| * | |||||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||||
| * | |||||
| * Unless required by applicable law or agreed to in writing, software | |||||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
| * See the License for the specific language governing permissions and | |||||
| * limitations under the License. | |||||
| * | |||||
| */ | |||||
| package org.apache.tools.ant.types.resources; | |||||
| import java.io.File; | |||||
| import java.io.IOException; | |||||
| import java.io.InputStream; | |||||
| import java.io.OutputStream; | |||||
| import java.net.URL; | |||||
| import java.net.URLConnection; | |||||
| import java.net.MalformedURLException; | |||||
| import org.apache.tools.ant.Project; | |||||
| import org.apache.tools.ant.AntClassLoader; | |||||
| import org.apache.tools.ant.BuildException; | |||||
| import org.apache.tools.ant.types.Path; | |||||
| import org.apache.tools.ant.types.Resource; | |||||
| import org.apache.tools.ant.types.Reference; | |||||
| import org.apache.tools.ant.util.FileUtils; | |||||
| /** | |||||
| * Exposes a URL as a Resource. | |||||
| * @since Ant 1.7 | |||||
| */ | |||||
| public class URLResource extends Resource { | |||||
| private static final FileUtils FILE_UTILS = FileUtils.getFileUtils(); | |||||
| private static final int NULL_URL | |||||
| = Resource.getMagicNumber("null URL".getBytes()); | |||||
| private URL url; | |||||
| private String javaResource; | |||||
| private URLConnection conn; | |||||
| private Path classpath; | |||||
| /** | |||||
| * Default constructor. | |||||
| */ | |||||
| public URLResource() { | |||||
| } | |||||
| /** | |||||
| * Convenience constructor. | |||||
| * @param u the URL to expose. | |||||
| */ | |||||
| public URLResource(URL u) { | |||||
| setURL(u); | |||||
| } | |||||
| /** | |||||
| * Convenience constructor. | |||||
| * @param f the File to set as a URL. | |||||
| */ | |||||
| public URLResource(File f) { | |||||
| setFile(f); | |||||
| } | |||||
| /** | |||||
| * String constructor for Ant attribute introspection. | |||||
| * @param u String representation of this URL. | |||||
| * @see org.apache.tools.ant.IntrospectionHelper | |||||
| */ | |||||
| public URLResource(String u) { | |||||
| this(newURL(u)); | |||||
| } | |||||
| /** | |||||
| * Set the URL for this URLResource. | |||||
| * @param u the URL to expose. | |||||
| */ | |||||
| public synchronized void setURL(URL u) { | |||||
| checkAttributesAllowed(); | |||||
| url = u; | |||||
| } | |||||
| /** | |||||
| * Set the URL from a File. | |||||
| * @param f the File to set as a URL. | |||||
| */ | |||||
| public synchronized void setFile(File f) { | |||||
| try { | |||||
| setURL(FILE_UTILS.getFileURL(f)); | |||||
| } catch (MalformedURLException e) { | |||||
| throw new BuildException(e); | |||||
| } | |||||
| } | |||||
| /** | |||||
| * Set the resource name with which to expose a Java resource. | |||||
| * @param s the Java resource name. | |||||
| * @see java.lang.ClassLoader#getResource() | |||||
| */ | |||||
| public synchronized void setJavaResource(String s) { | |||||
| checkAttributesAllowed(); | |||||
| javaResource = s; | |||||
| } | |||||
| /** | |||||
| * Set the classpath for this URLResource. | |||||
| * @param p the Path against which to resolve Java resources. | |||||
| */ | |||||
| public synchronized void setClasspath(Path p) { | |||||
| checkAttributesAllowed(); | |||||
| addConfiguredClasspath(p); | |||||
| } | |||||
| /** | |||||
| * Create a nested classpath element. | |||||
| * @return a Path object. | |||||
| */ | |||||
| public synchronized void addConfiguredClasspath(Path p) { | |||||
| checkChildrenAllowed(); | |||||
| if (classpath == null) { | |||||
| classpath = new Path(getProject()); | |||||
| } | |||||
| classpath.add(p); | |||||
| } | |||||
| /** | |||||
| * Get the URL used by this URLResource. | |||||
| * @return a URL object. | |||||
| */ | |||||
| public synchronized URL getURL() { | |||||
| if (isReference()) { | |||||
| return ((URLResource) getCheckedRef()).getURL(); | |||||
| } | |||||
| if (url == null && javaResource != null) { | |||||
| ClassLoader cl = null; | |||||
| AntClassLoader acl = null; | |||||
| if (classpath != null) { | |||||
| acl = getProject().createClassLoader(classpath); | |||||
| cl = acl; | |||||
| } else { | |||||
| cl = getClass().getClassLoader(); | |||||
| if (cl == null) { | |||||
| cl = ClassLoader.getSystemClassLoader(); | |||||
| } | |||||
| } | |||||
| if (cl != null) { | |||||
| setURL(cl.getResource(javaResource)); | |||||
| if (acl != null) { | |||||
| acl.cleanup(); | |||||
| } | |||||
| } | |||||
| } | |||||
| return url; | |||||
| } | |||||
| /** | |||||
| * Overrides the super version. | |||||
| * @param r the Reference to set. | |||||
| */ | |||||
| public synchronized void setRefid(Reference r) { | |||||
| //not using the accessor in this case to avoid side effects | |||||
| if (url != null || javaResource != null) { | |||||
| throw tooManyAttributes(); | |||||
| } | |||||
| super.setRefid(r); | |||||
| } | |||||
| /** | |||||
| * Get the name of this URLResource | |||||
| * (its file component minus the leading separator). | |||||
| * @return the name of this resource. | |||||
| */ | |||||
| public synchronized String getName() { | |||||
| return isReference() ? ((Resource) getCheckedRef()).getName() | |||||
| : getURL().getFile().substring(1); | |||||
| } | |||||
| /** | |||||
| * Return this URLResource formatted as a String. | |||||
| * @return a String representation of this URLResource. | |||||
| */ | |||||
| public synchronized String toString() { | |||||
| return isReference() | |||||
| ? getCheckedRef().toString() : String.valueOf(getURL()); | |||||
| } | |||||
| /** | |||||
| * Find out whether the URL exists . | |||||
| * @return true if this resource exists. | |||||
| */ | |||||
| public synchronized boolean isExists() { | |||||
| if (isReference()) { | |||||
| return ((Resource) getCheckedRef()).isExists(); | |||||
| } | |||||
| if (getURL() == null) { | |||||
| return false; | |||||
| } | |||||
| try { | |||||
| connect(); | |||||
| return true; | |||||
| } catch (IOException e) { | |||||
| return false; | |||||
| } | |||||
| } | |||||
| /** | |||||
| * Tells the modification time in milliseconds since 01.01.1970 . | |||||
| * | |||||
| * @return 0 if the resource does not exist to mirror the behavior | |||||
| * of {@link java.io.File File}. | |||||
| */ | |||||
| public synchronized long getLastModified() { | |||||
| if (isReference()) { | |||||
| return ((Resource) getCheckedRef()).getLastModified(); | |||||
| } | |||||
| if (!isExists()) { | |||||
| return 0L; | |||||
| } | |||||
| try { | |||||
| connect(); | |||||
| return conn.getLastModified(); | |||||
| } catch (IOException e) { | |||||
| return 0L; | |||||
| } | |||||
| } | |||||
| /** | |||||
| * Tells if the resource is a directory. | |||||
| * @return boolean whether the resource is a directory. | |||||
| */ | |||||
| public synchronized boolean isDirectory() { | |||||
| return isReference() | |||||
| ? ((Resource) getCheckedRef()).isDirectory() | |||||
| : getName().endsWith("/"); | |||||
| } | |||||
| /** | |||||
| * Get the size of this Resource. | |||||
| * @return the size, as a long, 0 if the Resource does not exist (for | |||||
| * compatibility with java.io.File), or UNKNOWN_SIZE if not known. | |||||
| */ | |||||
| public synchronized long getSize() { | |||||
| if (isReference()) { | |||||
| return ((Resource) getCheckedRef()).getSize(); | |||||
| } | |||||
| if (!isExists()) { | |||||
| return 0L; | |||||
| } | |||||
| try { | |||||
| connect(); | |||||
| return conn.getContentLength(); | |||||
| } catch (IOException e) { | |||||
| return UNKNOWN_SIZE; | |||||
| } | |||||
| } | |||||
| /** | |||||
| * Test whether an Object equals this URLResource. | |||||
| * @param another the other Object to compare. | |||||
| * @return true if the specified Object is equal to this Resource. | |||||
| */ | |||||
| public synchronized boolean equals(Object another) { | |||||
| if (this == another) { | |||||
| return true; | |||||
| } | |||||
| if (isReference()) { | |||||
| return getCheckedRef().equals(another); | |||||
| } | |||||
| if (!(another.getClass().equals(getClass()))) { | |||||
| return false; | |||||
| } | |||||
| URLResource otheru = (URLResource) another; | |||||
| return getURL() == null | |||||
| ? otheru.getURL() == null | |||||
| : getURL().equals(otheru.getURL()); | |||||
| } | |||||
| /** | |||||
| * Get the hash code for this Resource. | |||||
| * @return hash code as int. | |||||
| */ | |||||
| public synchronized int hashCode() { | |||||
| if (isReference()) { | |||||
| return getCheckedRef().hashCode(); | |||||
| } | |||||
| return MAGIC * ((getURL() == null) ? NULL_URL : getURL().hashCode()); | |||||
| } | |||||
| /** | |||||
| * Get an InputStream for the Resource. | |||||
| * @return an InputStream containing this Resource's content. | |||||
| * @throws IOException if unable to provide the content of this | |||||
| * Resource as a stream. | |||||
| * @throws UnsupportedOperationException if InputStreams are not | |||||
| * supported for this Resource type. | |||||
| */ | |||||
| public synchronized InputStream getInputStream() throws IOException { | |||||
| if (isReference()) { | |||||
| return ((Resource) getCheckedRef()).getInputStream(); | |||||
| } | |||||
| connect(); | |||||
| try { | |||||
| return conn.getInputStream(); | |||||
| } finally { | |||||
| conn = null; | |||||
| } | |||||
| } | |||||
| /** | |||||
| * Get an OutputStream for the Resource. | |||||
| * @return an OutputStream to which content can be written. | |||||
| * @throws IOException if unable to provide the content of this | |||||
| * Resource as a stream. | |||||
| * @throws UnsupportedOperationException if OutputStreams are not | |||||
| * supported for this Resource type. | |||||
| */ | |||||
| public synchronized OutputStream getOutputStream() throws IOException { | |||||
| if (isReference()) { | |||||
| return ((Resource) getCheckedRef()).getOutputStream(); | |||||
| } | |||||
| connect(); | |||||
| try { | |||||
| return conn.getOutputStream(); | |||||
| } finally { | |||||
| conn = null; | |||||
| } | |||||
| } | |||||
| /** | |||||
| * Ensure that we have a connection. | |||||
| */ | |||||
| protected synchronized void connect() throws IOException { | |||||
| URL u = getURL(); | |||||
| if (u == null) { | |||||
| throw new BuildException("URL not set"); | |||||
| } | |||||
| if (conn == null) { | |||||
| try { | |||||
| conn = u.openConnection(); | |||||
| conn.connect(); | |||||
| } catch (IOException e) { | |||||
| log(e.toString(), Project.MSG_ERR); | |||||
| conn = null; | |||||
| throw e; | |||||
| } | |||||
| } | |||||
| } | |||||
| /** | |||||
| * Finalize this URLResource. | |||||
| * @throws Throwable on error. | |||||
| */ | |||||
| protected void finalize() throws Throwable { | |||||
| conn = null; | |||||
| super.finalize(); | |||||
| } | |||||
| private static URL newURL(String u) { | |||||
| try { | |||||
| return new URL(u); | |||||
| } catch (MalformedURLException e) { | |||||
| throw new BuildException(e); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,85 @@ | |||||
| /* | |||||
| * Copyright 2005 The Apache Software Foundation | |||||
| * | |||||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||||
| * you may not use this file except in compliance with the License. | |||||
| * You may obtain a copy of the License at | |||||
| * | |||||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||||
| * | |||||
| * Unless required by applicable law or agreed to in writing, software | |||||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
| * See the License for the specific language governing permissions and | |||||
| * limitations under the License. | |||||
| * | |||||
| */ | |||||
| package org.apache.tools.ant.types.resources; | |||||
| import java.util.List; | |||||
| import java.util.Iterator; | |||||
| import java.util.ArrayList; | |||||
| import java.util.Collection; | |||||
| import java.util.Collections; | |||||
| import org.apache.tools.ant.types.ResourceCollection; | |||||
| /** | |||||
| * ResourceCollection representing the union of multiple nested ResourceCollections. | |||||
| * @since Ant 1.7 | |||||
| */ | |||||
| public class Union extends BaseResourceCollectionContainer { | |||||
| /** | |||||
| * Returns all Resources in String format. Moved up from | |||||
| * Path for convenience. | |||||
| * @return String array of Resources. | |||||
| */ | |||||
| public String[] list() { | |||||
| if (isReference()) { | |||||
| return ((Union) getCheckedRef()).list(); | |||||
| } | |||||
| Collection result = getCollection(true); | |||||
| return (String[]) (result.toArray(new String[result.size()])); | |||||
| } | |||||
| /** | |||||
| * Unify the contained Resources. | |||||
| * @return a Collection of Resources. | |||||
| */ | |||||
| protected Collection getCollection() { | |||||
| return getCollection(false); | |||||
| } | |||||
| /** | |||||
| * Unify the contained Resources. | |||||
| * @param asString indicates whether the resulting Collection | |||||
| * should contain Strings instead of Resources. | |||||
| * @return a Collection of Resources. | |||||
| */ | |||||
| protected Collection getCollection(boolean asString) { | |||||
| List rc = getResourceCollections(); | |||||
| if (rc.isEmpty()) { | |||||
| return Collections.EMPTY_LIST; | |||||
| } | |||||
| //preserve order-encountered using a list; enforce set logic manually: | |||||
| ArrayList union = new ArrayList(rc.size() * 2); | |||||
| for (Iterator rcIter = rc.iterator(); rcIter.hasNext();) { | |||||
| for (Iterator r = nextRC(rcIter).iterator(); r.hasNext();) { | |||||
| Object o = r.next(); | |||||
| if (asString) { | |||||
| o = o.toString(); | |||||
| } | |||||
| if (!(union.contains(o))) { | |||||
| union.add(o); | |||||
| } | |||||
| } | |||||
| } | |||||
| return union; | |||||
| } | |||||
| private static ResourceCollection nextRC(Iterator i) { | |||||
| return (ResourceCollection) i.next(); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,299 @@ | |||||
| /* | |||||
| * Copyright 2005 The Apache Software Foundation | |||||
| * | |||||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||||
| * you may not use this file except in compliance with the License. | |||||
| * You may obtain a copy of the License at | |||||
| * | |||||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||||
| * | |||||
| * Unless required by applicable law or agreed to in writing, software | |||||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
| * See the License for the specific language governing permissions and | |||||
| * limitations under the License. | |||||
| * | |||||
| */ | |||||
| package org.apache.tools.ant.types.resources; | |||||
| import java.io.File; | |||||
| import java.io.InputStream; | |||||
| import java.io.OutputStream; | |||||
| import java.io.IOException; | |||||
| import java.io.FilterInputStream; | |||||
| import org.apache.tools.ant.Project; | |||||
| import org.apache.tools.ant.BuildException; | |||||
| import org.apache.tools.ant.types.Resource; | |||||
| import org.apache.tools.ant.types.Reference; | |||||
| import org.apache.tools.ant.util.FileUtils; | |||||
| import org.apache.tools.zip.ZipFile; | |||||
| import org.apache.tools.zip.ZipEntry; | |||||
| /** | |||||
| * A Resource representation of an entry in a zipfile. | |||||
| * @since Ant 1.7 | |||||
| */ | |||||
| public class ZipResource extends Resource { | |||||
| private static final int NULL_ZIPFILE | |||||
| = Resource.getMagicNumber("null zipfile".getBytes()); | |||||
| private String encoding; | |||||
| private File zipfile; | |||||
| private boolean haveEntry = false; | |||||
| /** | |||||
| * Default constructor. | |||||
| */ | |||||
| public ZipResource() { | |||||
| } | |||||
| /** | |||||
| * Construct a ZipResource representing the specified | |||||
| * entry in the specified zipfile. | |||||
| * @param z the zipfile as File. | |||||
| * @param enc the encoding used for filenames. | |||||
| * @param e the ZipEntry. | |||||
| */ | |||||
| public ZipResource(File z, String enc, ZipEntry e) { | |||||
| setEntry(e); | |||||
| setZipfile(z); | |||||
| setEncoding(enc); | |||||
| } | |||||
| /** | |||||
| * Set the zipfile that holds this ZipResource. | |||||
| * @param z the zipfile as a File. | |||||
| */ | |||||
| public void setZipfile(File z) { | |||||
| checkAttributesAllowed(); | |||||
| zipfile = z; | |||||
| } | |||||
| /** | |||||
| * Get the zipfile that holds this ZipResource. | |||||
| * @return the zipfile as a File. | |||||
| */ | |||||
| public File getZipfile() { | |||||
| return isReference() | |||||
| ? ((ZipResource) getCheckedRef()).getZipfile() : zipfile; | |||||
| } | |||||
| /** | |||||
| * Set the encoding to use with the zipfile. | |||||
| * @param enc the String encoding. | |||||
| */ | |||||
| public void setEncoding(String enc) { | |||||
| checkAttributesAllowed(); | |||||
| encoding = enc; | |||||
| } | |||||
| /** | |||||
| * Get the encoding to use with the zipfile. | |||||
| * @return String encoding. | |||||
| */ | |||||
| public String getEncoding() { | |||||
| return isReference() | |||||
| ? ((ZipResource) getCheckedRef()).getEncoding() : encoding; | |||||
| } | |||||
| /** | |||||
| * Get the last modified date of this ZipResource. | |||||
| * @return the last modification date. | |||||
| */ | |||||
| public long getLastModified() { | |||||
| if (isReference()) { | |||||
| return ((Resource) getCheckedRef()).getLastModified(); | |||||
| } | |||||
| checkEntry(); | |||||
| return super.getLastModified(); | |||||
| } | |||||
| /** | |||||
| * Get the size of this ZipResource. | |||||
| * @return the long size of this ZipResource. | |||||
| */ | |||||
| public long getSize() { | |||||
| if (isReference()) { | |||||
| return ((Resource) getCheckedRef()).getSize(); | |||||
| } | |||||
| checkEntry(); | |||||
| return super.getSize(); | |||||
| } | |||||
| /** | |||||
| * Learn whether this ZipResource represents a directory. | |||||
| * @return boolean flag indicating whether the zip entry is a directory. | |||||
| */ | |||||
| public boolean isDirectory() { | |||||
| if (isReference()) { | |||||
| return ((Resource) getCheckedRef()).isDirectory(); | |||||
| } | |||||
| checkEntry(); | |||||
| return super.isDirectory(); | |||||
| } | |||||
| /** | |||||
| * Find out whether this ZipResource represents an existing Resource. | |||||
| * @return boolean existence flag. | |||||
| */ | |||||
| public boolean isExists() { | |||||
| if (isReference()) { | |||||
| return ((Resource) getCheckedRef()).isExists(); | |||||
| } | |||||
| checkEntry(); | |||||
| return super.isExists(); | |||||
| } | |||||
| /** | |||||
| * Overrides the super version. | |||||
| * @param r the Reference to set. | |||||
| */ | |||||
| public void setRefid(Reference r) { | |||||
| if (encoding != null || zipfile != null) { | |||||
| throw tooManyAttributes(); | |||||
| } | |||||
| super.setRefid(r); | |||||
| } | |||||
| /** | |||||
| * Return an InputStream for reading the contents of this Resource. | |||||
| * @return an InputStream object. | |||||
| * @throws IOException if the zip file cannot be opened, | |||||
| * or the entry cannot be read. | |||||
| */ | |||||
| public InputStream getInputStream() throws IOException { | |||||
| if (isReference()) { | |||||
| return ((Resource) getCheckedRef()).getInputStream(); | |||||
| } | |||||
| final ZipFile z = new ZipFile(getZipfile(), getEncoding()); | |||||
| return new FilterInputStream(z.getInputStream(z.getEntry(getName()))) { | |||||
| public void close() throws IOException { | |||||
| FileUtils.close(in); | |||||
| z.close(); | |||||
| } | |||||
| protected void finalize() throws Throwable { | |||||
| try { | |||||
| close(); | |||||
| } finally { | |||||
| super.finalize(); | |||||
| } | |||||
| } | |||||
| }; | |||||
| } | |||||
| /** | |||||
| * Get an OutputStream for the Resource. | |||||
| * @return an OutputStream to which content can be written. | |||||
| * @throws IOException if unable to provide the content of this | |||||
| * Resource as a stream. | |||||
| * @throws UnsupportedOperationException if OutputStreams are not | |||||
| * supported for this Resource type. | |||||
| */ | |||||
| public OutputStream getOutputStream() throws IOException { | |||||
| if (isReference()) { | |||||
| return ((Resource) getCheckedRef()).getOutputStream(); | |||||
| } | |||||
| throw new UnsupportedOperationException( | |||||
| "Use the zip task for zip output."); | |||||
| } | |||||
| /** | |||||
| * Compare this ZipResource to another Resource. | |||||
| * @param another the other Resource against which to compare. | |||||
| * @return a negative integer, zero, or a positive integer as this ZipResource | |||||
| * is less than, equal to, or greater than the specified Resource. | |||||
| */ | |||||
| public int compareTo(Object another) { | |||||
| return this.equals(another) ? 0 : super.compareTo(another); | |||||
| } | |||||
| /** | |||||
| * Compare another Object to this ZipResource for equality. | |||||
| * @param another the other Object to compare. | |||||
| * @return true if another is a ZipResource representing | |||||
| * the same entry in the same zipfile. | |||||
| */ | |||||
| public boolean equals(Object another) { | |||||
| if (this == another) { | |||||
| return true; | |||||
| } | |||||
| if (isReference()) { | |||||
| return getCheckedRef().equals(another); | |||||
| } | |||||
| if (!(another.getClass().equals(getClass()))) { | |||||
| return false; | |||||
| } | |||||
| ZipResource r = (ZipResource) another; | |||||
| return getZipfile().equals(r.getZipfile()) | |||||
| && getName().equals(r.getName()); | |||||
| } | |||||
| /** | |||||
| * Get the hash code for this Resource. | |||||
| * @return hash code as int. | |||||
| */ | |||||
| public int hashCode() { | |||||
| return super.hashCode() | |||||
| * (getZipfile() == null ? NULL_ZIPFILE : getZipfile().hashCode()); | |||||
| } | |||||
| /** | |||||
| * Format this ZipResource as a String. | |||||
| * @return String representatation of this ZipResource. | |||||
| */ | |||||
| public String toString() { | |||||
| return isReference() ? getCheckedRef().toString() | |||||
| : getZipfile().toString() + ':' + getName(); | |||||
| } | |||||
| private synchronized void checkEntry() throws BuildException { | |||||
| if (haveEntry) { | |||||
| return; | |||||
| } | |||||
| String name = getName(); | |||||
| if (name == null) { | |||||
| throw new BuildException("zip entry name not set"); | |||||
| } | |||||
| File f = getZipfile(); | |||||
| if (f == null) { | |||||
| throw new BuildException("zipfile attribute not set"); | |||||
| } | |||||
| if (!f.exists()) { | |||||
| throw new BuildException(f.getAbsolutePath() + " does not exist."); | |||||
| } | |||||
| if (f.isDirectory()) { | |||||
| throw new BuildException(f + " denotes a directory."); | |||||
| } | |||||
| ZipFile z = null; | |||||
| try { | |||||
| z = new ZipFile(f, getEncoding()); | |||||
| setEntry(z.getEntry(name)); | |||||
| } catch (IOException e) { | |||||
| log(e.getMessage(), Project.MSG_DEBUG); | |||||
| throw new BuildException(e); | |||||
| } finally { | |||||
| if (z != null) { | |||||
| try { | |||||
| z.close(); | |||||
| } catch (IOException e) { | |||||
| //? | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| private synchronized void setEntry(ZipEntry e) { | |||||
| haveEntry = true; | |||||
| if (e == null) { | |||||
| super.setExists(false); | |||||
| return; | |||||
| } | |||||
| super.setName(e.getName()); | |||||
| super.setExists(true); | |||||
| super.setLastModified(e.getTime()); | |||||
| super.setDirectory(e.isDirectory()); | |||||
| super.setSize(e.getSize()); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,69 @@ | |||||
| /* | |||||
| * Copyright 2005 The Apache Software Foundation | |||||
| * | |||||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||||
| * you may not use this file except in compliance with the License. | |||||
| * You may obtain a copy of the License at | |||||
| * | |||||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||||
| * | |||||
| * Unless required by applicable law or agreed to in writing, software | |||||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
| * See the License for the specific language governing permissions and | |||||
| * limitations under the License. | |||||
| * | |||||
| */ | |||||
| package org.apache.tools.ant.types.resources.comparators; | |||||
| import java.io.IOException; | |||||
| import org.apache.tools.ant.BuildException; | |||||
| import org.apache.tools.ant.types.Resource; | |||||
| import org.apache.tools.ant.util.FileUtils; | |||||
| /** | |||||
| * Compares Resources by content. | |||||
| * @since Ant 1.7 | |||||
| */ | |||||
| public class Content extends ResourceComparator { | |||||
| private boolean binary = true; | |||||
| /** | |||||
| * Set binary mode for this Content ResourceComparator. If this | |||||
| * attribute is set to false, Resource content will be compared | |||||
| * ignoring platform line-ending conventions. | |||||
| * Default is <code>true</code>. | |||||
| * @param b whether to compare content in binary mode. | |||||
| */ | |||||
| public void setBinary(boolean b) { | |||||
| binary = b; | |||||
| } | |||||
| /** | |||||
| * Learn whether this Content ResourceComparator is operating in binary mode. | |||||
| * @return boolean binary flag. | |||||
| */ | |||||
| public boolean isBinary() { | |||||
| return binary; | |||||
| } | |||||
| /** | |||||
| * Compare two Resources by content. | |||||
| * @param foo the first Resource. | |||||
| * @param bar the second Resource. | |||||
| * @return a negative integer, zero, or a positive integer as the first | |||||
| * argument is less than, equal to, or greater than the second. | |||||
| * @throws BuildException if I/O errors occur. | |||||
| * @see org.apache.tools.ant.util.FileUtils#compareContent(Resource, Resource, boolean). | |||||
| */ | |||||
| protected int resourceCompare(Resource foo, Resource bar) { | |||||
| try { | |||||
| return FileUtils.getFileUtils().compareContent(foo, bar, !binary); | |||||
| } catch (IOException e) { | |||||
| throw new BuildException(e); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,37 @@ | |||||
| /* | |||||
| * Copyright 2005 The Apache Software Foundation | |||||
| * | |||||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||||
| * you may not use this file except in compliance with the License. | |||||
| * You may obtain a copy of the License at | |||||
| * | |||||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||||
| * | |||||
| * Unless required by applicable law or agreed to in writing, software | |||||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
| * See the License for the specific language governing permissions and | |||||
| * limitations under the License. | |||||
| * | |||||
| */ | |||||
| package org.apache.tools.ant.types.resources.comparators; | |||||
| import org.apache.tools.ant.types.Resource; | |||||
| /** | |||||
| * Compares Resources by last modification date. | |||||
| * @since Ant 1.7 | |||||
| */ | |||||
| public class Date extends ResourceComparator { | |||||
| /** | |||||
| * Compare two Resources. | |||||
| * @param foo the first Resource. | |||||
| * @param bar the second Resource. | |||||
| * @return a negative integer, zero, or a positive integer as the first | |||||
| * argument is less than, equal to, or greater than the second. | |||||
| */ | |||||
| protected int resourceCompare(Resource foo, Resource bar) { | |||||
| return (int) (foo.getLastModified() - bar.getLastModified()); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,42 @@ | |||||
| /* | |||||
| * Copyright 2005 The Apache Software Foundation | |||||
| * | |||||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||||
| * you may not use this file except in compliance with the License. | |||||
| * You may obtain a copy of the License at | |||||
| * | |||||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||||
| * | |||||
| * Unless required by applicable law or agreed to in writing, software | |||||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
| * See the License for the specific language governing permissions and | |||||
| * limitations under the License. | |||||
| * | |||||
| */ | |||||
| package org.apache.tools.ant.types.resources.comparators; | |||||
| import org.apache.tools.ant.types.Resource; | |||||
| /** | |||||
| * Compares Resources by existence. Not existing is "less than" existing. | |||||
| * @since Ant 1.7 | |||||
| */ | |||||
| public class Exists extends ResourceComparator { | |||||
| /** | |||||
| * Compare two Resources. | |||||
| * @param foo the first Resource. | |||||
| * @param bar the second Resource. | |||||
| * @return a negative integer, zero, or a positive integer as the first | |||||
| * argument is less than, equal to, or greater than the second. | |||||
| */ | |||||
| protected int resourceCompare(Resource foo, Resource bar) { | |||||
| boolean f = foo.isExists(); | |||||
| if (f == bar.isExists()) { | |||||
| return 0; | |||||
| } | |||||
| return f ? 1 : -1; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,37 @@ | |||||
| /* | |||||
| * Copyright 2005 The Apache Software Foundation | |||||
| * | |||||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||||
| * you may not use this file except in compliance with the License. | |||||
| * You may obtain a copy of the License at | |||||
| * | |||||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||||
| * | |||||
| * Unless required by applicable law or agreed to in writing, software | |||||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
| * See the License for the specific language governing permissions and | |||||
| * limitations under the License. | |||||
| * | |||||
| */ | |||||
| package org.apache.tools.ant.types.resources.comparators; | |||||
| import org.apache.tools.ant.types.Resource; | |||||
| /** | |||||
| * Compares Resources by name. | |||||
| * @since Ant 1.7 | |||||
| */ | |||||
| public class Name extends ResourceComparator { | |||||
| /** | |||||
| * Compare two Resources. | |||||
| * @param foo the first Resource. | |||||
| * @param bar the second Resource. | |||||
| * @return a negative integer, zero, or a positive integer as the first | |||||
| * argument is less than, equal to, or greater than the second. | |||||
| */ | |||||
| protected int resourceCompare(Resource foo, Resource bar) { | |||||
| return foo.getName().compareTo(bar.getName()); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,62 @@ | |||||
| /* | |||||
| * Copyright 2005 The Apache Software Foundation | |||||
| * | |||||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||||
| * you may not use this file except in compliance with the License. | |||||
| * You may obtain a copy of the License at | |||||
| * | |||||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||||
| * | |||||
| * Unless required by applicable law or agreed to in writing, software | |||||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
| * See the License for the specific language governing permissions and | |||||
| * limitations under the License. | |||||
| * | |||||
| */ | |||||
| package org.apache.tools.ant.types.resources.comparators; | |||||
| import java.util.Comparator; | |||||
| import org.apache.tools.ant.types.Resource; | |||||
| /** | |||||
| * Abstract Resource Comparator. | |||||
| * @since Ant 1.7 | |||||
| */ | |||||
| public abstract class ResourceComparator implements Comparator { | |||||
| /** | |||||
| * Compare two objects. | |||||
| * @param foo the first Object. | |||||
| * @param bar the second Object. | |||||
| * @return a negative integer, zero, or a positive integer as the first | |||||
| * argument is less than, equal to, or greater than the second. | |||||
| * @throws ClassCastException if either argument is null. | |||||
| */ | |||||
| public final int compare(Object foo, Object bar) { | |||||
| return resourceCompare((Resource) foo, (Resource) bar); | |||||
| } | |||||
| /** | |||||
| * Test for equality with this ResourceComparator. | |||||
| * @param o the Object to compare against. | |||||
| * @return true if the specified Object equals this one. | |||||
| */ | |||||
| public final boolean equals(Object o) { | |||||
| if (o == null) { | |||||
| return false; | |||||
| } | |||||
| return o == this || o.getClass().equals(getClass()); | |||||
| } | |||||
| /** | |||||
| * Compare two Resources. | |||||
| * @param foo the first Resource. | |||||
| * @param bar the second Resource. | |||||
| * @return a negative integer, zero, or a positive integer as the first | |||||
| * argument is less than, equal to, or greater than the second. | |||||
| */ | |||||
| protected abstract int resourceCompare(Resource foo, Resource bar); | |||||
| } | |||||
| @@ -0,0 +1,56 @@ | |||||
| /* | |||||
| * Copyright 2005 The Apache Software Foundation | |||||
| * | |||||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||||
| * you may not use this file except in compliance with the License. | |||||
| * You may obtain a copy of the License at | |||||
| * | |||||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||||
| * | |||||
| * Unless required by applicable law or agreed to in writing, software | |||||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
| * See the License for the specific language governing permissions and | |||||
| * limitations under the License. | |||||
| * | |||||
| */ | |||||
| package org.apache.tools.ant.types.resources.comparators; | |||||
| import org.apache.tools.ant.BuildException; | |||||
| import org.apache.tools.ant.types.Resource; | |||||
| /** | |||||
| * Reverses another ResourceComparator. If no nested ResourceComparator | |||||
| * is supplied, the compared Resources' natural order will be reversed. | |||||
| * @since Ant 1.7 | |||||
| */ | |||||
| public class Reverse extends ResourceComparator { | |||||
| private static final String ONE_NESTED | |||||
| = "You must not nest more than one ResourceComparator for reversal."; | |||||
| private ResourceComparator nested; | |||||
| /** | |||||
| * Add the ResourceComparator to reverse. | |||||
| * @param nested the ResourceComparator to add. | |||||
| */ | |||||
| public void add(ResourceComparator c) { | |||||
| if (nested != null) { | |||||
| throw new BuildException(ONE_NESTED); | |||||
| } | |||||
| nested = c; | |||||
| } | |||||
| /** | |||||
| * Compare two Resources. | |||||
| * @param foo the first Resource. | |||||
| * @param bar the second Resource. | |||||
| * @return a negative integer, zero, or a positive integer as the first | |||||
| * argument is greater than, equal to, or less than the second. | |||||
| */ | |||||
| protected int resourceCompare(Resource foo, Resource bar) { | |||||
| return -1 * (nested == null | |||||
| ? foo.compareTo(bar) : nested.compare(foo, bar)); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,37 @@ | |||||
| /* | |||||
| * Copyright 2005 The Apache Software Foundation | |||||
| * | |||||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||||
| * you may not use this file except in compliance with the License. | |||||
| * You may obtain a copy of the License at | |||||
| * | |||||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||||
| * | |||||
| * Unless required by applicable law or agreed to in writing, software | |||||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
| * See the License for the specific language governing permissions and | |||||
| * limitations under the License. | |||||
| * | |||||
| */ | |||||
| package org.apache.tools.ant.types.resources.comparators; | |||||
| import org.apache.tools.ant.types.Resource; | |||||
| /** | |||||
| * Compares Resources by size. | |||||
| * @since Ant 1.7 | |||||
| */ | |||||
| public class Size extends ResourceComparator { | |||||
| /** | |||||
| * Compare two Resources. | |||||
| * @param foo the first Resource. | |||||
| * @param bar the second Resource. | |||||
| * @return a negative integer, zero, or a positive integer as the first | |||||
| * argument is less than, equal to, or greater than the second. | |||||
| */ | |||||
| protected int resourceCompare(Resource foo, Resource bar) { | |||||
| return (int) (foo.getSize() - bar.getSize()); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,43 @@ | |||||
| /* | |||||
| * Copyright 2005 The Apache Software Foundation | |||||
| * | |||||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||||
| * you may not use this file except in compliance with the License. | |||||
| * You may obtain a copy of the License at | |||||
| * | |||||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||||
| * | |||||
| * Unless required by applicable law or agreed to in writing, software | |||||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
| * See the License for the specific language governing permissions and | |||||
| * limitations under the License. | |||||
| * | |||||
| */ | |||||
| package org.apache.tools.ant.types.resources.comparators; | |||||
| import org.apache.tools.ant.types.Resource; | |||||
| /** | |||||
| * Compares Resources by is-directory status. As a container | |||||
| * of files, a directory is deemed "greater" than a file. | |||||
| * @since Ant 1.7 | |||||
| */ | |||||
| public class Type extends ResourceComparator { | |||||
| /** | |||||
| * Compare two Resources. | |||||
| * @param foo the first Resource. | |||||
| * @param bar the second Resource. | |||||
| * @return a negative integer, zero, or a positive integer as the first | |||||
| * argument is less than, equal to, or greater than the second. | |||||
| */ | |||||
| protected int resourceCompare(Resource foo, Resource bar) { | |||||
| boolean f = foo.isDirectory(); | |||||
| if (f == bar.isDirectory()) { | |||||
| return 0; | |||||
| } | |||||
| return f ? 1 : -1; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,43 @@ | |||||
| /* | |||||
| * Copyright 2005 The Apache Software Foundation | |||||
| * | |||||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||||
| * you may not use this file except in compliance with the License. | |||||
| * You may obtain a copy of the License at | |||||
| * | |||||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||||
| * | |||||
| * Unless required by applicable law or agreed to in writing, software | |||||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
| * See the License for the specific language governing permissions and | |||||
| * limitations under the License. | |||||
| * | |||||
| */ | |||||
| package org.apache.tools.ant.types.resources.selectors; | |||||
| import java.util.Iterator; | |||||
| import org.apache.tools.ant.types.Resource; | |||||
| /** | |||||
| * And ResourceSelector. | |||||
| * @since Ant 1.7 | |||||
| */ | |||||
| public class And extends ResourceSelectorContainer implements ResourceSelector { | |||||
| /** | |||||
| * Return true if this Resource is selected. | |||||
| * @param r the Resource to check. | |||||
| * @return whether the Resource was selected. | |||||
| */ | |||||
| public boolean isSelected(Resource r) { | |||||
| for (Iterator i = getSelectors(); i.hasNext();) { | |||||
| if (!((ResourceSelector) i.next()).isSelected(r)) { | |||||
| return false; | |||||
| } | |||||
| } | |||||
| return true; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,161 @@ | |||||
| /* | |||||
| * Copyright 2005 The Apache Software Foundation | |||||
| * | |||||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||||
| * you may not use this file except in compliance with the License. | |||||
| * You may obtain a copy of the License at | |||||
| * | |||||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||||
| * | |||||
| * Unless required by applicable law or agreed to in writing, software | |||||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
| * See the License for the specific language governing permissions and | |||||
| * limitations under the License. | |||||
| * | |||||
| */ | |||||
| package org.apache.tools.ant.types.resources.selectors; | |||||
| import java.text.DateFormat; | |||||
| import java.text.SimpleDateFormat; | |||||
| import java.text.ParseException; | |||||
| import java.util.Locale; | |||||
| import org.apache.tools.ant.BuildException; | |||||
| import org.apache.tools.ant.types.Resource; | |||||
| import org.apache.tools.ant.types.TimeComparison; | |||||
| import org.apache.tools.ant.util.FileUtils; | |||||
| /** | |||||
| * Date ResourceSelector. Based on the date FileSelector, with the most | |||||
| * notable difference being the lack of support for the includedirs attribute. | |||||
| * It is recommended that the effect of includeDirs = "false" be achieved for | |||||
| * resources by enclosing a "dir" Type ResourceSelector and a Date | |||||
| * ResourceSelector in an Or ResourceSelector. | |||||
| * @since Ant 1.7 | |||||
| */ | |||||
| public class Date implements ResourceSelector { | |||||
| private static final String MILLIS_OR_DATETIME | |||||
| = "Either the millis or the datetime attribute must be set."; | |||||
| private static final FileUtils FILE_UTILS = FileUtils.getFileUtils(); | |||||
| private Long millis = null; | |||||
| private String dateTime = null; | |||||
| private String pattern = null; | |||||
| private TimeComparison when = TimeComparison.EQUAL; | |||||
| private long granularity = FILE_UTILS.getFileTimestampGranularity(); | |||||
| /** | |||||
| * Set the date/time in milliseconds since 1970. | |||||
| * @param m the number of millis. | |||||
| */ | |||||
| public synchronized void setMillis(long m) { | |||||
| millis = new Long(m); | |||||
| } | |||||
| /** | |||||
| * Get the date/time in ms. | |||||
| * @return long number of millis since 1970. | |||||
| */ | |||||
| public synchronized long getMillis() { | |||||
| return millis == null ? -1L : millis.longValue(); | |||||
| } | |||||
| /** | |||||
| * Set the date and time as a String. | |||||
| * @param s the date & time to use. | |||||
| */ | |||||
| public synchronized void setDateTime(String s) { | |||||
| dateTime = s; | |||||
| millis = null; | |||||
| } | |||||
| /** | |||||
| * Get the date & time in String format. | |||||
| * @return a String representing a date & time. | |||||
| */ | |||||
| public synchronized String getDatetime() { | |||||
| return dateTime; | |||||
| } | |||||
| /** | |||||
| * Set the granularity to use for this ResourceSelector. | |||||
| * @param g the timestamp granularity. | |||||
| */ | |||||
| public synchronized void setGranularity(long g) { | |||||
| granularity = g; | |||||
| } | |||||
| /** | |||||
| * Get the timestamp granularity used by this ResourceSelector. | |||||
| * @return the long granularity. | |||||
| */ | |||||
| public synchronized long getGranularity() { | |||||
| return granularity; | |||||
| } | |||||
| /** | |||||
| * Set the optional pattern to use with the datetime attribute. | |||||
| * @param p the SimpleDateFormat-compatible pattern string. | |||||
| */ | |||||
| public synchronized void setPattern(String p) { | |||||
| pattern = p; | |||||
| } | |||||
| /** | |||||
| * Get the pattern for use with the datetime attribute. | |||||
| * @return a SimpleDateFormat-compatible pattern string. | |||||
| */ | |||||
| public synchronized String getPattern() { | |||||
| return pattern; | |||||
| } | |||||
| /** | |||||
| * Set the comparison mode. | |||||
| * @param c a TimeComparison object. | |||||
| */ | |||||
| public synchronized void setWhen(TimeComparison c) { | |||||
| when = c; | |||||
| } | |||||
| /** | |||||
| * Get the comparison mode. | |||||
| * @return a TimeComparison object. | |||||
| */ | |||||
| public synchronized TimeComparison getWhen() { | |||||
| return when; | |||||
| } | |||||
| /** | |||||
| * Return true if this Resource is selected. | |||||
| * @param r the Resource to check. | |||||
| * @return whether the Resource was selected. | |||||
| */ | |||||
| public synchronized boolean isSelected(Resource r) { | |||||
| if (dateTime == null && millis == null) { | |||||
| throw new BuildException(MILLIS_OR_DATETIME); | |||||
| } | |||||
| if (millis == null) { | |||||
| DateFormat df = ((pattern == null) | |||||
| ? DateFormat.getDateTimeInstance( | |||||
| DateFormat.SHORT, DateFormat.SHORT, Locale.US) | |||||
| : new SimpleDateFormat(pattern)); | |||||
| try { | |||||
| long m = df.parse(dateTime).getTime(); | |||||
| if (m < 0) { | |||||
| throw new BuildException("Date of " + dateTime | |||||
| + " results in negative milliseconds value" | |||||
| + " relative to epoch (January 1, 1970, 00:00:00 GMT)."); | |||||
| } | |||||
| setMillis(m); | |||||
| } catch (ParseException pe) { | |||||
| throw new BuildException("Date of " + dateTime | |||||
| + " Cannot be parsed correctly. It should be in" | |||||
| + (pattern == null | |||||
| ? " MM/DD/YYYY HH:MM AM_PM" : pattern) + " format."); | |||||
| } | |||||
| } | |||||
| return when.evaluate(r.getLastModified(), millis.longValue(), granularity); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,36 @@ | |||||
| /* | |||||
| * Copyright 2005 The Apache Software Foundation | |||||
| * | |||||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||||
| * you may not use this file except in compliance with the License. | |||||
| * You may obtain a copy of the License at | |||||
| * | |||||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||||
| * | |||||
| * Unless required by applicable law or agreed to in writing, software | |||||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
| * See the License for the specific language governing permissions and | |||||
| * limitations under the License. | |||||
| * | |||||
| */ | |||||
| package org.apache.tools.ant.types.resources.selectors; | |||||
| import org.apache.tools.ant.types.Resource; | |||||
| /** | |||||
| * Exists ResourceSelector. | |||||
| * @since Ant 1.7 | |||||
| */ | |||||
| public class Exists implements ResourceSelector { | |||||
| /** | |||||
| * Return true if this Resource is selected. | |||||
| * @param r the Resource to check. | |||||
| * @return whether the Resource was selected. | |||||
| */ | |||||
| public boolean isSelected(Resource r) { | |||||
| return r.isExists(); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,129 @@ | |||||
| /* | |||||
| * Copyright 2005 The Apache Software Foundation | |||||
| * | |||||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||||
| * you may not use this file except in compliance with the License. | |||||
| * You may obtain a copy of the License at | |||||
| * | |||||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||||
| * | |||||
| * Unless required by applicable law or agreed to in writing, software | |||||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
| * See the License for the specific language governing permissions and | |||||
| * limitations under the License. | |||||
| * | |||||
| */ | |||||
| package org.apache.tools.ant.types.resources.selectors; | |||||
| import org.apache.tools.ant.Project; | |||||
| import org.apache.tools.ant.ProjectHelper; | |||||
| import org.apache.tools.ant.BuildException; | |||||
| import org.apache.tools.ant.ComponentHelper; | |||||
| import org.apache.tools.ant.AntTypeDefinition; | |||||
| import org.apache.tools.ant.types.Resource; | |||||
| /** | |||||
| * InstanceOf ResourceSelector. | |||||
| * @since Ant 1.7 | |||||
| */ | |||||
| public class InstanceOf implements ResourceSelector { | |||||
| private static final String ONE_ONLY = "Exactly one of class|type must be set."; | |||||
| private Project project; | |||||
| private Class clazz; | |||||
| private String type; | |||||
| private String uri; | |||||
| /** | |||||
| * Set the Project instance for this InstanceOf selector. | |||||
| * @param p the Project instance used for type comparisons. | |||||
| */ | |||||
| public void setProject(Project p) { | |||||
| project = p; | |||||
| } | |||||
| /** | |||||
| * Set the class to compare against. | |||||
| * @param c the class. | |||||
| */ | |||||
| public void setClass(Class c) { | |||||
| if (clazz != null) { | |||||
| throw new BuildException("The class attribute has already been set."); | |||||
| } | |||||
| clazz = c; | |||||
| } | |||||
| /** | |||||
| * Set the Ant type to compare against. | |||||
| * @param s the type name. | |||||
| */ | |||||
| public void setType(String s) { | |||||
| type = s; | |||||
| } | |||||
| /** | |||||
| * Set the URI in which the Ant type, if specified, should be defined. | |||||
| * @param u the URI. | |||||
| */ | |||||
| public void setURI(String u) { | |||||
| uri = u; | |||||
| } | |||||
| /** | |||||
| * Get the comparison class. | |||||
| * @return the Class object. | |||||
| */ | |||||
| public Class getCheckClass() { | |||||
| return clazz; | |||||
| } | |||||
| /** | |||||
| * Get the comparison type. | |||||
| * @return the String typename. | |||||
| */ | |||||
| public String getType() { | |||||
| return type; | |||||
| } | |||||
| /** | |||||
| * Get the type's URI. | |||||
| * @return the String URI. | |||||
| */ | |||||
| public String getURI() { | |||||
| return uri; | |||||
| } | |||||
| /** | |||||
| * Return true if this Resource is selected. | |||||
| * @param r the Resource to check. | |||||
| * @return whether the Resource was selected. | |||||
| * @throws BuildException if an error occurs. | |||||
| */ | |||||
| public boolean isSelected(Resource r) { | |||||
| if ((clazz == null) == (type == null)) { | |||||
| throw new BuildException(ONE_ONLY); | |||||
| } | |||||
| Class c = clazz; | |||||
| if (type != null) { | |||||
| if (project == null) { | |||||
| throw new BuildException( | |||||
| "No project set for InstanceOf ResourceSelector; " | |||||
| + "the type attribute is invalid."); | |||||
| } | |||||
| AntTypeDefinition d = ComponentHelper.getComponentHelper( | |||||
| project).getDefinition(ProjectHelper.genComponentName(uri, type)); | |||||
| if (d == null) { | |||||
| throw new BuildException("type " + type + " not found."); | |||||
| } | |||||
| try { | |||||
| c = d.innerGetTypeClass(); | |||||
| } catch (ClassNotFoundException e) { | |||||
| throw new BuildException(e); | |||||
| } | |||||
| } | |||||
| return c.isAssignableFrom(r.getClass()); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,69 @@ | |||||
| /* | |||||
| * Copyright 2005 The Apache Software Foundation | |||||
| * | |||||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||||
| * you may not use this file except in compliance with the License. | |||||
| * You may obtain a copy of the License at | |||||
| * | |||||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||||
| * | |||||
| * Unless required by applicable law or agreed to in writing, software | |||||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
| * See the License for the specific language governing permissions and | |||||
| * limitations under the License. | |||||
| * | |||||
| */ | |||||
| package org.apache.tools.ant.types.resources.selectors; | |||||
| import java.util.Iterator; | |||||
| import org.apache.tools.ant.types.Resource; | |||||
| /** | |||||
| * Majority ResourceSelector. | |||||
| * @since Ant 1.7 | |||||
| */ | |||||
| public class Majority | |||||
| extends ResourceSelectorContainer implements ResourceSelector { | |||||
| private boolean tie = true; | |||||
| /** | |||||
| * Set whether ties are allowed. | |||||
| * @param b whether a tie is a pass. | |||||
| */ | |||||
| public synchronized void setAllowtie(boolean b) { | |||||
| tie = b; | |||||
| } | |||||
| /** | |||||
| * Return true if this Resource is selected. | |||||
| * @param r the Resource to check. | |||||
| * @return whether the Resource was selected. | |||||
| */ | |||||
| public synchronized boolean isSelected(Resource r) { | |||||
| int passed = 0; | |||||
| int failed = 0; | |||||
| int count = selectorCount(); | |||||
| boolean even = count % 2 == 0; | |||||
| int threshold = count / 2; | |||||
| for (Iterator i = getSelectors(); i.hasNext();) { | |||||
| if (((ResourceSelector) i.next()).isSelected(r)) { | |||||
| ++passed; | |||||
| if (passed > threshold || (even && tie && passed == threshold)) { | |||||
| return true; | |||||
| } | |||||
| } else { | |||||
| ++failed; | |||||
| if (failed > threshold || (even && !tie && failed == threshold)) { | |||||
| return false; | |||||
| } | |||||
| } | |||||
| } | |||||
| //dummy | |||||
| return false; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,76 @@ | |||||
| /* | |||||
| * Copyright 2005 The Apache Software Foundation | |||||
| * | |||||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||||
| * you may not use this file except in compliance with the License. | |||||
| * You may obtain a copy of the License at | |||||
| * | |||||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||||
| * | |||||
| * Unless required by applicable law or agreed to in writing, software | |||||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
| * See the License for the specific language governing permissions and | |||||
| * limitations under the License. | |||||
| * | |||||
| */ | |||||
| package org.apache.tools.ant.types.resources.selectors; | |||||
| import org.apache.tools.ant.types.Resource; | |||||
| import org.apache.tools.ant.types.selectors.SelectorUtils; | |||||
| /** | |||||
| * Name ResourceSelector. | |||||
| * @since Ant 1.7 | |||||
| */ | |||||
| public class Name implements ResourceSelector { | |||||
| private String pattern; | |||||
| private boolean cs = true; | |||||
| /** | |||||
| * Set the pattern to compare names against. | |||||
| * @param n the pattern String to set. | |||||
| */ | |||||
| public void setName(String n) { | |||||
| pattern = n; | |||||
| } | |||||
| /** | |||||
| * Get the pattern used by this Name ResourceSelector. | |||||
| * @return the String selection pattern. | |||||
| */ | |||||
| public String getName() { | |||||
| return pattern; | |||||
| } | |||||
| /** | |||||
| * Set whether the name comparisons are case-sensitive. | |||||
| * @param b boolean case-sensitivity flag. | |||||
| */ | |||||
| public void setCaseSensitive(boolean b) { | |||||
| cs = b; | |||||
| } | |||||
| /** | |||||
| * Learn whether this Name ResourceSelector is case-sensitive. | |||||
| * @return boolean case-sensitivity flag. | |||||
| */ | |||||
| public boolean isCaseSensitive() { | |||||
| return cs; | |||||
| } | |||||
| /** | |||||
| * Return true if this Resource is selected. | |||||
| * @param r the Resource to check. | |||||
| * @return whether the Resource was selected. | |||||
| */ | |||||
| public boolean isSelected(Resource r) { | |||||
| String n = r.getName(); | |||||
| if (SelectorUtils.match(pattern, n, cs)) { | |||||
| return true; | |||||
| } | |||||
| String s = r.toString(); | |||||
| return s.equals(n) ? false : SelectorUtils.match(pattern, s, cs); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,43 @@ | |||||
| /* | |||||
| * Copyright 2005 The Apache Software Foundation | |||||
| * | |||||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||||
| * you may not use this file except in compliance with the License. | |||||
| * You may obtain a copy of the License at | |||||
| * | |||||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||||
| * | |||||
| * Unless required by applicable law or agreed to in writing, software | |||||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
| * See the License for the specific language governing permissions and | |||||
| * limitations under the License. | |||||
| * | |||||
| */ | |||||
| package org.apache.tools.ant.types.resources.selectors; | |||||
| import java.util.Iterator; | |||||
| import org.apache.tools.ant.types.Resource; | |||||
| /** | |||||
| * None ResourceSelector. | |||||
| * @since Ant 1.7 | |||||
| */ | |||||
| public class None | |||||
| extends ResourceSelectorContainer implements ResourceSelector { | |||||
| /** | |||||
| * Return true if this Resource is selected. | |||||
| * @param r the Resource to check. | |||||
| * @return whether the Resource was selected. | |||||
| */ | |||||
| public boolean isSelected(Resource r) { | |||||
| boolean none = true; | |||||
| for (Iterator i = getSelectors(); none && i.hasNext();) { | |||||
| none = !((ResourceSelector) i.next()).isSelected(r); | |||||
| } | |||||
| return none; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,65 @@ | |||||
| /* | |||||
| * Copyright 2005 The Apache Software Foundation | |||||
| * | |||||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||||
| * you may not use this file except in compliance with the License. | |||||
| * You may obtain a copy of the License at | |||||
| * | |||||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||||
| * | |||||
| * Unless required by applicable law or agreed to in writing, software | |||||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
| * See the License for the specific language governing permissions and | |||||
| * limitations under the License. | |||||
| * | |||||
| */ | |||||
| package org.apache.tools.ant.types.resources.selectors; | |||||
| import org.apache.tools.ant.types.Resource; | |||||
| /** | |||||
| * Not ResourceSelector. | |||||
| * @since Ant 1.7 | |||||
| */ | |||||
| public class Not implements ResourceSelector { | |||||
| private ResourceSelector sel; | |||||
| /** | |||||
| * Default constructor. | |||||
| */ | |||||
| public Not() { | |||||
| } | |||||
| /** | |||||
| * Convenience constructor. | |||||
| * @param s the ResourceSelector to negate. | |||||
| */ | |||||
| public Not(ResourceSelector s) { | |||||
| add(s); | |||||
| } | |||||
| /** | |||||
| * Set the ResourceSelector. | |||||
| * @param s the ResourceSelector to negate. | |||||
| * @throws IllegalStateException if already set. | |||||
| */ | |||||
| public void add(ResourceSelector s) { | |||||
| if (sel != null) { | |||||
| throw new IllegalStateException( | |||||
| "The Not ResourceSelector accepts a single nested ResourceSelector"); | |||||
| } | |||||
| sel = s; | |||||
| } | |||||
| /** | |||||
| * Return true if this Resource is selected. | |||||
| * @param r the Resource to check. | |||||
| * @return whether the Resource was selected. | |||||
| */ | |||||
| public boolean isSelected(Resource r) { | |||||
| return !(sel.isSelected(r)); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,43 @@ | |||||
| /* | |||||
| * Copyright 2005 The Apache Software Foundation | |||||
| * | |||||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||||
| * you may not use this file except in compliance with the License. | |||||
| * You may obtain a copy of the License at | |||||
| * | |||||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||||
| * | |||||
| * Unless required by applicable law or agreed to in writing, software | |||||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
| * See the License for the specific language governing permissions and | |||||
| * limitations under the License. | |||||
| * | |||||
| */ | |||||
| package org.apache.tools.ant.types.resources.selectors; | |||||
| import java.util.Iterator; | |||||
| import org.apache.tools.ant.types.Resource; | |||||
| /** | |||||
| * Or ResourceSelector. | |||||
| * @since Ant 1.7 | |||||
| */ | |||||
| public class Or extends ResourceSelectorContainer implements ResourceSelector { | |||||
| /** | |||||
| * Return true if this Resource is selected. | |||||
| * @param r the Resource to check. | |||||
| * @return whether the Resource was selected. | |||||
| */ | |||||
| public boolean isSelected(Resource r) { | |||||
| for (Iterator i = getSelectors(); i.hasNext();) { | |||||
| if (((ResourceSelector) i.next()).isSelected(r)) { | |||||
| return true; | |||||
| } | |||||
| } | |||||
| return false; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,34 @@ | |||||
| /* | |||||
| * Copyright 2005 The Apache Software Foundation | |||||
| * | |||||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||||
| * you may not use this file except in compliance with the License. | |||||
| * You may obtain a copy of the License at | |||||
| * | |||||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||||
| * | |||||
| * Unless required by applicable law or agreed to in writing, software | |||||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
| * See the License for the specific language governing permissions and | |||||
| * limitations under the License. | |||||
| * | |||||
| */ | |||||
| package org.apache.tools.ant.types.resources.selectors; | |||||
| import org.apache.tools.ant.types.Resource; | |||||
| /** | |||||
| * Interface for a Resource selector. | |||||
| * @since Ant 1.7 | |||||
| */ | |||||
| public interface ResourceSelector { | |||||
| /** | |||||
| * Return true if this Resource is selected. | |||||
| * @param r the Resource to check. | |||||
| * @return whether the Resource was selected. | |||||
| */ | |||||
| public boolean isSelected(Resource r); | |||||
| } | |||||
| @@ -0,0 +1,111 @@ | |||||
| /* | |||||
| * Copyright 2005 The Apache Software Foundation | |||||
| * | |||||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||||
| * you may not use this file except in compliance with the License. | |||||
| * You may obtain a copy of the License at | |||||
| * | |||||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||||
| * | |||||
| * Unless required by applicable law or agreed to in writing, software | |||||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
| * See the License for the specific language governing permissions and | |||||
| * limitations under the License. | |||||
| * | |||||
| */ | |||||
| package org.apache.tools.ant.types.resources.selectors; | |||||
| import java.util.Stack; | |||||
| import java.util.Vector; | |||||
| import java.util.Iterator; | |||||
| import java.util.Collections; | |||||
| import org.apache.tools.ant.Project; | |||||
| import org.apache.tools.ant.BuildException; | |||||
| import org.apache.tools.ant.types.DataType; | |||||
| /** | |||||
| * ResourceSelector container. | |||||
| * @since Ant 1.7 | |||||
| */ | |||||
| public class ResourceSelectorContainer extends DataType { | |||||
| private Vector v = new Vector(); | |||||
| /** | |||||
| * Add a ResourceSelector to the container. | |||||
| * @param s the ResourceSelector to add. | |||||
| */ | |||||
| public void add(ResourceSelector s) { | |||||
| if (isReference()) { | |||||
| throw noChildrenAllowed(); | |||||
| } | |||||
| if (s == null) { | |||||
| return; | |||||
| } | |||||
| v.add(s); | |||||
| setChecked(false); | |||||
| } | |||||
| /** | |||||
| * Learn whether this ResourceSelectorContainer has selectors. | |||||
| * @return boolean indicating whether selectors have been added to the container. | |||||
| */ | |||||
| public boolean hasSelectors() { | |||||
| if (isReference()) { | |||||
| return ((ResourceSelectorContainer) getCheckedRef()).hasSelectors(); | |||||
| } | |||||
| dieOnCircularReference(); | |||||
| return !v.isEmpty(); | |||||
| } | |||||
| /** | |||||
| * Get the count of nested selectors. | |||||
| * @return the selector count as int. | |||||
| */ | |||||
| public int selectorCount() { | |||||
| if (isReference()) { | |||||
| return ((ResourceSelectorContainer) getCheckedRef()).selectorCount(); | |||||
| } | |||||
| dieOnCircularReference(); | |||||
| return v.size(); | |||||
| } | |||||
| /** | |||||
| * Return an Iterator over the nested selectors. | |||||
| * @return Iterator of ResourceSelectors. | |||||
| */ | |||||
| public Iterator getSelectors() { | |||||
| if (isReference()) { | |||||
| return ((ResourceSelectorContainer) getCheckedRef()).getSelectors(); | |||||
| } | |||||
| dieOnCircularReference(); | |||||
| return Collections.unmodifiableList(v).iterator(); | |||||
| } | |||||
| /** | |||||
| * Overrides the version from DataType to recurse on nested ResourceSelectors. | |||||
| * @param stk the Stack of references. | |||||
| * @param p the Project to resolve against. | |||||
| * @throws BuildException on error. | |||||
| */ | |||||
| public void dieOnCircularReference(Stack stk, Project p) { | |||||
| if (isChecked()) { | |||||
| return; | |||||
| } | |||||
| if (isReference()) { | |||||
| super.dieOnCircularReference(stk, p); | |||||
| } else { | |||||
| for (Iterator i = v.iterator(); i.hasNext();) { | |||||
| Object o = i.next(); | |||||
| if (o instanceof DataType) { | |||||
| stk.push(o); | |||||
| invokeCircularReferenceCheck((DataType) o, stk, p); | |||||
| } | |||||
| } | |||||
| setChecked(true); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,72 @@ | |||||
| /* | |||||
| * Copyright 2005 The Apache Software Foundation | |||||
| * | |||||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||||
| * you may not use this file except in compliance with the License. | |||||
| * You may obtain a copy of the License at | |||||
| * | |||||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||||
| * | |||||
| * Unless required by applicable law or agreed to in writing, software | |||||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
| * See the License for the specific language governing permissions and | |||||
| * limitations under the License. | |||||
| * | |||||
| */ | |||||
| package org.apache.tools.ant.types.resources.selectors; | |||||
| import org.apache.tools.ant.types.Resource; | |||||
| import org.apache.tools.ant.types.Comparison; | |||||
| /** | |||||
| * Size ResourceSelector. | |||||
| * @since Ant 1.7 | |||||
| */ | |||||
| public class Size implements ResourceSelector { | |||||
| private long size = -1; | |||||
| private Comparison when = Comparison.EQUAL; | |||||
| /** | |||||
| * Set the size to compare against. | |||||
| * @param l the long resource size. | |||||
| */ | |||||
| public void setSize(long l) { | |||||
| size = l; | |||||
| } | |||||
| /** | |||||
| * Get the size compared to by this Size ResourceSelector. | |||||
| * @return the long resource size. | |||||
| */ | |||||
| public long getSize() { | |||||
| return size; | |||||
| } | |||||
| /** | |||||
| * Set the comparison mode. | |||||
| * @param c a Comparison object. | |||||
| */ | |||||
| public void setWhen(Comparison c) { | |||||
| when = c; | |||||
| } | |||||
| /** | |||||
| * Get the comparison mode. | |||||
| * @return a Comparison object. | |||||
| */ | |||||
| public Comparison getWhen() { | |||||
| return when; | |||||
| } | |||||
| /** | |||||
| * Return true if this Resource is selected. | |||||
| * @param r the Resource to check. | |||||
| * @return whether the Resource was selected. | |||||
| */ | |||||
| public boolean isSelected(Resource r) { | |||||
| long diff = r.getSize() - size; | |||||
| return when.evaluate(diff == 0 ? 0 : (int) (diff / Math.abs(diff))); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,67 @@ | |||||
| /* | |||||
| * Copyright 2005 The Apache Software Foundation | |||||
| * | |||||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||||
| * you may not use this file except in compliance with the License. | |||||
| * You may obtain a copy of the License at | |||||
| * | |||||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||||
| * | |||||
| * Unless required by applicable law or agreed to in writing, software | |||||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
| * See the License for the specific language governing permissions and | |||||
| * limitations under the License. | |||||
| * | |||||
| */ | |||||
| package org.apache.tools.ant.types.resources.selectors; | |||||
| import org.apache.tools.ant.BuildException; | |||||
| import org.apache.tools.ant.types.Resource; | |||||
| import org.apache.tools.ant.types.EnumeratedAttribute; | |||||
| /** | |||||
| * Type file/dir ResourceSelector. | |||||
| * @since Ant 1.7 | |||||
| */ | |||||
| public class Type implements ResourceSelector { | |||||
| /** | |||||
| * Implements the type attribute. | |||||
| */ | |||||
| public static class FileDir extends EnumeratedAttribute { | |||||
| private static final String[] VALUES = new String[] {"file", "dir"}; | |||||
| /** | |||||
| * Return the possible values. | |||||
| * @return a String array. | |||||
| */ | |||||
| public String[] getValues() { | |||||
| return VALUES; | |||||
| } | |||||
| } | |||||
| private FileDir type = null; | |||||
| /** | |||||
| * Set type; file|dir. | |||||
| * @param fd a FileDir object. | |||||
| */ | |||||
| public void setType(FileDir fd) { | |||||
| type = fd; | |||||
| } | |||||
| /** | |||||
| * Return true if this Resource is selected. | |||||
| * @param r the Resource to check. | |||||
| * @return whether the Resource was selected. | |||||
| */ | |||||
| public boolean isSelected(Resource r) { | |||||
| if (type == null) { | |||||
| throw new BuildException("The type attribute is required."); | |||||
| } | |||||
| int i = type.getIndex(); | |||||
| return r.isDirectory() ? i == 1 : i == 0; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,143 @@ | |||||
| /* | |||||
| * Copyright 2005 The Apache Software Foundation | |||||
| * | |||||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||||
| * you may not use this file except in compliance with the License. | |||||
| * You may obtain a copy of the License at | |||||
| * | |||||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||||
| * | |||||
| * Unless required by applicable law or agreed to in writing, software | |||||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
| * See the License for the specific language governing permissions and | |||||
| * limitations under the License. | |||||
| * | |||||
| */ | |||||
| package org.apache.tools.ant.util; | |||||
| import java.io.InputStream; | |||||
| import java.io.BufferedInputStream; | |||||
| import java.io.IOException; | |||||
| import java.util.Iterator; | |||||
| import org.apache.tools.ant.Project; | |||||
| import org.apache.tools.ant.ProjectComponent; | |||||
| import org.apache.tools.ant.types.Resource; | |||||
| import org.apache.tools.ant.types.ResourceCollection; | |||||
| /** | |||||
| * Special <code>InputStream</code> that will | |||||
| * concatenate the contents of Resources from a single ResourceCollection. | |||||
| */ | |||||
| public class ConcatResourceInputStream extends InputStream { | |||||
| private static final int EOF = -1; | |||||
| private boolean eof = false; | |||||
| private Iterator iter; | |||||
| private InputStream currentStream; | |||||
| private ProjectComponent managingPc; | |||||
| private boolean ignoreErrors = false; | |||||
| /** | |||||
| * Construct a new ConcatResourceInputStream | |||||
| * for the specified ResourceCollection. | |||||
| * @param rc the ResourceCollection to combine. | |||||
| * @throws IOException if I/O errors occur. | |||||
| */ | |||||
| public ConcatResourceInputStream(ResourceCollection rc) throws IOException { | |||||
| iter = rc.iterator(); | |||||
| } | |||||
| /** | |||||
| * Set whether this ConcatResourceInputStream ignores errors. | |||||
| * @param b whether to ignore errors. | |||||
| */ | |||||
| public void setIgnoreErrors(boolean b) { | |||||
| ignoreErrors = b; | |||||
| } | |||||
| /** | |||||
| * Find out whether this ConcatResourceInputStream ignores errors. | |||||
| * @return boolean ignore-errors flag. | |||||
| */ | |||||
| public boolean isIgnoreErrors() { | |||||
| return ignoreErrors; | |||||
| } | |||||
| // inherit doc | |||||
| public void close() throws IOException { | |||||
| closeCurrent(); | |||||
| eof = true; | |||||
| } | |||||
| // inherit doc | |||||
| public int read() throws IOException { | |||||
| if (eof) { | |||||
| return EOF; | |||||
| } | |||||
| int result = readCurrent(); | |||||
| if (result == EOF) { | |||||
| nextResource(); | |||||
| result = readCurrent(); | |||||
| } | |||||
| return result; | |||||
| } | |||||
| /** | |||||
| * Set a managing <code>ProjectComponent</code> for | |||||
| * this <code>ConcatResourceInputStream</code>. | |||||
| * @param task the managing <code>Task</code>. | |||||
| */ | |||||
| public void setManagingComponent(ProjectComponent pc) { | |||||
| this.managingPc = pc; | |||||
| } | |||||
| /** | |||||
| * Log a message with the specified logging level. | |||||
| * @param message the <code>String</code> message. | |||||
| * @param loglevel the <code>int</code> logging level. | |||||
| */ | |||||
| public void log(String message, int loglevel) { | |||||
| if (managingPc != null) { | |||||
| managingPc.log(message, loglevel); | |||||
| } else { | |||||
| if (loglevel > Project.MSG_WARN) { | |||||
| System.out.println(message); | |||||
| } else { | |||||
| System.err.println(message); | |||||
| } | |||||
| } | |||||
| } | |||||
| private int readCurrent() throws IOException { | |||||
| return (eof || currentStream == null) ? EOF : currentStream.read(); | |||||
| } | |||||
| private void nextResource() throws IOException { | |||||
| closeCurrent(); | |||||
| while (iter.hasNext()) { | |||||
| Resource r = (Resource) iter.next(); | |||||
| if (!r.isExists()) { | |||||
| continue; | |||||
| } | |||||
| log("Concating " + r.toLongString(), Project.MSG_VERBOSE); | |||||
| try { | |||||
| currentStream = new BufferedInputStream(r.getInputStream()); | |||||
| return; | |||||
| } catch (IOException eyeOhEx) { | |||||
| if (!ignoreErrors) { | |||||
| log("Failed to get input stream for " + r, Project.MSG_ERR); | |||||
| throw eyeOhEx; | |||||
| } | |||||
| } | |||||
| } | |||||
| eof = true; | |||||
| } | |||||
| private void closeCurrent() { | |||||
| FileUtils.close(currentStream); | |||||
| currentStream = null; | |||||
| } | |||||
| } | |||||
| @@ -45,7 +45,10 @@ import org.apache.tools.ant.BuildException; | |||||
| import org.apache.tools.ant.Project; | import org.apache.tools.ant.Project; | ||||
| import org.apache.tools.ant.filters.util.ChainReaderHelper; | import org.apache.tools.ant.filters.util.ChainReaderHelper; | ||||
| import org.apache.tools.ant.taskdefs.condition.Os; | 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.FilterSetCollection; | ||||
| import org.apache.tools.ant.types.resources.Touchable; | |||||
| import org.apache.tools.ant.types.resources.FileResource; | |||||
| import org.apache.tools.ant.launch.Locator; | import org.apache.tools.ant.launch.Locator; | ||||
| /** | /** | ||||
| @@ -521,139 +524,204 @@ public class FileUtils { | |||||
| String inputEncoding, String outputEncoding, | String inputEncoding, String outputEncoding, | ||||
| Project project) | Project project) | ||||
| throws IOException { | 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 { | } 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. | * if this is -1, the current time is used. | ||||
| */ | */ | ||||
| public void setFileLastModified(File file, long time) { | 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 | * @since Ant 1.6.3 | ||||
| */ | */ | ||||
| public boolean contentEquals(File f1, File f2, boolean textfile) throws IOException { | 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; | return false; | ||||
| } | } | ||||
| if (!f1.exists()) { | |||||
| if (!r1.isExists()) { | |||||
| // two not existing files are equal | // two not existing files are equal | ||||
| return true; | 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? | // 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 | // don't want to compare directory contents for now | ||||
| return false; | return false; | ||||
| } | } | ||||
| if (fileNameEquals(f1, f2)) { | |||||
| // same filename => true | |||||
| if (r1.equals(r2)) { | |||||
| return true; | 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> | * <p> | ||||
| * simple but sub-optimal comparision algorithm. written for working | * simple but sub-optimal comparision algorithm. written for working | ||||
| * rather than fast. Better would be a block read into buffers followed | * rather than fast. Better would be a block read into buffers followed | ||||
| * by long comparisions apart from the final 1-7 bytes. | * by long comparisions apart from the final 1-7 bytes. | ||||
| * </p> | * </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 in1 = null; | ||||
| InputStream in2 = null; | InputStream in2 = null; | ||||
| try { | 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 { | } finally { | ||||
| close(in1); | close(in1); | ||||
| close(in2); | 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. | * 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 in1 = null; | ||||
| BufferedReader in2 = null; | BufferedReader in2 = null; | ||||
| try { | 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(); | String expected = in1.readLine(); | ||||
| while (expected != null) { | 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(); | expected = in1.readLine(); | ||||
| } | } | ||||
| if (in2.readLine() != null) { | |||||
| return false; | |||||
| } | |||||
| return true; | |||||
| return in2.readLine() == null ? 0 : -1; | |||||
| } finally { | } finally { | ||||
| close(in1); | close(in1); | ||||
| close(in2); | close(in2); | ||||
| @@ -1384,7 +1507,6 @@ public class FileUtils { | |||||
| return isUpToDate(sourceTime, destTime, granularity); | return isUpToDate(sourceTime, destTime, granularity); | ||||
| } | } | ||||
| /** | /** | ||||
| * Returns true if the source is older than the dest. | * Returns true if the source is older than the dest. | ||||
| * @param source source file (should be the older). | * @param source source file (should be the older). | ||||
| @@ -0,0 +1,69 @@ | |||||
| /* | |||||
| * Copyright 2005 The Apache Software Foundation | |||||
| * | |||||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||||
| * you may not use this file except in compliance with the License. | |||||
| * You may obtain a copy of the License at | |||||
| * | |||||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||||
| * | |||||
| * Unless required by applicable law or agreed to in writing, software | |||||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
| * See the License for the specific language governing permissions and | |||||
| * limitations under the License. | |||||
| * | |||||
| */ | |||||
| package org.apache.tools.ant.util; | |||||
| import java.io.IOException; | |||||
| import java.io.ByteArrayOutputStream; | |||||
| import org.apache.tools.ant.Project; | |||||
| /** | |||||
| * Exception thrown when an attempt is made to get an OutputStream | |||||
| * from an immutable Resource. | |||||
| * @since Ant 1.7 | |||||
| */ | |||||
| public class PropertyOutputStream extends ByteArrayOutputStream { | |||||
| private Project project; | |||||
| private String property; | |||||
| private boolean trim; | |||||
| /** | |||||
| * Construct a new PropertyOutputStream for the specified Project | |||||
| * and property name, trimming the property value. | |||||
| * @param p the associated Ant Project. | |||||
| * @param s the String property name. | |||||
| */ | |||||
| public PropertyOutputStream(Project p, String s) { | |||||
| this(p, s, true); | |||||
| } | |||||
| /** | |||||
| * Construct a new PropertyOutputStream for | |||||
| * the specified Project, property name, and trim mode. | |||||
| * @param p the associated Ant Project. | |||||
| * @param s the String property name. | |||||
| * @param b the boolean trim mode. | |||||
| */ | |||||
| public PropertyOutputStream(Project p, String s, boolean b) { | |||||
| project = p; | |||||
| property = s; | |||||
| trim = b; | |||||
| } | |||||
| /** | |||||
| * Close the PropertyOutputStream, storing the property. | |||||
| */ | |||||
| public void close() { | |||||
| if (project != null && property != null) { | |||||
| String s = new String(toByteArray()); | |||||
| project.setNewProperty(property, trim ? s.trim() : s); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -370,27 +370,29 @@ public class ZipFile { | |||||
| */ | */ | ||||
| private void positionAtCentralDirectory() | private void positionAtCentralDirectory() | ||||
| throws IOException { | throws IOException { | ||||
| long off = archive.length() - MIN_EOCD_SIZE; | |||||
| archive.seek(off); | |||||
| byte[] sig = ZipOutputStream.EOCD_SIG; | |||||
| int curr = archive.read(); | |||||
| boolean found = false; | 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(); | curr = archive.read(); | ||||
| if (curr == sig[2]) { | |||||
| if (curr == sig[1]) { | |||||
| curr = archive.read(); | 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) { | if (!found) { | ||||
| throw new ZipException("archive is not a ZIP archive"); | throw new ZipException("archive is not a ZIP archive"); | ||||
| @@ -0,0 +1,16 @@ | |||||
| <antlib> | |||||
| <typedef name="name" | |||||
| classname="org.apache.tools.ant.types.resources.comparators.Name" /> | |||||
| <typedef name="size" | |||||
| classname="org.apache.tools.ant.types.resources.comparators.Size" /> | |||||
| <typedef name="date" | |||||
| classname="org.apache.tools.ant.types.resources.comparators.Date" /> | |||||
| <typedef name="exists" | |||||
| classname="org.apache.tools.ant.types.resources.comparators.Exists" /> | |||||
| <typedef name="type" | |||||
| classname="org.apache.tools.ant.types.resources.comparators.Type" /> | |||||
| <typedef name="content" | |||||
| classname="org.apache.tools.ant.types.resources.comparators.Content" /> | |||||
| <typedef name="reverse" | |||||
| classname="org.apache.tools.ant.types.resources.comparators.Reverse" /> | |||||
| </antlib> | |||||
| @@ -0,0 +1,24 @@ | |||||
| <antlib> | |||||
| <typedef name="name" | |||||
| classname="org.apache.tools.ant.types.resources.selectors.Name" /> | |||||
| <typedef name="not" | |||||
| classname="org.apache.tools.ant.types.resources.selectors.Not" /> | |||||
| <typedef name="none" | |||||
| classname="org.apache.tools.ant.types.resources.selectors.None" /> | |||||
| <typedef name="and" | |||||
| classname="org.apache.tools.ant.types.resources.selectors.And" /> | |||||
| <typedef name="or" | |||||
| classname="org.apache.tools.ant.types.resources.selectors.Or" /> | |||||
| <typedef name="exists" | |||||
| classname="org.apache.tools.ant.types.resources.selectors.Exists" /> | |||||
| <typedef name="type" | |||||
| classname="org.apache.tools.ant.types.resources.selectors.Type" /> | |||||
| <typedef name="majority" | |||||
| classname="org.apache.tools.ant.types.resources.selectors.Majority" /> | |||||
| <typedef name="instanceof" | |||||
| classname="org.apache.tools.ant.types.resources.selectors.InstanceOf" /> | |||||
| <typedef name="size" | |||||
| classname="org.apache.tools.ant.types.resources.selectors.Size" /> | |||||
| <typedef name="date" | |||||
| classname="org.apache.tools.ant.types.resources.selectors.Date" /> | |||||
| </antlib> | |||||
| @@ -275,4 +275,9 @@ public class ConcatTest | |||||
| File f2 = getProject().resolveFile("concat.utf8"); | File f2 = getProject().resolveFile("concat.utf8"); | ||||
| assertTrue(FILE_UTILS.contentEquals(f1, f2)); | assertTrue(FILE_UTILS.contentEquals(f1, f2)); | ||||
| } | } | ||||
| public void testResources() { | |||||
| executeTarget("testResources"); | |||||
| } | |||||
| } | } | ||||
| @@ -0,0 +1,136 @@ | |||||
| /* | |||||
| * Copyright 2005 The Apache Software Foundation | |||||
| * | |||||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||||
| * you may not use this file except in compliance with the License. | |||||
| * You may obtain a copy of the License at | |||||
| * | |||||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||||
| * | |||||
| * Unless required by applicable law or agreed to in writing, software | |||||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
| * See the License for the specific language governing permissions and | |||||
| * limitations under the License. | |||||
| * | |||||
| */ | |||||
| package org.apache.tools.ant.types; | |||||
| import org.apache.tools.ant.BuildFileTest; | |||||
| public class ResourceCollectionsTest extends BuildFileTest { | |||||
| public ResourceCollectionsTest(String name) { | |||||
| super(name); | |||||
| } | |||||
| public void setUp() { | |||||
| configureProject("src/etc/testcases/types/resources/build.xml"); | |||||
| } | |||||
| public void tearDown() { | |||||
| executeTarget("tearDown"); | |||||
| } | |||||
| public void testdifference() { | |||||
| executeTarget("testdifference"); | |||||
| } | |||||
| public void testdirset() { | |||||
| executeTarget("testdirset"); | |||||
| } | |||||
| public void testfile() { | |||||
| executeTarget("testfile"); | |||||
| } | |||||
| public void testfilelist() { | |||||
| executeTarget("testfilelist"); | |||||
| } | |||||
| public void testfiles1() { | |||||
| executeTarget("testfiles1"); | |||||
| } | |||||
| public void testfiles2() { | |||||
| executeTarget("testfiles2"); | |||||
| } | |||||
| public void testfiles3() { | |||||
| executeTarget("testfiles3"); | |||||
| } | |||||
| public void testfileset() { | |||||
| executeTarget("testfileset"); | |||||
| } | |||||
| public void testfileurl() { | |||||
| executeTarget("testfileurl"); | |||||
| } | |||||
| public void testfileurlref() { | |||||
| executeTarget("testfileurlref"); | |||||
| } | |||||
| public void testhttpurl1() { | |||||
| executeTarget("testhttpurl1"); | |||||
| } | |||||
| public void testhttpurl2() { | |||||
| executeTarget("testhttpurl2"); | |||||
| } | |||||
| public void testintersect() { | |||||
| executeTarget("testintersect"); | |||||
| } | |||||
| public void testjarurl() { | |||||
| executeTarget("testjarurl"); | |||||
| } | |||||
| public void testnestedresources() { | |||||
| executeTarget("testnestedresources"); | |||||
| } | |||||
| public void testpath() { | |||||
| executeTarget("testpath"); | |||||
| } | |||||
| public void testpropertyset() { | |||||
| executeTarget("testpropertyset"); | |||||
| } | |||||
| public void testresource() { | |||||
| executeTarget("testresource"); | |||||
| } | |||||
| public void testresourcesref() { | |||||
| executeTarget("testresourcesref"); | |||||
| } | |||||
| public void testresourceurl() { | |||||
| executeTarget("testresourceurl"); | |||||
| } | |||||
| public void teststring1() { | |||||
| executeTarget("teststring1"); | |||||
| } | |||||
| public void teststring2() { | |||||
| executeTarget("teststring2"); | |||||
| } | |||||
| public void testunion() { | |||||
| executeTarget("testunion"); | |||||
| } | |||||
| public void testzipentry() { | |||||
| executeTarget("testzipentry"); | |||||
| } | |||||
| public void testzipfileset() { | |||||
| executeTarget("testzipfileset"); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,100 @@ | |||||
| /* | |||||
| * Copyright 2005 The Apache Software Foundation | |||||
| * | |||||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||||
| * you may not use this file except in compliance with the License. | |||||
| * You may obtain a copy of the License at | |||||
| * | |||||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||||
| * | |||||
| * Unless required by applicable law or agreed to in writing, software | |||||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
| * See the License for the specific language governing permissions and | |||||
| * limitations under the License. | |||||
| * | |||||
| */ | |||||
| package org.apache.tools.ant.types; | |||||
| import org.apache.tools.ant.BuildFileTest; | |||||
| public class ResourceComparatorsTest extends BuildFileTest { | |||||
| public ResourceComparatorsTest(String name) { | |||||
| super(name); | |||||
| } | |||||
| public void setUp() { | |||||
| configureProject("src/etc/testcases/types/resources/comparators/build.xml"); | |||||
| } | |||||
| public void tearDown() { | |||||
| executeTarget("tearDown"); | |||||
| } | |||||
| public void testcompoundsort1() { | |||||
| executeTarget("testcompoundsort1"); | |||||
| } | |||||
| public void testcompoundsort2() { | |||||
| executeTarget("testcompoundsort2"); | |||||
| } | |||||
| public void testcontent() { | |||||
| executeTarget("testcontent"); | |||||
| } | |||||
| public void testexists() { | |||||
| executeTarget("testexists"); | |||||
| } | |||||
| public void testdate() { | |||||
| executeTarget("testdate"); | |||||
| } | |||||
| public void testname() { | |||||
| executeTarget("testname"); | |||||
| } | |||||
| public void testrvcontent() { | |||||
| executeTarget("testrvcontent"); | |||||
| } | |||||
| public void testrvdefault() { | |||||
| executeTarget("testrvdefault"); | |||||
| } | |||||
| public void testrvexists() { | |||||
| executeTarget("testrvexists"); | |||||
| } | |||||
| public void testrvdate() { | |||||
| executeTarget("testrvdate"); | |||||
| } | |||||
| public void testrvname() { | |||||
| executeTarget("testrvname"); | |||||
| } | |||||
| public void testrvsize() { | |||||
| executeTarget("testrvsize"); | |||||
| } | |||||
| public void testrvtype() { | |||||
| executeTarget("testrvtype"); | |||||
| } | |||||
| public void testsize() { | |||||
| executeTarget("testsize"); | |||||
| } | |||||
| public void testsortdefault() { | |||||
| executeTarget("testsortdefault"); | |||||
| } | |||||
| public void testtype() { | |||||
| executeTarget("testtype"); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,153 @@ | |||||
| /* | |||||
| * Copyright 2005 The Apache Software Foundation | |||||
| * | |||||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||||
| * you may not use this file except in compliance with the License. | |||||
| * You may obtain a copy of the License at | |||||
| * | |||||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||||
| * | |||||
| * Unless required by applicable law or agreed to in writing, software | |||||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
| * See the License for the specific language governing permissions and | |||||
| * limitations under the License. | |||||
| * | |||||
| */ | |||||
| package org.apache.tools.ant.types; | |||||
| import java.io.File; | |||||
| import java.io.IOException; | |||||
| import java.io.InputStreamReader; | |||||
| import java.net.UnknownServiceException; | |||||
| import org.apache.tools.ant.Project; | |||||
| import org.apache.tools.ant.BuildFileTest; | |||||
| import org.apache.tools.ant.BuildException; | |||||
| import org.apache.tools.ant.taskdefs.Zip; | |||||
| import org.apache.tools.ant.types.Resource; | |||||
| import org.apache.tools.ant.types.resources.URLResource; | |||||
| import org.apache.tools.ant.types.resources.ZipResource; | |||||
| import org.apache.tools.ant.types.resources.FileResource; | |||||
| import org.apache.tools.ant.types.resources.StringResource; | |||||
| import org.apache.tools.ant.types.resources.PropertyResource; | |||||
| import org.apache.tools.ant.types.resources.ImmutableResourceException; | |||||
| import org.apache.tools.ant.util.FileUtils; | |||||
| public class ResourceOutputTest extends BuildFileTest { | |||||
| private static final FileUtils FILE_UTILS = FileUtils.getFileUtils(); | |||||
| private static final File basedir = new File(System.getProperty("root"), | |||||
| "src/etc/testcases/types/resources"); | |||||
| public ResourceOutputTest(String name) { | |||||
| super(name); | |||||
| } | |||||
| public void setUp() { | |||||
| project = new Project(); | |||||
| project.init(); | |||||
| project.setUserProperty("basedir" , basedir.getAbsolutePath()); | |||||
| } | |||||
| public void testresourceoutput() { | |||||
| try { | |||||
| testoutputbe(new Resource("foo")); | |||||
| fail("should have caught UnsupportedOperationException"); | |||||
| } catch (UnsupportedOperationException e) { | |||||
| } | |||||
| } | |||||
| public void teststringoutput1() { | |||||
| StringResource r = new StringResource(); | |||||
| testoutputbe(r); | |||||
| assertEquals("foo", r.getValue()); | |||||
| } | |||||
| public void teststringoutput2() { | |||||
| StringResource r = new StringResource("bar"); | |||||
| try { | |||||
| testoutput(r); | |||||
| fail("should have caught ImmutableResourceException"); | |||||
| } catch (ImmutableResourceException e) { | |||||
| } catch (IOException e) { | |||||
| fail("caught some other IOException: " + e); | |||||
| } | |||||
| assertEquals("bar", r.getValue()); | |||||
| } | |||||
| public void testpropertyoutput1() { | |||||
| PropertyResource r = new PropertyResource(getProject(), "bar"); | |||||
| testoutputbe(r); | |||||
| assertPropertyEquals("bar", "foo"); | |||||
| } | |||||
| public void testpropertyoutput2() { | |||||
| getProject().setNewProperty("bar", "bar"); | |||||
| PropertyResource r = new PropertyResource(getProject(), "bar"); | |||||
| try { | |||||
| testoutput(r); | |||||
| fail("should have caught ImmutableResourceException"); | |||||
| } catch (ImmutableResourceException e) { | |||||
| } catch (IOException e) { | |||||
| fail("caught some other IOException: " + e); | |||||
| } | |||||
| assertPropertyEquals("bar", "bar"); | |||||
| } | |||||
| public void testurloutput() { | |||||
| File f = getProject().resolveFile("testurloutput"); | |||||
| try { | |||||
| FILE_UTILS.createNewFile(f); | |||||
| testoutput(new URLResource(f)); | |||||
| fail("should have caught UnknownServiceException"); | |||||
| } catch (UnknownServiceException e) { | |||||
| } catch (IOException e) { | |||||
| e.printStackTrace(System.err); | |||||
| fail("caught some other IOException: " + e); | |||||
| } finally { | |||||
| if (!f.delete()) { | |||||
| f.deleteOnExit(); | |||||
| } | |||||
| } | |||||
| } | |||||
| public void testzipentryoutput() { | |||||
| Zip z = new Zip(); | |||||
| z.setProject(getProject()); | |||||
| Zip.WhenEmpty create = new Zip.WhenEmpty(); | |||||
| create.setValue("create"); | |||||
| z.setWhenempty(create); | |||||
| z.setBasedir(basedir); | |||||
| z.setExcludes("**/*"); | |||||
| File f = getProject().resolveFile("foo"); | |||||
| z.setDestFile(f); | |||||
| z.execute(); | |||||
| ZipResource r = new ZipResource(); | |||||
| r.setZipfile(f); | |||||
| r.setName("foo"); | |||||
| try { | |||||
| testoutputbe(r); | |||||
| fail("should have caught UnsupportedOperationException"); | |||||
| } catch (UnsupportedOperationException e) { | |||||
| } finally { | |||||
| if (!f.delete()) { | |||||
| f.deleteOnExit(); | |||||
| } | |||||
| } | |||||
| } | |||||
| private void testoutputbe(Resource dest) { | |||||
| try { | |||||
| testoutput(dest); | |||||
| } catch (IOException e) { | |||||
| throw new BuildException(e); | |||||
| } | |||||
| } | |||||
| private void testoutput(Resource dest) throws IOException { | |||||
| FILE_UTILS.copyResource(new StringResource("foo"), dest, null); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,100 @@ | |||||
| /* | |||||
| * Copyright 2005 The Apache Software Foundation | |||||
| * | |||||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||||
| * you may not use this file except in compliance with the License. | |||||
| * You may obtain a copy of the License at | |||||
| * | |||||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||||
| * | |||||
| * Unless required by applicable law or agreed to in writing, software | |||||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
| * See the License for the specific language governing permissions and | |||||
| * limitations under the License. | |||||
| * | |||||
| */ | |||||
| package org.apache.tools.ant.types; | |||||
| import org.apache.tools.ant.BuildFileTest; | |||||
| public class ResourceSelectorsTest extends BuildFileTest { | |||||
| public ResourceSelectorsTest(String name) { | |||||
| super(name); | |||||
| } | |||||
| public void setUp() { | |||||
| configureProject("src/etc/testcases/types/resources/selectors/build.xml"); | |||||
| } | |||||
| public void testname1() { | |||||
| executeTarget("testname1"); | |||||
| } | |||||
| public void testname2() { | |||||
| executeTarget("testname2"); | |||||
| } | |||||
| public void testexists() { | |||||
| executeTarget("testexists"); | |||||
| } | |||||
| public void testinstanceoftype1() { | |||||
| executeTarget("testinstanceoftype1"); | |||||
| } | |||||
| public void testinstanceoftype2() { | |||||
| executeTarget("testinstanceoftype2"); | |||||
| } | |||||
| public void testinstanceofclass() { | |||||
| executeTarget("testinstanceofclass"); | |||||
| } | |||||
| public void testtype() { | |||||
| executeTarget("testtype"); | |||||
| } | |||||
| public void testdate() { | |||||
| executeTarget("testdate"); | |||||
| } | |||||
| public void testsize() { | |||||
| executeTarget("testsize"); | |||||
| } | |||||
| public void testand() { | |||||
| executeTarget("testand"); | |||||
| } | |||||
| public void testor() { | |||||
| executeTarget("testor"); | |||||
| } | |||||
| public void testnot() { | |||||
| executeTarget("testnot"); | |||||
| } | |||||
| public void testnone() { | |||||
| executeTarget("testnone"); | |||||
| } | |||||
| public void testmajority1() { | |||||
| executeTarget("testmajority1"); | |||||
| } | |||||
| public void testmajority2() { | |||||
| executeTarget("testmajority2"); | |||||
| } | |||||
| public void testmajority3() { | |||||
| executeTarget("testmajority3"); | |||||
| } | |||||
| public void testmajority4() { | |||||
| executeTarget("testmajority4"); | |||||
| } | |||||
| } | |||||
| @@ -172,4 +172,9 @@ public class ClassFileSetTest extends BuildFileTest { | |||||
| assertTrue("Result did not contain test" + File.separator + "ContainsOnlyInner.class", | assertTrue("Result did not contain test" + File.separator + "ContainsOnlyInner.class", | ||||
| files.containsKey("test" + File.separator + "MethodParam.class")); | files.containsKey("test" + File.separator + "MethodParam.class")); | ||||
| } | } | ||||
| public void testResourceCollection() { | |||||
| executeTarget("testresourcecollection"); | |||||
| } | |||||
| } | } | ||||