git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@278337 13f79535-47bb-0310-9956-ffa450edef68master
| @@ -0,0 +1,600 @@ | |||
| <html> | |||
| <head> | |||
| <meta http-equiv="Content-Language" content="en-us"> | |||
| <link rel="stylesheet" type="text/css" href="../stylesheets/style.css"> | |||
| <title>Resources and Resource Collections</title> | |||
| </head> | |||
| <body> | |||
| <h2><a name="resource">Resources</a></h2> | |||
| <p> | |||
| A file-like entity can be abstracted to the concept of a <i>resource</i>. | |||
| In addition to providing access to file-like attributes, a resource | |||
| implementation should, when possible, provide the means to read content | |||
| from and/or write content to the underlying entity. Although the resource | |||
| concept was introduced in <i>Ant 1.5.2</i>, resources are available for | |||
| explicit use beginning in <b>Ant 1.7</b>. | |||
| </p> | |||
| <h3>The built-in resource types are:</h3> | |||
| <ul> | |||
| <li><a href="#basic">resource</a> - a basic resource.</li> | |||
| <li><a href="#file">file</a> - a file.</li> | |||
| <li><a href="#zipentry">zipentry</a> - an entry in a zip file.</li> | |||
| <li><a href="#url">url</a> - a URL.</li> | |||
| <li><a href="#string">string</a> - a text string.</li> | |||
| <li><a href="#property">property</a> - an Ant property.</li> | |||
| </ul> | |||
| <h4><a name="basic">resource</a></h4> | |||
| <p>A basic resource. Other resource types derive from this basic | |||
| type; as such all its attributes are available, though in most cases | |||
| irrelevant attributes will be ignored. This and all resource | |||
| implementations are also usable as single-element | |||
| <a href="#collection">Resource Collections</a>. | |||
| </p> | |||
| <table border="1" cellpadding="2" cellspacing="0"> | |||
| <tr> | |||
| <td valign="top"><b>Attribute</b></td> | |||
| <td valign="top"><b>Description</b></td> | |||
| <td align="center" valign="top"><b>Required</b></td> | |||
| </tr> | |||
| <tr> | |||
| <td valign="top">name</td> | |||
| <td valign="top">The name of this resource</td> | |||
| <td align="center" valign="top">No</td> | |||
| </tr> | |||
| <tr> | |||
| <td valign="top">exists</td> | |||
| <td valign="top">Whether this resource exists</td> | |||
| <td align="center" valign="top">No, default <i>true</i></td> | |||
| </tr> | |||
| <tr> | |||
| <td valign="top">lastmodified</td> | |||
| <td valign="top">The last modification time of this resource</td> | |||
| <td align="center" valign="top">No</td> | |||
| </tr> | |||
| <tr> | |||
| <td valign="top">directory</td> | |||
| <td valign="top">Whether this resource is directory-like</td> | |||
| <td align="center" valign="top">No, default <i>false</i></td> | |||
| </tr> | |||
| <tr> | |||
| <td valign="top">size</td> | |||
| <td valign="top">The size of this resource</td> | |||
| <td align="center" valign="top">No</td> | |||
| </tr> | |||
| </table> | |||
| <h4><a name="file">file</a></h4> | |||
| <p>Represents a file accessible via local filesystem conventions.</p> | |||
| <table border="1" cellpadding="2" cellspacing="0"> | |||
| <tr> | |||
| <td valign="top"><b>Attribute</b></td> | |||
| <td valign="top"><b>Description</b></td> | |||
| <td align="center" valign="top"><b>Required</b></td> | |||
| </tr> | |||
| <tr> | |||
| <td valign="top">file</td> | |||
| <td valign="top">The file represented by this resource</td> | |||
| <td align="center" valign="top">Yes</td> | |||
| </tr> | |||
| <tr> | |||
| <td valign="top">base</td> | |||
| <td valign="top">The base directory of this resource. When this | |||
| attribute is set, attempts to access the name of the resource | |||
| will yield a path relative to this location.</td> | |||
| <td align="center" valign="top">No</td> | |||
| </tr> | |||
| </table> | |||
| <h4><a name="zipentry">zipentry</a></h4> | |||
| <p>Represents an entry in a ZIP archive.</p> | |||
| <table border="1" cellpadding="2" cellspacing="0"> | |||
| <tr> | |||
| <td valign="top"><b>Attribute</b></td> | |||
| <td valign="top"><b>Description</b></td> | |||
| <td align="center" valign="top"><b>Required</b></td> | |||
| </tr> | |||
| <tr> | |||
| <td valign="top">zipfile</td> | |||
| <td valign="top">The zip file containing this resource</td> | |||
| <td align="center" valign="top">Yes</td> | |||
| </tr> | |||
| <tr> | |||
| <td valign="top">name</td> | |||
| <td valign="top">The name of the archived resource</td> | |||
| <td align="center" valign="top">Yes</td> | |||
| </tr> | |||
| <tr> | |||
| <td valign="top">encoding</td> | |||
| <td valign="top">The encoding of the zipfile</td> | |||
| <td align="center" valign="top">No; | |||
| platform default used if unspecified</td> | |||
| </tr> | |||
| </table> | |||
| <h4><a name="url">url</a></h4> | |||
| <p>Represents a URL.</p> | |||
| <table border="1" cellpadding="2" cellspacing="0"> | |||
| <tr> | |||
| <td valign="top"><b>Attribute</b></td> | |||
| <td valign="top"><b>Description</b></td> | |||
| <td align="center" valign="top"><b>Required</b></td> | |||
| </tr> | |||
| <tr> | |||
| <td valign="top">url</td> | |||
| <td valign="top">The url to expose</td> | |||
| <td rowspan="3" align="center" valign="middle">Exactly one of these</td> | |||
| </tr> | |||
| <tr> | |||
| <td valign="top">file</td> | |||
| <td valign="top">The file to expose as a file: url</td> | |||
| </tr> | |||
| <tr> | |||
| <td valign="top">javaresource</td> | |||
| <td valign="top">The Java resource to expose as a jar: url</td> | |||
| </tr> | |||
| <tr> | |||
| <td valign="top">classpath</td> | |||
| <td valign="top">The classpath to use when establishing the URL | |||
| for a Java resource</td> | |||
| <td align="center" valign="top">No</td> | |||
| </tr> | |||
| </table> | |||
| <p>The classpath along which to search for a Java resource | |||
| can also be specified by means of one or more nested | |||
| <code><a href="../using.html#path">classpath</a></code> elements. | |||
| </p> | |||
| <h4><a name="string">string</a></h4> | |||
| <p>Represents a Java String. As such a string is readable but not writable.</p> | |||
| <table border="1" cellpadding="2" cellspacing="0"> | |||
| <tr> | |||
| <td valign="top"><b>Attribute</b></td> | |||
| <td valign="top"><b>Description</b></td> | |||
| <td align="center" valign="top"><b>Required</b></td> | |||
| </tr> | |||
| <tr> | |||
| <td valign="top">value</td> | |||
| <td valign="top">The value of this resource</td> | |||
| <td align="center" valign="top">Yes</td> | |||
| </tr> | |||
| </table> | |||
| <h4><a name="property">property</a></h4> | |||
| <p>Represents an Ant property.</p> | |||
| <table border="1" cellpadding="2" cellspacing="0"> | |||
| <tr> | |||
| <td valign="top"><b>Attribute</b></td> | |||
| <td valign="top"><b>Description</b></td> | |||
| <td align="center" valign="top"><b>Required</b></td> | |||
| </tr> | |||
| <tr> | |||
| <td valign="top">name</td> | |||
| <td valign="top">The property name</td> | |||
| <td align="center" valign="top">Yes</td> | |||
| </tr> | |||
| </table> | |||
| <hr> | |||
| <h2><a name="collection">Resource Collections</a></h2> | |||
| <p> | |||
| A Resource Collection is an abstraction of an entity that groups | |||
| together a number of <a href="#resource">resources</a>. Several of | |||
| Ant's "legacy" datatypes have been modified to behave as Resource Collections: | |||
| <ul> | |||
| <li><a href="fileset.html">fileset</a>, | |||
| <a href="dirset.html">dirset</a>, | |||
| <a href="filelist.html">filelist</a>, and | |||
| <a href="../using.html#path">path</a> | |||
| (and derivative types) expose <a href="#file">file</a> resources | |||
| </li> | |||
| <li><a href="zipfileset.html">zipfileset</a> | |||
| can expose <a href="#file">file</a> or <a href="#zipentry">zipentry</a> | |||
| resources depending on configuration | |||
| </li> | |||
| <li><a href="propertyset.html">propertyset</a> | |||
| exposes <a href="#property">property</a> resources | |||
| </li> | |||
| </ul> | |||
| </p> | |||
| <h3>The additional built-in resource collections are:</h3> | |||
| <ul> | |||
| <li><a href="#resources">resources</a> - generic resource collection</li> | |||
| <li><a href="#files">files</a> - collection of files similar to | |||
| <a href="fileset.html">fileset</a></li> | |||
| <li><a href="#restrict">restrict</a> - restrict a resource collection | |||
| to include only resources meeting specified criteria</li> | |||
| <li><a href="#sort">sort</a> - sorted resource collection</li> | |||
| <li><a href="#union">union</a> - set union of nested resource collections</li> | |||
| <li><a href="#intersect">intersect</a> - set intersection | |||
| of nested resource collections</li> | |||
| <li><a href="#difference">difference</a> - set difference | |||
| of nested resource collections</li> | |||
| </ul> | |||
| <h4><a name="resources">resources</a></h4> | |||
| <p>A generic resource collection, designed for use with | |||
| <a href="../using.html#references">references</a>. | |||
| For example, if a third-party Ant task generates a Resource Collection | |||
| of an unknown type, it can still be accessed via a | |||
| <code><resources></code> collection. The secondary use of this | |||
| collection type is as a container of other resource collections, | |||
| preserving the order of nested collections as well as | |||
| duplicate resources (contrast with <a href="#union">union</a>). | |||
| </p> | |||
| <h4><a name="files">files</a></h4> | |||
| <p>A group of files. These files are matched by <b>absolute</b> patterns | |||
| taken from a number of <a href="patternset.html">PatternSets</a>. | |||
| These can be specified as nested <code><patternset></code> | |||
| elements. In addition, <code><files></code> holds an implicit | |||
| PatternSet and supports the nested <code><include></code>, | |||
| <code><includesfile></code>, <code><exclude></code> | |||
| and <code><excludesfile></code> elements of PatternSet directly, | |||
| as well as PatternSet's attributes. | |||
| </p> | |||
| <p><a href="selectors.html">File Selectors</a> are available as nested | |||
| elements. A file must be selected by all selectors in order to be included; | |||
| <code><files></code> is thus equivalent to an | |||
| <code><and></code> file selector container. | |||
| </p> | |||
| <p><b>More simply put</b>, this type is equivalent to a | |||
| <a href="fileset.html">fileset</a> with no base directory. | |||
| <b>Please note</b> that without a base directory, | |||
| filesystem scanning is based entirely on include and exclude patterns. | |||
| A <a href="selectors.html#filenameselect">filename</a> (or any) | |||
| selector can <i>only</i> influence the scanning process <i>after</i> | |||
| the file has been included based on pattern-based selection. | |||
| </p> | |||
| <table border="1" cellpadding="2" cellspacing="0"> | |||
| <tr> | |||
| <td valign="top"><b>Attribute</b></td> | |||
| <td valign="top"><b>Description</b></td> | |||
| <td align="center" valign="top"><b>Required</b></td> | |||
| </tr> | |||
| <tr> | |||
| <td valign="top">includes</td> | |||
| <td valign="top">comma- or space-separated list of patterns | |||
| of files that must be included</td> | |||
| <td rowspan="2" valign="middle" align="center">At least one of these</td> | |||
| </tr> | |||
| <tr> | |||
| <td valign="top">includesfile</td> | |||
| <td valign="top">the name of a file; each line of this file is | |||
| taken to be an include pattern.</td> | |||
| </tr> | |||
| <tr> | |||
| <td valign="top">excludes</td> | |||
| <td valign="top">comma- or space-separated list of patterns | |||
| of files that must be excluded</td> | |||
| <td rowspan="2" valign="top" align="center">No, default none | |||
| (except default excludes when true)</td> | |||
| </tr> | |||
| <tr> | |||
| <td valign="top">excludesfile</td> | |||
| <td valign="top">the name of a file; each line of this file is | |||
| taken to be an exclude pattern.</td> | |||
| </tr> | |||
| <tr> | |||
| <td valign="top">defaultexcludes</td> | |||
| <td valign="top">Whether | |||
| <a href="../dirtasks.html#defaultexcludes">default excludes</a> | |||
| should be used</td> | |||
| <td valign="top" align="center">No, default <i>true</i></td> | |||
| </tr> | |||
| <tr> | |||
| <td valign="top">casesensitive</td> | |||
| <td valign="top">Whether patterns are case-sensitive</td> | |||
| <td valign="top" align="center">No, default <i>true</i></td> | |||
| </tr> | |||
| <tr> | |||
| <td valign="top">followsymlinks</td> | |||
| <td valign="top">Whether to follow symbolic links | |||
| (see note <a href="#symlink">below</a>)</td> | |||
| <td valign="top" align="center">No, default <i>true</i></td> | |||
| </tr> | |||
| </table> | |||
| <p><a name="symlink"><b>Note</b></a>: All files/directories for which | |||
| the canonical path is different from its path are considered symbolic | |||
| links. On Unix systems this usually means the file really is a | |||
| symbolic link but it may lead to false results on other | |||
| platforms. | |||
| </p> | |||
| <h4><a name="restrict">restrict</a></h4> | |||
| <p>Restricts another nested resource collection using resource selectors: | |||
| <blockquote> | |||
| <h4>Parameters specified as nested elements</h4> | |||
| <p>A single resource collection is required.</p> | |||
| <p>Nested resource selectors are used to "narrow down" the included | |||
| resources. These are patterned after <a href="selectors.html">file | |||
| selectors</a> but are, unsurprisingly, targeted to resources. | |||
| Several built-in resource selectors are available in the internal | |||
| <a href="antlib.html">antlib</a> | |||
| <code>org.apache.tools.ant.types.resources.selectors</code>: | |||
| </p> | |||
| <ul> | |||
| <li><a href="#rsel.name">name</a> - select resources by name.</li> | |||
| <li><a href="#rsel.exists">exists</a> - select existing resources.</li> | |||
| <li><a href="#rsel.date">date</a> - select resources by date.</li> | |||
| <li><a href="#rsel.type">type</a> - select resources by type.</li> | |||
| <li><a href="#rsel.size">size</a> - select resources by size.</li> | |||
| <li><a href="#rsel.instanceof">instanceof</a> | |||
| - select resources by class or Ant datatype.</li> | |||
| <li><a href="#rsel.and">and</a> - "and" nested resource selectors.</li> | |||
| <li><a href="#rsel.or">or</a> - "or" nested resource selectors.</li> | |||
| <li><a href="#rsel.not">not</a> - "not" a nested resource selector.</li> | |||
| <li><a href="#rsel.none">none</a> | |||
| - select resources selected by no nested resource selectors.</li> | |||
| <li><a href="#rsel.majority">majority</a> - select resources selected | |||
| by a majority of nested resource selectors.</li> | |||
| </ul> | |||
| <h4><a name="rsel.name">name</a></h4> | |||
| <p>Selects resources by name.</p> | |||
| <table border="1" cellpadding="2" cellspacing="0"> | |||
| <tr> | |||
| <td valign="top"><b>Attribute</b></td> | |||
| <td valign="top"><b>Description</b></td> | |||
| <td align="center" valign="top"><b>Required</b></td> | |||
| </tr> | |||
| <tr> | |||
| <td valign="top">name</td> | |||
| <td valign="top">The name pattern to test</td> | |||
| <td align="center" valign="top">Yes</td> | |||
| </tr> | |||
| <tr> | |||
| <td valign="top">casesensitive</td> | |||
| <td valign="top">Whether name comparisons are case-sensitive</td> | |||
| <td align="center" valign="top">No, default <i>true</i></td> | |||
| </tr> | |||
| </table> | |||
| <h4><a name="rsel.exists">exists</a></h4> | |||
| <p>Selects existing resources.</p> | |||
| <h4><a name="rsel.date">date</a></h4> | |||
| <p>Selects resources by date.</p> | |||
| <table border="1" cellpadding="2" cellspacing="0"> | |||
| <tr> | |||
| <td valign="top"><b>Attribute</b></td> | |||
| <td valign="top"><b>Description</b></td> | |||
| <td align="center" valign="top"><b>Required</b></td> | |||
| </tr> | |||
| <tr> | |||
| <td valign="top">millis</td> | |||
| <td valign="top">The comparison date/time in ms since January 1, 1970</td> | |||
| <td rowspan="2" align="center" valign="middle">One of these</td> | |||
| </tr> | |||
| <tr> | |||
| <td valign="top">datetime</td> | |||
| <td valign="top">The formatted comparison date/time</td> | |||
| </tr> | |||
| <tr> | |||
| <td valign="top">pattern</td> | |||
| <td valign="top">SimpleDateFormat-compatible pattern | |||
| for use with the <code>datetime</code> attribute</td> | |||
| <td align="center" valign="top"> | |||
| No, default is "MM/DD/YYYY HH:MM AM_or_PM"</td> | |||
| </tr> | |||
| <tr> | |||
| <td valign="top">granularity</td> | |||
| <td valign="top">The number of milliseconds leeway to use when | |||
| comparing file modification times. This is needed because not | |||
| every file system supports tracking the last modified time to | |||
| the millisecond level.</td> | |||
| <td align="center" valign="top">No; default varies by platform: | |||
| FAT filesystems = 2 sec; Unix = 1 sec; NTFS = 1 ms.</td> | |||
| </tr> | |||
| <tr> | |||
| <td valign="top">when</td> | |||
| <td valign="top">One of "before", "after", "equal"</td> | |||
| <td align="center" valign="top">No, default "equal"</td> | |||
| </tr> | |||
| </table> | |||
| <h4><a name="rsel.type">type</a></h4> | |||
| <p>Selects resources by type (file or directory).</p> | |||
| <table border="1" cellpadding="2" cellspacing="0"> | |||
| <tr> | |||
| <td valign="top"><b>Attribute</b></td> | |||
| <td valign="top"><b>Description</b></td> | |||
| <td align="center" valign="top"><b>Required</b></td> | |||
| </tr> | |||
| <tr> | |||
| <td valign="top">type</td> | |||
| <td valign="top">One of "file", "dir"</td> | |||
| <td align="center" valign="top">Yes</td> | |||
| </tr> | |||
| </table> | |||
| <h4><a name="rsel.size">size</a></h4> | |||
| <p>Selects resources by size.</p> | |||
| <table border="1" cellpadding="2" cellspacing="0"> | |||
| <tr> | |||
| <td valign="top"><b>Attribute</b></td> | |||
| <td valign="top"><b>Description</b></td> | |||
| <td align="center" valign="top"><b>Required</b></td> | |||
| </tr> | |||
| <tr> | |||
| <td valign="top">size</td> | |||
| <td valign="top">The size to compare</td> | |||
| <td align="center" valign="top">Yes</td> | |||
| </tr> | |||
| <tr> | |||
| <td valign="top">when</td> | |||
| <td valign="top">One of "equal", "eq", "greater", "gt", "less", "lt", | |||
| "ge" (greater or equal), "ne" (not equal), "le" (less or equal)</td> | |||
| <td align="center" valign="top">No, default "equal"</td> | |||
| </tr> | |||
| </table> | |||
| <h4><a name="rsel.instanceof">instanceof</a></h4> | |||
| <p>Selects resources by type.</p> | |||
| <table border="1" cellpadding="2" cellspacing="0"> | |||
| <tr> | |||
| <td valign="top"><b>Attribute</b></td> | |||
| <td valign="top"><b>Description</b></td> | |||
| <td align="center" valign="top"><b>Required</b></td> | |||
| </tr> | |||
| <tr> | |||
| <td valign="top">class</td> | |||
| <td valign="top">The class of which the resource must be an instance</td> | |||
| <td rowspan="2" align="center" valign="middle">One of these</td> | |||
| </tr> | |||
| <tr> | |||
| <td valign="top">type</td> | |||
| <td valign="top">The Ant type that must | |||
| be assignable from the resource</td> | |||
| </tr> | |||
| <tr> | |||
| <td valign="top">uri</td> | |||
| <td valign="top">The uri in which <i>type</i> must be defined</td> | |||
| <td valign="top">No</td> | |||
| </tr> | |||
| </table> | |||
| <h4><a name="rsel.and">and</a></h4> | |||
| <p>Selects a resource if it is selected by all nested resource selectors.</p> | |||
| <h4><a name="rsel.or">or</a></h4> | |||
| <p>Selects a resource if it is selected | |||
| by at least one nested resource selector.</p> | |||
| <h4><a name="rsel.not">not</a></h4> | |||
| <p>Negates the selection result of the single | |||
| nested resource selector allowed.</p> | |||
| <h4><a name="rsel.none">none</a></h4> | |||
| <p>Selects a resource if it is selected | |||
| by no nested resource selectors.</p> | |||
| <h4><a name="rsel.majority">majority</a></h4> | |||
| <p>Selects a resource if it is selected | |||
| by the majority of nested resource selectors.</p> | |||
| <table border="1" cellpadding="2" cellspacing="0"> | |||
| <tr> | |||
| <td valign="top"><b>Attribute</b></td> | |||
| <td valign="top"><b>Description</b></td> | |||
| <td align="center" valign="top"><b>Required</b></td> | |||
| </tr> | |||
| <tr> | |||
| <td valign="top">allowtie</td> | |||
| <td valign="top">Whether a tie (when there is an even number | |||
| of nested resource selectors) is considered a majority</td> | |||
| <td valign="top">No, default <i>true</i></td> | |||
| </tr> | |||
| </table> | |||
| </blockquote> | |||
| <h4><a name="sort">sort</a></h4> | |||
| <p>Sorts another nested resource collection according to the resources' | |||
| natural order, or by one or more nested resource comparators:</p> | |||
| <blockquote> | |||
| <h4>Parameters specified as nested elements</h4> | |||
| <p>A single resource collection is required.</p> | |||
| <p>The sort can be controlled and customized by specifying one or more | |||
| resource comparators. Resources can be sorted according to multiple | |||
| criteria; the first specified is the "outermost", while the last | |||
| specified is the "innermost". Several built-in resource comparators | |||
| are available in the internal <a href="antlib.html">antlib</a> | |||
| <code>org.apache.tools.ant.types.resources.comparators</code>: | |||
| </p> | |||
| <ul> | |||
| <li><a href="#rcmp.name">name</a> - sort resources by name</li> | |||
| <li><a href="#rcmp.exists">exists</a> - sort resources by existence</li> | |||
| <li><a href="#rcmp.date">date</a> - sort resources by date</li> | |||
| <li><a href="#rcmp.type">type</a> - sort resources by type</li> | |||
| <li><a href="#rcmp.size">size</a> - sort resources by size</li> | |||
| <li><a href="#rcmp.content">content</a> - sort resources by content</li> | |||
| <li><a href="#rcmp.reverse">reverse</a> - reverse the natural sort order, | |||
| or a single nested resource comparator</li> | |||
| </ul> | |||
| <h4><a name="rcmp.name">name</a></h4> | |||
| <p>Sort resources by name.</p> | |||
| <h4><a name="rcmp.exists">exists</a></h4> | |||
| <p>Sort resources by existence. | |||
| Not existing is considered "less than" existing.</p> | |||
| <h4><a name="rcmp.date">date</a></h4> | |||
| <p>Sort resources by date.</p> | |||
| <h4><a name="rcmp.type">type</a></h4> | |||
| <p>Sort resources by type (file or directory). | |||
| Because directories contain files, they are considered "greater".</p> | |||
| <h4><a name="rcmp.size">size</a></h4> | |||
| <p>Sort resources by size.</p> | |||
| <h4><a name="rcmp.content">content</a></h4> | |||
| <p>Sort resources by content.</p> | |||
| <table border="1" cellpadding="2" cellspacing="0"> | |||
| <tr> | |||
| <td valign="top"><b>Attribute</b></td> | |||
| <td valign="top"><b>Description</b></td> | |||
| <td align="center" valign="top"><b>Required</b></td> | |||
| </tr> | |||
| <tr> | |||
| <td valign="top">binary</td> | |||
| <td valign="top">Whether content should be compared in binary mode. | |||
| If <i>false<i>, content will be compared without regard to | |||
| platform-specific line-ending conventions.</td> | |||
| <td valign="top">No, default <i>true</i></td> | |||
| </tr> | |||
| </table> | |||
| <h4><a name="rcmp.reverse">reverse</a></h4> | |||
| <p>Reverse the natural sort order, or a single nested comparator.</p> | |||
| </blockquote> | |||
| <h4><a name="setlogic">Set operations</a></h4> | |||
| <blockquote> | |||
| <p>The following resource collections implement set operations:</p> | |||
| <ul> | |||
| <li><a href="#union">union</a></li> | |||
| <li><a href="#intersect">intersect</a></li> | |||
| <li><a href="#difference">difference</a></li> | |||
| </ul> | |||
| <h4><a name="union">union</a></h4> | |||
| <p>Union of nested resource collections.</p> | |||
| <h4><a name="intersect">intersect</a></h4> | |||
| <p>Intersection of nested resource collections.</p> | |||
| <h4><a name="difference">difference</a></h4> | |||
| <p>Difference of nested resource collections.</p> | |||
| </blockquote> | |||
| <hr> | |||
| <p align="center">Copyright © 2005 The Apache Software Foundation. All rights | |||
| Reserved.</p> | |||
| </body> | |||
| </html> | |||
| @@ -31,6 +31,8 @@ | |||
| <a href="CoreTypes/propertyset.html">PropertySet</a><br> | |||
| <a href="CoreTypes/redirector.html">I/O Redirectors</a><br> | |||
| <a href="CoreTypes/regexp.html">Regexp</a><br> | |||
| <a href="CoreTypes/resources.html">Resources</a><br> | |||
| <a href="CoreTypes/resources.html#collection">Resource Collections</a><br> | |||
| <a href="CoreTypes/selectors.html">Selectors</a><br> | |||
| <a href="CoreTypes/xmlcatalog.html">XMLCatalog</a><br> | |||
| <a href="CoreTypes/zipfileset.html">ZipFileSet</a><br> | |||
| @@ -15,6 +15,7 @@ | |||
| <delete file="concat.noeol"/> | |||
| <delete file="concat.linecr"/> | |||
| <delete file="concat.utf8"/> | |||
| <delete file="concat.urls"/> | |||
| </target> | |||
| <target name="test1"> | |||
| @@ -185,4 +186,30 @@ | |||
| </concat> | |||
| </target> | |||
| <target name="testResources" unless="offline"> | |||
| <concat destfile="concat.urls" binary="true"> | |||
| <url url="http://ant.apache.org" /> | |||
| <url url="http://ant.apache.org" /> | |||
| </concat> | |||
| <length property="expected" includeduplicates="true"> | |||
| <resources> | |||
| <url url="http://ant.apache.org" /> | |||
| <url url="http://ant.apache.org" /> | |||
| </resources> | |||
| </length> | |||
| <length property="actual"> | |||
| <fileset file="concat.urls" /> | |||
| </length> | |||
| <fail> | |||
| <condition> | |||
| <or> | |||
| <equals arg1="${actual}" arg2="0" /> | |||
| <not> | |||
| <equals arg1="${actual}" arg2="${expected}" /> | |||
| </not> | |||
| </or> | |||
| </condition> | |||
| </fail> | |||
| </target> | |||
| </project> | |||
| @@ -82,6 +82,30 @@ | |||
| <classfileset id="result" dir="${classes.dir}" rootclass="B"/> | |||
| </target> | |||
| <target name="testresourcecollection" depends="testsmallset"> | |||
| <fail> | |||
| <condition> | |||
| <not> | |||
| <and> | |||
| <resourcecount count="2" refid="result" /> | |||
| <resourcecount count="1"> | |||
| <intersect> | |||
| <resources refid="result" /> | |||
| <file file="${classes.dir}/B.class" /> | |||
| </intersect> | |||
| </resourcecount> | |||
| <resourcecount count="1"> | |||
| <intersect> | |||
| <resources refid="result" /> | |||
| <file file="${classes.dir}/C.class" /> | |||
| </intersect> | |||
| </resourcecount> | |||
| </and> | |||
| </not> | |||
| </condition> | |||
| </fail> | |||
| </target> | |||
| <target name="testcomboset" depends="src1setup, compile"> | |||
| <classfileset id="result" dir="${classes.dir}" rootclass="B"> | |||
| <include name="**/C.class"/> | |||
| @@ -0,0 +1,450 @@ | |||
| <project default="all" | |||
| xmlns:rsel="antlib:org.apache.tools.ant.types.resources.selectors"> | |||
| <property name="dirname" value="work" /> | |||
| <property name="dir" location="${dirname}" /> | |||
| <property name="zip" location="${dirname}.zip" /> | |||
| <property name="jar" location="${dirname}.jar" /> | |||
| <property name="file" location="${dirname}/file.txt" /> | |||
| <target name="init"> | |||
| <touch mkdirs="true"> | |||
| <filelist dir="${dir}/foo/a" files="x,y,z" /> | |||
| </touch> | |||
| <copy todir="${dir}/foo" enablemultiplemappings="true"> | |||
| <fileset dir="${dir}/foo" /> | |||
| <mapper> | |||
| <globmapper handledirsep="true" from="a/*" to="b/*" /> | |||
| <globmapper handledirsep="true" from="a/*" to="c/*" /> | |||
| </mapper> | |||
| </copy> | |||
| <copy todir="${dir}/bar"> | |||
| <fileset dir="${dir}/foo" /> | |||
| </copy> | |||
| <property name="foo" location="${dir}/foo" /> | |||
| <property name="foo.a" location="${dir}/foo/a" /> | |||
| <property name="foo.b" location="${dir}/foo/b" /> | |||
| <property name="foo.c" location="${dir}/foo/c" /> | |||
| <property name="bar" location="${dir}/bar" /> | |||
| <property name="bar.a" location="${dir}/bar/a" /> | |||
| <property name="bar.b" location="${dir}/bar/b" /> | |||
| <property name="bar.c" location="${dir}/bar/c" /> | |||
| </target> | |||
| <target name="tearDown"> | |||
| <delete dir="${dir}" /> | |||
| <delete file="${zip}" /> | |||
| <delete file="${jar}" deleteonexit="true" /> | |||
| <delete file="${file}" /> | |||
| </target> | |||
| <target name="testfiles1" depends="init"> | |||
| <fail> | |||
| <condition> | |||
| <not> | |||
| <resourcecount count="26"> | |||
| <files> | |||
| <include name="${dir}/foo/" /> | |||
| <include name="${dir}/bar/" /> | |||
| </files> | |||
| </resourcecount> | |||
| </not> | |||
| </condition> | |||
| </fail> | |||
| </target> | |||
| <target name="testfiles2" depends="init"> | |||
| <fail> | |||
| <condition> | |||
| <not> | |||
| <resourcecount count="8"> | |||
| <files> | |||
| <include name="${dir}/foo/" /> | |||
| <include name="${dir}/bar/" /> | |||
| <type type="dir" /> | |||
| </files> | |||
| </resourcecount> | |||
| </not> | |||
| </condition> | |||
| </fail> | |||
| </target> | |||
| <target name="testfiles3" depends="init"> | |||
| <fail> | |||
| <condition> | |||
| <not> | |||
| <resourcecount count="18"> | |||
| <files> | |||
| <include name="${dir}/foo/" /> | |||
| <include name="${dir}/bar/" /> | |||
| <type type="file" /> | |||
| </files> | |||
| </resourcecount> | |||
| </not> | |||
| </condition> | |||
| </fail> | |||
| </target> | |||
| <target name="files" depends="testfiles1,testfiles2,testfiles3" /> | |||
| <target name="testnestedresources" depends="init"> | |||
| <fail> | |||
| <condition> | |||
| <not> | |||
| <resourcecount count="27"><!-- include duplicates! --> | |||
| <resources> | |||
| <files> | |||
| <include name="${dir}/foo/" /> | |||
| <include name="${dir}/bar/" /> | |||
| <type type="file" /> | |||
| </files> | |||
| <files> | |||
| <include name="${dir}/foo/" /> | |||
| <type type="file" /> | |||
| </files> | |||
| </resources> | |||
| </resourcecount> | |||
| </not> | |||
| </condition> | |||
| </fail> | |||
| </target> | |||
| <target name="testresourcesref" depends="init"> | |||
| <files id="files"> | |||
| <include name="${dir}/foo/" /> | |||
| <include name="${dir}/bar/" /> | |||
| <type type="file" /> | |||
| </files> | |||
| <fail> | |||
| <condition> | |||
| <not> | |||
| <resourcecount count="18"> | |||
| <resources refid="files" /> | |||
| </resourcecount> | |||
| </not> | |||
| </condition> | |||
| </fail> | |||
| </target> | |||
| <target name="resources" depends="testnestedresources,testresourcesref" /> | |||
| <target name="testfileset" depends="init"> | |||
| <fail> | |||
| <condition> | |||
| <not> | |||
| <resourcecount count="9"> | |||
| <fileset dir="${dir}/foo" /> | |||
| </resourcecount> | |||
| </not> | |||
| </condition> | |||
| </fail> | |||
| </target> | |||
| <target name="testdirset" depends="init"> | |||
| <fail> | |||
| <condition> | |||
| <not> | |||
| <resourcecount count="4"> | |||
| <dirset dir="${dir}/foo" /> | |||
| </resourcecount> | |||
| </not> | |||
| </condition> | |||
| </fail> | |||
| </target> | |||
| <target name="testfilelist"> | |||
| <fail> | |||
| <condition> | |||
| <not> | |||
| <resourcecount count="5"> | |||
| <filelist dir="${dir}/foo" files="1,2,3,4,5" /> | |||
| </resourcecount> | |||
| </not> | |||
| </condition> | |||
| </fail> | |||
| </target> | |||
| <target name="testpath" depends="init"> | |||
| <fail> | |||
| <condition> | |||
| <not> | |||
| <resourcecount count="24"> | |||
| <path> | |||
| <path id="p"> | |||
| <fileset id="fs" dir="${foo.a}" /> <!-- 3 --> | |||
| <dirset id="ds" dir="${foo}" /> <!-- 4 --> | |||
| </path> | |||
| <pathelement id="pe" location="${dir}" /> <!-- 1 --> | |||
| <filelist id="fl" dir="${bar}" files="1,2,3,a,b,c" /> <!-- 6 --> | |||
| <files id="f" includes="${bar}/" /> <!-- 13; 3 overlap fl --> | |||
| </path> | |||
| </resourcecount> | |||
| </not> | |||
| </condition> | |||
| </fail> | |||
| </target> | |||
| <target name="createzip" depends="init"> | |||
| <zip destfile="${zip}" basedir="${dir}" /> | |||
| </target> | |||
| <target name="testzipfileset" depends="createzip"> | |||
| <fail> | |||
| <condition> | |||
| <not> | |||
| <resourcecount count="9"> | |||
| <zipfileset src="${zip}" includes="foo/" /> | |||
| </resourcecount> | |||
| </not> | |||
| </condition> | |||
| </fail> | |||
| </target> | |||
| <target name="testpropertyset"> | |||
| <property name="testpropertyset.a" value="a" /> | |||
| <property name="testpropertyset.aa" value="aa" /> | |||
| <property name="testpropertyset.aaa" value="aaa" /> | |||
| <propertyset id="testpropertyset"> | |||
| <propertyref prefix="testpropertyset." /> | |||
| </propertyset> | |||
| <fail> | |||
| <condition> | |||
| <not> | |||
| <and> | |||
| <resourcecount refid="testpropertyset" count="3" /> | |||
| <length length="12"> | |||
| <resources> | |||
| <resources refid="testpropertyset" /> | |||
| <propertyset refid="testpropertyset" /> | |||
| </resources> | |||
| </length> | |||
| </and> | |||
| </not> | |||
| </condition> | |||
| </fail> | |||
| </target> | |||
| <target name="legacy" | |||
| depends="testfileset,testdirset,testfilelist,testpath,testzipfileset,testpropertyset" /> | |||
| <target name="testunion" depends="init"> | |||
| <fail> | |||
| <condition> | |||
| <not> | |||
| <resourcecount count="4"> | |||
| <union> | |||
| <files includes="${foo.a}/w,${foo.a}/x" /> <!-- 1 --> | |||
| <fileset dir="${foo.a}" includes="x,y" /> <!-- 2; net 1 --> | |||
| <filelist dir="${foo.a}" files="v" /> <!-- 1 --> | |||
| <files includes="${foo.a}/y,${foo.a}/z" /> <!-- 2; net 1 --> | |||
| </union> | |||
| </resourcecount> | |||
| </not> | |||
| </condition> | |||
| </fail> | |||
| </target> | |||
| <target name="testintersect"> | |||
| <fail> | |||
| <condition> | |||
| <not> | |||
| <resourcecount count="3"> | |||
| <intersect> | |||
| <filelist dir="${dir}" files="1,2,3,4,5" /> | |||
| <filelist dir="${dir}" files="2,3,4,5,6" /> | |||
| <filelist dir="${dir}" files="3,4,5,6,7" /> | |||
| </intersect> | |||
| </resourcecount> | |||
| </not> | |||
| </condition> | |||
| </fail> | |||
| </target> | |||
| <target name="testdifference"> | |||
| <fail> | |||
| <condition> | |||
| <not> | |||
| <resourcecount count="2"> | |||
| <difference id="diff"> | |||
| <filelist dir="${dir}" files="1,2,3,4,5" /> | |||
| <filelist dir="${dir}" files="2,3,4,5,6" /> | |||
| <filelist dir="${dir}" files="3,4,5,6,7" /> | |||
| </difference> | |||
| </resourcecount> | |||
| </not> | |||
| </condition> | |||
| </fail> | |||
| </target> | |||
| <target name="setlogic" depends="testunion,testintersect,testdifference" /> | |||
| <target name="testfileurl"> | |||
| <condition property="blah"> | |||
| <length when="less" length="1"> | |||
| <url file="${ant.file}" /> | |||
| </length> | |||
| </condition> | |||
| <fail if="blah" /> | |||
| </target> | |||
| <target name="testfileurlref"> | |||
| <url id="fileurl" file="${ant.file}" /> | |||
| <condition property="blah"> | |||
| <length when="less" length="1"> | |||
| <url refid="fileurl" /> | |||
| </length> | |||
| </condition> | |||
| <fail if="blah" /> | |||
| </target> | |||
| <target name="testhttpurl1" unless="offline"> | |||
| <fail> | |||
| <condition> | |||
| <length when="less" length="1"> | |||
| <url url="http://ant.apache.org/index.html" /> | |||
| </length> | |||
| </condition> | |||
| </fail> | |||
| </target> | |||
| <target name="testhttpurl2" unless="offline"> | |||
| <concat destfile="${file}" force="true" append="false"> | |||
| <url id="httpurl" url="http://ant.apache.org/index.html" /> | |||
| <url refid="httpurl" /> | |||
| </concat> | |||
| <length property="httpurl.length"> | |||
| <url refid="httpurl" /> | |||
| </length> | |||
| <fail> | |||
| <condition> | |||
| <not> | |||
| <length file="${file}" when="greater" length="${httpurl.length}" /> | |||
| </not> | |||
| </condition> | |||
| </fail> | |||
| </target> | |||
| <target name="createjar" depends="init"> | |||
| <jar destfile="${jar}" basedir="${dir}" /> | |||
| </target> | |||
| <target name="testjarurl" depends="createjar"> | |||
| <pathconvert property="jarurl"> | |||
| <url file="${jar}" /> | |||
| </pathconvert> | |||
| <fail> | |||
| <condition> | |||
| <length when="less" length="1"> | |||
| <url url="jar:${jarurl}!/META-INF/MANIFEST.MF" /> | |||
| </length> | |||
| </condition> | |||
| </fail> | |||
| </target> | |||
| <target name="testresourceurl" depends="createjar"> | |||
| <!-- test ref while we're at it --> | |||
| <url id="resourceurl" | |||
| javaresource="foo/c/z" classpath="${jar}" /> | |||
| <fail> | |||
| <condition> | |||
| <resourcecount count="0"> | |||
| <restrict> | |||
| <url refid="resourceurl" /> | |||
| <rsel:exists /> | |||
| </restrict> | |||
| </resourcecount> | |||
| </condition> | |||
| </fail> | |||
| </target> | |||
| <target name="url" | |||
| depends="testfileurl,testfileurlref,testhttpurl1,testhttpurl2,testjarurl,testresourceurl" /> | |||
| <target name="testfile" depends="init"> | |||
| <echo file="${file}">This is a test.</echo> | |||
| <fail> | |||
| <condition> | |||
| <not> | |||
| <length length="15"> | |||
| <file file="${file}" /> | |||
| </length> | |||
| </not> | |||
| </condition> | |||
| </fail> | |||
| </target> | |||
| <target name="testzipentry" depends="createjar"> | |||
| <fail> | |||
| <condition> | |||
| <not> | |||
| <length when="greater" length="0"> | |||
| <zipentry zipfile="${jar}" name="META-INF/MANIFEST.MF" /> | |||
| </length> | |||
| </not> | |||
| </condition> | |||
| </fail> | |||
| </target> | |||
| <target name="teststring1"> | |||
| <fail> | |||
| <condition> | |||
| <not> | |||
| <length length="15"> | |||
| <string value="This is a test." /> | |||
| </length> | |||
| </not> | |||
| </condition> | |||
| </fail> | |||
| </target> | |||
| <target name="teststring2"> | |||
| <property name="test" value="foo" /> | |||
| <fail> | |||
| <condition> | |||
| <not> | |||
| <length length="14"> | |||
| <string value="This is a ${test}." /> | |||
| </length> | |||
| </not> | |||
| </condition> | |||
| </fail> | |||
| </target> | |||
| <target name="string" depends="teststring1,teststring2" /> | |||
| <target name="testresource"> | |||
| <fail> | |||
| <condition> | |||
| <not> | |||
| <length length="4096"> | |||
| <resource size="4096" /> | |||
| </length> | |||
| </not> | |||
| </condition> | |||
| </fail> | |||
| </target> | |||
| <target name="testproperty"> | |||
| <property name="testproperty" value="abcdefghij" /> | |||
| <fail> | |||
| <condition> | |||
| <not> | |||
| <length length="10"> | |||
| <propertyresource name="testproperty" /> | |||
| </length> | |||
| </not> | |||
| </condition> | |||
| </fail> | |||
| </target> | |||
| <target name="single" | |||
| depends="testresource,url,testfile,string,testzipentry,testproperty" /> | |||
| <target name="all" depends="legacy,files,resources,setlogic,single" /> | |||
| </project> | |||
| @@ -0,0 +1,326 @@ | |||
| <project default="sort" | |||
| xmlns:rcmp="antlib:org.apache.tools.ant.types.resources.comparators"> | |||
| <property name="dirname" value="work" /> | |||
| <property name="dir" location="${dirname}" /> | |||
| <target name="tearDown"> | |||
| <delete dir="${dir}" /> | |||
| <delete file="${zip}" /> | |||
| <delete file="${jar}" deleteonexit="true" /> | |||
| <delete file="${file}" /> | |||
| </target> | |||
| <target name="sortsetup" unless="sortsetup.done"> | |||
| <mkdir dir="${dir}" /> | |||
| <echo file="${dir}/b" message="yyy" /> | |||
| <echo file="${dir}/e" message="aaa" /> | |||
| <sleep seconds="2" /> | |||
| <echo file="${dir}/c" message="x" /> | |||
| <echo file="${dir}/d" message="x" /> | |||
| <sleep seconds="2" /> | |||
| <echo file="${dir}/a" message="zz" /> | |||
| <echo file="${dir}/f" message="zz" /> | |||
| <mkdir dir="${dir}/a.dir" /> | |||
| <mkdir dir="${dir}/b.dir" /> | |||
| <mkdir dir="${dir}/c.dir" /> | |||
| <macrodef name="mysort"> | |||
| <attribute name="property" /> | |||
| <attribute name="separator" default="," /> | |||
| <element name="cmp" optional="true" implicit="true" /> | |||
| <sequential> | |||
| <pathconvert property="@{property}" pathsep="@{separator}"> | |||
| <sort> | |||
| <fileset dir="${dir}" includes="a,b,c" /> | |||
| <cmp /> | |||
| </sort> | |||
| <flattenmapper /> | |||
| </pathconvert> | |||
| </sequential> | |||
| </macrodef> | |||
| <property name="sortsetup.done" value="true" /> | |||
| </target> | |||
| <target name="testsortdefault" depends="sortsetup"> | |||
| <mysort property="sortdf" /> | |||
| <fail> | |||
| <condition> | |||
| <not> | |||
| <equals arg1="${sortdf}" arg2="a,b,c" /> | |||
| </not> | |||
| </condition> | |||
| </fail> | |||
| </target> | |||
| <target name="testrvdefault" depends="sortsetup"> | |||
| <mysort property="sortdf-rev"> | |||
| <rcmp:reverse /> | |||
| </mysort> | |||
| <fail> | |||
| <condition> | |||
| <not> | |||
| <equals arg1="${sortdf-rev}" arg2="c,b,a" /> | |||
| </not> | |||
| </condition> | |||
| </fail> | |||
| </target> | |||
| <target name="testname" depends="sortsetup"> | |||
| <mysort property="sortnm"> | |||
| <rcmp:name /> | |||
| </mysort> | |||
| <fail> | |||
| <condition> | |||
| <not> | |||
| <equals arg1="${sortnm}" arg2="a,b,c" /> | |||
| </not> | |||
| </condition> | |||
| </fail> | |||
| </target> | |||
| <target name="testrvname" depends="sortsetup"> | |||
| <mysort property="sortnm-rev"> | |||
| <rcmp:reverse> | |||
| <rcmp:name /> | |||
| </rcmp:reverse> | |||
| </mysort> | |||
| <fail> | |||
| <condition> | |||
| <not> | |||
| <equals arg1="${sortnm-rev}" arg2="c,b,a" /> | |||
| </not> | |||
| </condition> | |||
| </fail> | |||
| </target> | |||
| <target name="testdate" depends="sortsetup"> | |||
| <mysort property="sortlm"> | |||
| <rcmp:date /> | |||
| </mysort> | |||
| <fail> | |||
| <condition> | |||
| <not> | |||
| <equals arg1="${sortlm}" arg2="b,c,a" /> | |||
| </not> | |||
| </condition> | |||
| </fail> | |||
| </target> | |||
| <target name="testrvdate" depends="sortsetup"> | |||
| <mysort property="sortlm-rev"> | |||
| <rcmp:reverse> | |||
| <rcmp:date /> | |||
| </rcmp:reverse> | |||
| </mysort> | |||
| <fail> | |||
| <condition> | |||
| <not> | |||
| <equals arg1="${sortlm-rev}" arg2="a,c,b" /> | |||
| </not> | |||
| </condition> | |||
| </fail> | |||
| </target> | |||
| <target name="testsize" depends="sortsetup"> | |||
| <mysort property="sortsz"> | |||
| <rcmp:size /> | |||
| </mysort> | |||
| <fail> | |||
| <condition> | |||
| <not> | |||
| <equals arg1="${sortsz}" arg2="c,a,b" /> | |||
| </not> | |||
| </condition> | |||
| </fail> | |||
| </target> | |||
| <target name="testrvsize" depends="sortsetup"> | |||
| <mysort property="sortsz-rev"> | |||
| <rcmp:reverse> | |||
| <rcmp:size /> | |||
| </rcmp:reverse> | |||
| </mysort> | |||
| <fail> | |||
| <condition> | |||
| <not> | |||
| <equals arg1="${sortsz-rev}" arg2="b,a,c" /> | |||
| </not> | |||
| </condition> | |||
| </fail> | |||
| </target> | |||
| <target name="testcontent" depends="sortsetup"> | |||
| <mysort property="sortct"> | |||
| <rcmp:content /> | |||
| </mysort> | |||
| <fail> | |||
| <condition> | |||
| <not> | |||
| <equals arg1="${sortct}" arg2="c,b,a" /> | |||
| </not> | |||
| </condition> | |||
| </fail> | |||
| </target> | |||
| <target name="testrvcontent" depends="sortsetup"> | |||
| <mysort property="sortct-rev"> | |||
| <rcmp:reverse> | |||
| <rcmp:content /> | |||
| </rcmp:reverse> | |||
| </mysort> | |||
| <fail> | |||
| <condition> | |||
| <not> | |||
| <equals arg1="${sortct-rev}" arg2="a,b,c" /> | |||
| </not> | |||
| </condition> | |||
| </fail> | |||
| </target> | |||
| <target name="testexists" depends="sortsetup"> | |||
| <pathconvert property="sortex" pathsep=","> | |||
| <sort> | |||
| <resources> | |||
| <file file="${dir}/a" /> | |||
| <resource name="redherring" exists="false" /> | |||
| </resources> | |||
| <rcmp:exists /> | |||
| </sort> | |||
| <flattenmapper /> | |||
| </pathconvert> | |||
| <fail> | |||
| <condition> | |||
| <not> | |||
| <equals arg1="${sortex}" arg2="redherring,a" /> | |||
| </not> | |||
| </condition> | |||
| </fail> | |||
| </target> | |||
| <target name="testrvexists" depends="sortsetup"> | |||
| <pathconvert property="sortex-rev" pathsep=","> | |||
| <sort> | |||
| <resources> | |||
| <file file="${dir}/a" /> | |||
| <resource name="redherring" exists="false" /> | |||
| </resources> | |||
| <rcmp:reverse> | |||
| <rcmp:exists /> | |||
| </rcmp:reverse> | |||
| </sort> | |||
| <flattenmapper /> | |||
| </pathconvert> | |||
| <fail> | |||
| <condition> | |||
| <not> | |||
| <equals arg1="${sortex-rev}" arg2="a,redherring" /> | |||
| </not> | |||
| </condition> | |||
| </fail> | |||
| </target> | |||
| <target name="testtype" depends="sortsetup"> | |||
| <pathconvert property="sorttp" pathsep=","> | |||
| <sort> | |||
| <resources> | |||
| <file file="${dir}/a" /> | |||
| <file file="${dir}/a.dir" /> | |||
| </resources> | |||
| <rcmp:type /> | |||
| </sort> | |||
| <flattenmapper /> | |||
| </pathconvert> | |||
| <fail> | |||
| <condition> | |||
| <not> | |||
| <equals arg1="${sorttp}" arg2="a,a.dir" /> | |||
| </not> | |||
| </condition> | |||
| </fail> | |||
| </target> | |||
| <target name="testrvtype" depends="sortsetup"> | |||
| <pathconvert property="sorttp-rev" pathsep=","> | |||
| <sort> | |||
| <resources> | |||
| <file file="${dir}/a" /> | |||
| <file file="${dir}/a.dir" /> | |||
| </resources> | |||
| <rcmp:reverse> | |||
| <rcmp:type /> | |||
| </rcmp:reverse> | |||
| </sort> | |||
| <flattenmapper /> | |||
| </pathconvert> | |||
| <fail> | |||
| <condition> | |||
| <not> | |||
| <equals arg1="${sorttp-rev}" arg2="a.dir,a" /> | |||
| </not> | |||
| </condition> | |||
| </fail> | |||
| </target> | |||
| <target name="forwardsort" | |||
| depends="testsortdefault,testname,testdate,testsize,testcontent,testexists,testtype" /> | |||
| <target name="reversesort" | |||
| depends="testrvdefault,testrvname,testrvdate,testrvsize,testrvcontent,testrvexists,testrvtype" /> | |||
| <target name="testcompoundsort1" depends="sortsetup"> | |||
| <pathconvert property="sortcmp1" pathsep=","> | |||
| <sort> | |||
| <resources> | |||
| <file file="${dir}/c" /> | |||
| <file file="${dir}/b.dir" /> | |||
| <file file="${dir}/a" /> | |||
| <file file="${dir}/c.dir" /> | |||
| <file file="${dir}/b" /> | |||
| <file file="${dir}/a.dir" /> | |||
| </resources> | |||
| <rcmp:reverse> | |||
| <rcmp:type /> | |||
| </rcmp:reverse> | |||
| <rcmp:name /> | |||
| </sort> | |||
| <flattenmapper /> | |||
| </pathconvert> | |||
| <fail> | |||
| <condition> | |||
| <not> | |||
| <equals arg1="${sortcmp1}" arg2="a.dir,b.dir,c.dir,a,b,c" /> | |||
| </not> | |||
| </condition> | |||
| </fail> | |||
| </target> | |||
| <target name="testcompoundsort2" depends="sortsetup"> | |||
| <pathconvert property="sortcmp2" pathsep=","> | |||
| <sort> | |||
| <files includes="${dir}/?" /> | |||
| <rcmp:size /> | |||
| <rcmp:content /> | |||
| <rcmp:reverse> | |||
| <rcmp:name /> | |||
| </rcmp:reverse> | |||
| </sort> | |||
| <flattenmapper /> | |||
| </pathconvert> | |||
| <fail> | |||
| <condition> | |||
| <not> | |||
| <equals arg1="${sortcmp2}" arg2="d,c,f,a,e,b" /> | |||
| </not> | |||
| </condition> | |||
| </fail> | |||
| </target> | |||
| <target name="compoundsort" depends="testcompoundsort1,testcompoundsort2" /> | |||
| <target name="sort" depends="forwardsort,reversesort,compoundsort" /> | |||
| </project> | |||
| @@ -0,0 +1,410 @@ | |||
| <project default="all" | |||
| xmlns:rsel="antlib:org.apache.tools.ant.types.resources.selectors"> | |||
| <target name="testname1"> | |||
| <fail> | |||
| <condition> | |||
| <not> | |||
| <resourcecount when="equal" count="2"> | |||
| <restrict> | |||
| <resources> | |||
| <resource name="foo" /> | |||
| <resource name="bar" /> | |||
| <resource name="baz" /> | |||
| <resource name="boo" /> | |||
| <resource name="bang" /> | |||
| </resources> | |||
| <rsel:name name="ba?" /> | |||
| </restrict> | |||
| </resourcecount> | |||
| </not> | |||
| </condition> | |||
| </fail> | |||
| </target> | |||
| <target name="testname2"> | |||
| <fail> | |||
| <condition> | |||
| <not> | |||
| <resourcecount when="equal" count="2"> | |||
| <restrict> | |||
| <resources> | |||
| <file file="foo" /> | |||
| <resource name="foo" /> | |||
| <file file="foo" base="${basedir}" /> | |||
| </resources> | |||
| <rsel:name name="foo" /> | |||
| </restrict> | |||
| </resourcecount> | |||
| </not> | |||
| </condition> | |||
| </fail> | |||
| </target> | |||
| <target name="name" depends="testname1,testname2" /> | |||
| <target name="testexists"> | |||
| <fail> | |||
| <condition> | |||
| <not> | |||
| <resourcecount when="equal" count="1"> | |||
| <restrict> | |||
| <resources> | |||
| <file file="idonotexist" /> | |||
| <resource name="foo" /> | |||
| <resource name="foo" exists="false" /> | |||
| </resources> | |||
| <rsel:exists /> | |||
| </restrict> | |||
| </resourcecount> | |||
| </not> | |||
| </condition> | |||
| </fail> | |||
| </target> | |||
| <target name="testinstanceoftype1"> | |||
| <fail> | |||
| <condition> | |||
| <not> | |||
| <resourcecount when="equal" count="2"> | |||
| <restrict> | |||
| <resources> | |||
| <file file="foo" /> | |||
| <url url="http://ant.apache.org/index.html" /> | |||
| <resource name="foo" /> | |||
| <string value="foo" /> | |||
| <file file="bar" /> | |||
| </resources> | |||
| <rsel:instanceof type="file" /> | |||
| </restrict> | |||
| </resourcecount> | |||
| </not> | |||
| </condition> | |||
| </fail> | |||
| </target> | |||
| <target name="testinstanceoftype2"> | |||
| <typedef name="file" uri="test" | |||
| classname="org.apache.tools.ant.types.resources.FileResource" /> | |||
| <fail> | |||
| <condition> | |||
| <not> | |||
| <resourcecount when="equal" count="1"> | |||
| <restrict> | |||
| <resources> | |||
| <url file="foo" /> | |||
| <file file="bar" xmlns="test" /> | |||
| </resources> | |||
| <rsel:instanceof type="test:file" /> | |||
| </restrict> | |||
| </resourcecount> | |||
| </not> | |||
| </condition> | |||
| </fail> | |||
| </target> | |||
| <target name="testinstanceoftype3"> | |||
| <typedef name="file" uri="test" | |||
| classname="org.apache.tools.ant.types.resources.FileResource" /> | |||
| <fail> | |||
| <condition> | |||
| <not> | |||
| <resourcecount when="equal" count="1"> | |||
| <restrict> | |||
| <resources> | |||
| <url file="foo" /> | |||
| <file file="bar" xmlns="test" /> | |||
| </resources> | |||
| <rsel:instanceof type="file" uri="test" /> | |||
| </restrict> | |||
| </resourcecount> | |||
| </not> | |||
| </condition> | |||
| </fail> | |||
| </target> | |||
| <target name="testinstanceoftype" | |||
| depends="testinstanceoftype1,testinstanceoftype2,testinstanceoftype3" /> | |||
| <target name="testinstanceofclass"> | |||
| <fail> | |||
| <condition> | |||
| <not> | |||
| <resourcecount when="equal" count="7"> | |||
| <restrict> | |||
| <resources> | |||
| <filelist dir="${basedir}" files="a,b,c,d,e,f,g" /> | |||
| </resources> | |||
| <rsel:instanceof class="org.apache.tools.ant.types.Resource" /> | |||
| </restrict> | |||
| </resourcecount> | |||
| </not> | |||
| </condition> | |||
| </fail> | |||
| </target> | |||
| <target name="instanceof" depends="testinstanceoftype,testinstanceofclass" /> | |||
| <target name="testtype"> | |||
| <fail> | |||
| <condition> | |||
| <not> | |||
| <resourcecount when="equal" count="2"> | |||
| <restrict> | |||
| <resources> | |||
| <file file="${basedir}" /> | |||
| <file file="${ant.file}" /> | |||
| <resource directory="true" /> | |||
| <resource directory="false" /> | |||
| </resources> | |||
| <rsel:type type="dir" /> | |||
| </restrict> | |||
| </resourcecount> | |||
| </not> | |||
| </condition> | |||
| </fail> | |||
| </target> | |||
| <target name="testdate"> | |||
| <fail> | |||
| <condition> | |||
| <not> | |||
| <resourcecount when="equal" count="3"> | |||
| <restrict> | |||
| <resources> | |||
| <resource lastmodified="4" /> | |||
| <resource lastmodified="5" /> | |||
| <resource lastmodified="6" /> | |||
| <resource lastmodified="7" /> | |||
| <resource lastmodified="8" /> | |||
| </resources> | |||
| <rsel:date when="after" millis="5" granularity="0" /> | |||
| </restrict> | |||
| </resourcecount> | |||
| </not> | |||
| </condition> | |||
| </fail> | |||
| </target> | |||
| <target name="testsize"> | |||
| <fail> | |||
| <condition> | |||
| <not> | |||
| <resourcecount when="equal" count="4"> | |||
| <restrict> | |||
| <resources> | |||
| <resource size="4" /> | |||
| <resource size="5" /> | |||
| <resource size="6" /> | |||
| <resource size="7" /> | |||
| <resource size="8" /> | |||
| </resources> | |||
| <rsel:size when="le" size="7" /> | |||
| </restrict> | |||
| </resourcecount> | |||
| </not> | |||
| </condition> | |||
| </fail> | |||
| </target> | |||
| <target name="testand"> | |||
| <fail> | |||
| <condition> | |||
| <not> | |||
| <resourcecount when="equal" count="1"> | |||
| <restrict> | |||
| <resources> | |||
| <string value="fee" /> | |||
| <resource name="fi" size="3" /> | |||
| <resource name="fo" /> | |||
| <resource name="fum" /> | |||
| </resources> | |||
| <and xmlns="antlib:org.apache.tools.ant.types.resources.selectors"> | |||
| <name name="f?" /> | |||
| <size size="3" /> | |||
| </and> | |||
| </restrict> | |||
| </resourcecount> | |||
| </not> | |||
| </condition> | |||
| </fail> | |||
| </target> | |||
| <target name="testor"> | |||
| <fail> | |||
| <condition> | |||
| <not> | |||
| <resourcecount when="equal" count="3"> | |||
| <restrict> | |||
| <resources> | |||
| <string value="fee" /> | |||
| <resource name="fi" size="3" /> | |||
| <resource name="fo" /> | |||
| <resource name="fum" /> | |||
| </resources> | |||
| <or xmlns="antlib:org.apache.tools.ant.types.resources.selectors"> | |||
| <name name="f?" /> | |||
| <size size="3" /> | |||
| </or> | |||
| </restrict> | |||
| </resourcecount> | |||
| </not> | |||
| </condition> | |||
| </fail> | |||
| </target> | |||
| <target name="testnot"> | |||
| <fail> | |||
| <condition> | |||
| <not> | |||
| <resourcecount when="equal" count="2"> | |||
| <restrict> | |||
| <resources> | |||
| <string value="fee" /> | |||
| <resource name="fi" size="3" /> | |||
| <resource name="fo" /> | |||
| <resource name="fum" /> | |||
| </resources> | |||
| <not xmlns="antlib:org.apache.tools.ant.types.resources.selectors"> | |||
| <size size="3" /> | |||
| </not> | |||
| </restrict> | |||
| </resourcecount> | |||
| </not> | |||
| </condition> | |||
| </fail> | |||
| </target> | |||
| <target name="testnone"> | |||
| <fail> | |||
| <condition> | |||
| <not> | |||
| <resourcecount when="equal" count="1"> | |||
| <restrict> | |||
| <resources> | |||
| <string value="fee" /> | |||
| <resource name="fi" size="3" /> | |||
| <resource name="fo" /> | |||
| <resource name="fum" /> | |||
| </resources> | |||
| <none xmlns="antlib:org.apache.tools.ant.types.resources.selectors"> | |||
| <name name="f?" /> | |||
| <size size="3" /> | |||
| </none> | |||
| </restrict> | |||
| </resourcecount> | |||
| </not> | |||
| </condition> | |||
| </fail> | |||
| </target> | |||
| <target name="testmajority1"> | |||
| <fail> | |||
| <condition> | |||
| <not> | |||
| <resourcecount when="equal" count="2"> | |||
| <restrict> | |||
| <resources> | |||
| <string value="fee" /> | |||
| <resource name="fi" size="3" /> | |||
| <resource name="fo" /> | |||
| <resource name="fum" /> | |||
| </resources> | |||
| <majority xmlns="antlib:org.apache.tools.ant.types.resources.selectors"> | |||
| <name name="f?" /> | |||
| <size size="3" /> | |||
| <instanceof type="string" /> | |||
| </majority> | |||
| </restrict> | |||
| </resourcecount> | |||
| </not> | |||
| </condition> | |||
| </fail> | |||
| </target> | |||
| <target name="testmajority2"> | |||
| <fail> | |||
| <condition> | |||
| <not> | |||
| <resourcecount when="equal" count="3"> | |||
| <restrict> | |||
| <resources> | |||
| <string value="fee" /> | |||
| <resource name="fi" size="3" /> | |||
| <resource name="fo" /> | |||
| <resource name="fum" /> | |||
| </resources> | |||
| <majority xmlns="antlib:org.apache.tools.ant.types.resources.selectors"> | |||
| <name name="f?" /> | |||
| <size size="3" /> | |||
| <instanceof type="resource" /> | |||
| </majority> | |||
| </restrict> | |||
| </resourcecount> | |||
| </not> | |||
| </condition> | |||
| </fail> | |||
| </target> | |||
| <target name="testmajority3"> | |||
| <fail> | |||
| <condition> | |||
| <not> | |||
| <resourcecount when="equal" count="3"> | |||
| <restrict> | |||
| <resources> | |||
| <string value="fee" /> | |||
| <resource name="fi" size="3" /> | |||
| <resource name="fo" /> | |||
| <resource name="fum" /> | |||
| </resources> | |||
| <majority allowtie="true" | |||
| xmlns="antlib:org.apache.tools.ant.types.resources.selectors"> | |||
| <name name="f?" /> | |||
| <size size="3" /> | |||
| <instanceof type="string" /> | |||
| <exists /> | |||
| </majority> | |||
| </restrict> | |||
| </resourcecount> | |||
| </not> | |||
| </condition> | |||
| </fail> | |||
| </target> | |||
| <target name="testmajority4"> | |||
| <fail> | |||
| <condition> | |||
| <not> | |||
| <resourcecount when="equal" count="2"> | |||
| <restrict> | |||
| <resources> | |||
| <string value="fee" /> | |||
| <resource name="fi" size="3" /> | |||
| <resource name="fo" /> | |||
| <resource name="fum" /> | |||
| </resources> | |||
| <majority allowtie="false" | |||
| xmlns="antlib:org.apache.tools.ant.types.resources.selectors"> | |||
| <name name="f?" /> | |||
| <size size="3" /> | |||
| <instanceof type="string" /> | |||
| <exists /> | |||
| </majority> | |||
| </restrict> | |||
| </resourcecount> | |||
| </not> | |||
| </condition> | |||
| </fail> | |||
| </target> | |||
| <target name="majority" | |||
| depends="testmajority1,testmajority2,testmajority3,testmajority4" /> | |||
| <target name="logical" | |||
| depends="testand,testor,testnone,testnot,majority" /> | |||
| <target name="all" | |||
| depends="name,testexists,instanceof,testtype,testdate,testsize,logical" /> | |||
| </project> | |||
| @@ -17,34 +17,46 @@ | |||
| package org.apache.tools.ant.taskdefs; | |||
| import java.io.File; | |||
| import java.io.Reader; | |||
| import java.io.Writer; | |||
| import java.io.FileReader; | |||
| import java.io.InputStream; | |||
| import java.io.IOException; | |||
| import java.io.PrintWriter; | |||
| import java.io.OutputStream; | |||
| import java.io.StringReader; | |||
| import java.io.BufferedReader; | |||
| import java.io.BufferedWriter; | |||
| import java.io.File; | |||
| import java.io.FileInputStream; | |||
| import java.io.FileOutputStream; | |||
| import java.io.FileReader; | |||
| import java.io.IOException; | |||
| import java.io.InputStreamReader; | |||
| import java.io.OutputStream; | |||
| import java.io.OutputStreamWriter; | |||
| import java.io.PrintWriter; | |||
| import java.io.Reader; | |||
| import java.io.StringReader; | |||
| import java.io.Writer; | |||
| import java.util.Enumeration; | |||
| import java.util.Iterator; | |||
| import java.util.Arrays; | |||
| import java.util.Vector; | |||
| import java.util.Iterator; | |||
| import java.util.Enumeration; | |||
| import org.apache.tools.ant.Task; | |||
| import org.apache.tools.ant.Project; | |||
| import org.apache.tools.ant.BuildException; | |||
| import org.apache.tools.ant.DirectoryScanner; | |||
| import org.apache.tools.ant.Project; | |||
| import org.apache.tools.ant.ProjectComponent; | |||
| import org.apache.tools.ant.Task; | |||
| import org.apache.tools.ant.filters.util.ChainReaderHelper; | |||
| import org.apache.tools.ant.types.FileList; | |||
| import org.apache.tools.ant.types.Path; | |||
| import org.apache.tools.ant.types.FileSet; | |||
| import org.apache.tools.ant.types.FileList; | |||
| import org.apache.tools.ant.types.FilterChain; | |||
| import org.apache.tools.ant.types.Path; | |||
| import org.apache.tools.ant.types.Resource; | |||
| import org.apache.tools.ant.types.ResourceCollection; | |||
| import org.apache.tools.ant.types.resources.Restrict; | |||
| import org.apache.tools.ant.types.resources.Resources; | |||
| import org.apache.tools.ant.types.resources.FileResource; | |||
| import org.apache.tools.ant.types.resources.StringResource; | |||
| import org.apache.tools.ant.types.resources.selectors.Not; | |||
| import org.apache.tools.ant.types.resources.selectors.Exists; | |||
| import org.apache.tools.ant.types.resources.selectors.ResourceSelector; | |||
| import org.apache.tools.ant.util.FileUtils; | |||
| import org.apache.tools.ant.util.ConcatResourceInputStream; | |||
| /** | |||
| * This class contains the 'concat' task, used to concatenate a series | |||
| @@ -68,32 +80,36 @@ public class Concat extends Task { | |||
| // The size of buffers to be used | |||
| private static final int BUFFER_SIZE = 8192; | |||
| private static final FileUtils FILE_UTILS = FileUtils.getFileUtils(); | |||
| private static final FileUtils FILE_UTILS = FileUtils.getFileUtils(); | |||
| private static final ResourceSelector EXISTS = new Exists(); | |||
| private static final ResourceSelector NOT_EXISTS = new Not(EXISTS); | |||
| // Attributes. | |||
| /** | |||
| * The destination of the stream. If <code>null</code>, the system | |||
| * console is used. | |||
| */ | |||
| private File destinationFile = null; | |||
| private File destinationFile; | |||
| /** | |||
| * Whether or not the stream should be appended if the destination file | |||
| * exists. | |||
| * Defaults to <code>false</code>. | |||
| */ | |||
| private boolean append = false; | |||
| private boolean append; | |||
| /** | |||
| * Stores the input file encoding. | |||
| */ | |||
| private String encoding = null; | |||
| private String encoding; | |||
| /** Stores the output file encoding. */ | |||
| private String outputEncoding = null; | |||
| private String outputEncoding; | |||
| /** Stores the binary attribute */ | |||
| private boolean binary = false; | |||
| private boolean binary; | |||
| // Child elements. | |||
| @@ -106,25 +122,49 @@ public class Concat extends Task { | |||
| * Stores a collection of file sets and/or file lists, used to | |||
| * select multiple files for concatenation. | |||
| */ | |||
| private Vector sources = new Vector(); | |||
| private Resources rc; | |||
| /** for filtering the concatenated */ | |||
| private Vector filterChains = null; | |||
| private Vector filterChains; | |||
| /** ignore dates on input files */ | |||
| private boolean forceOverwrite = true; | |||
| private boolean forceOverwrite = true; | |||
| /** String to place at the start of the concatented stream */ | |||
| private TextElement footer; | |||
| private TextElement footer; | |||
| /** String to place at the end of the concatented stream */ | |||
| private TextElement header; | |||
| private TextElement header; | |||
| /** add missing line.separator to files **/ | |||
| private boolean fixLastLine = false; | |||
| private boolean fixLastLine = false; | |||
| /** endofline for fixlast line */ | |||
| private String eolString = System.getProperty("line.separator"); | |||
| private String eolString; | |||
| /** outputwriter */ | |||
| private Writer outputWriter = null; | |||
| private Writer outputWriter = null; | |||
| /** internal variable - used to collect the source files from sources */ | |||
| private Vector sourceFiles = new Vector(); | |||
| /** | |||
| * Construct a new Concat task. | |||
| */ | |||
| public Concat() { | |||
| reset(); | |||
| } | |||
| /** | |||
| * Reset state to default. | |||
| */ | |||
| public void reset() { | |||
| append = false; | |||
| forceOverwrite = true; | |||
| destinationFile = null; | |||
| encoding = null; | |||
| outputEncoding = null; | |||
| fixLastLine = false; | |||
| filterChains = null; | |||
| footer = null; | |||
| header = null; | |||
| binary = false; | |||
| outputWriter = null; | |||
| textBuffer = null; | |||
| eolString = System.getProperty("line.separator"); | |||
| rc = null; | |||
| } | |||
| // Attribute setters. | |||
| @@ -187,7 +227,7 @@ public class Concat extends Task { | |||
| */ | |||
| public Path createPath() { | |||
| Path path = new Path(getProject()); | |||
| sources.addElement(path); | |||
| add(path); | |||
| return path; | |||
| } | |||
| @@ -196,7 +236,7 @@ public class Concat extends Task { | |||
| * @param set the set of files | |||
| */ | |||
| public void addFileset(FileSet set) { | |||
| sources.addElement(set); | |||
| add(set); | |||
| } | |||
| /** | |||
| @@ -204,7 +244,17 @@ public class Concat extends Task { | |||
| * @param list the list of files | |||
| */ | |||
| public void addFilelist(FileList list) { | |||
| sources.addElement(list); | |||
| add(list); | |||
| } | |||
| /** | |||
| * Add an arbitrary ResourceCollection. | |||
| * @param c the ResourceCollection to add. | |||
| * @since Ant 1.7 | |||
| */ | |||
| public void add(ResourceCollection c) { | |||
| rc = (rc == null) ? new Resources() : rc; | |||
| rc.add(c); | |||
| } | |||
| /** | |||
| @@ -284,9 +334,9 @@ public class Concat extends Task { | |||
| } | |||
| /** | |||
| * set the output writer, this is to allow | |||
| * concat to be used as a nested element | |||
| * @param outputWriter the output writer | |||
| * Set the output writer. This is to allow | |||
| * concat to be used as a nested element. | |||
| * @param outputWriter the output writer. | |||
| * @since Ant 1.6 | |||
| */ | |||
| public void setWriter(Writer outputWriter) { | |||
| @@ -294,23 +344,20 @@ public class Concat extends Task { | |||
| } | |||
| /** | |||
| * set the binary attribute. | |||
| * if true, concat will concatenate the files | |||
| * byte for byte. This mode does not allow | |||
| * any filtering, or other modifications | |||
| * to the input streams. | |||
| * The default value is false. | |||
| * @since ant 1.6.2 | |||
| * @param binary if true, enable binary mode | |||
| * Set the binary attribute. If true, concat will concatenate the files | |||
| * byte for byte. This mode does not allow any filtering or other | |||
| * modifications to the input streams. The default value is false. | |||
| * @since Ant 1.6.2 | |||
| * @param binary if true, enable binary mode. | |||
| */ | |||
| public void setBinary(boolean binary) { | |||
| this.binary = binary; | |||
| } | |||
| /** | |||
| * This method checks the attributes and performs the concatenation. | |||
| * Validate configuration options. | |||
| */ | |||
| private void checkAndExecute() { | |||
| private ResourceCollection validate() { | |||
| // treat empty nested text as no text | |||
| sanitizeText(); | |||
| @@ -319,9 +366,8 @@ public class Concat extends Task { | |||
| if (binary) { | |||
| if (destinationFile == null) { | |||
| throw new BuildException( | |||
| "DestFile attribute is required for binary concatenation"); | |||
| "destfile attribute is required for binary concatenation"); | |||
| } | |||
| if (textBuffer != null) { | |||
| throw new BuildException( | |||
| "Nested text is incompatible with binary concatenation"); | |||
| @@ -344,187 +390,117 @@ public class Concat extends Task { | |||
| "Nested header or footer is incompatible with binary concatenation"); | |||
| } | |||
| } | |||
| if (destinationFile != null && outputWriter != null) { | |||
| throw new BuildException( | |||
| "Cannot specify both a destination file and an output writer"); | |||
| } | |||
| // Sanity check our inputs. | |||
| if (sources.size() == 0 && textBuffer == null) { | |||
| if (rc == null && textBuffer == null) { | |||
| // Nothing to concatenate! | |||
| throw new BuildException( | |||
| "At least one file must be provided, or some text."); | |||
| "At least one resource must be provided, or some text."); | |||
| } | |||
| // If using filesets, disallow inline text. This is similar to | |||
| // using GNU 'cat' with file arguments -- stdin is simply | |||
| // ignored. | |||
| if (sources.size() > 0 && textBuffer != null) { | |||
| throw new BuildException( | |||
| "Cannot include inline text when using filesets."); | |||
| } | |||
| // Iterate thru the sources - paths, filesets and filelists | |||
| for (Enumeration e = sources.elements(); e.hasMoreElements();) { | |||
| Object o = e.nextElement(); | |||
| if (o instanceof Path) { | |||
| Path path = (Path) o; | |||
| checkAddFiles(null, path.list()); | |||
| } else if (o instanceof FileSet) { | |||
| FileSet fileSet = (FileSet) o; | |||
| DirectoryScanner scanner = | |||
| fileSet.getDirectoryScanner(getProject()); | |||
| checkAddFiles(fileSet.getDir(getProject()), | |||
| scanner.getIncludedFiles()); | |||
| } else if (o instanceof FileList) { | |||
| FileList fileList = (FileList) o; | |||
| checkAddFiles(fileList.getDir(getProject()), | |||
| fileList.getFiles(getProject())); | |||
| } | |||
| } | |||
| // check if the files are outofdate | |||
| if (destinationFile != null && !forceOverwrite | |||
| && (sourceFiles.size() > 0) && destinationFile.exists()) { | |||
| boolean outofdate = false; | |||
| for (int i = 0; i < sourceFiles.size(); ++i) { | |||
| File file = (File) sourceFiles.elementAt(i); | |||
| if (file.lastModified() > destinationFile.lastModified()) { | |||
| outofdate = true; | |||
| break; | |||
| if (rc != null) { | |||
| // If using resources, disallow inline text. This is similar to | |||
| // using GNU 'cat' with file arguments -- stdin is simply | |||
| // ignored. | |||
| if (textBuffer != null) { | |||
| throw new BuildException( | |||
| "Cannot include inline text when using resources."); | |||
| } | |||
| Restrict noexistRc = new Restrict(); | |||
| noexistRc.add(NOT_EXISTS); | |||
| noexistRc.add(rc); | |||
| for (Iterator i = noexistRc.iterator(); i.hasNext();) { | |||
| log(i.next() + " does not exist.", Project.MSG_ERR); | |||
| } | |||
| if (destinationFile != null) { | |||
| for (Iterator i = rc.iterator(); i.hasNext();) { | |||
| Object o = i.next(); | |||
| if (o instanceof FileResource) { | |||
| File f = ((FileResource) o).getFile(); | |||
| if (FILE_UTILS.fileNameEquals(f, destinationFile)) { | |||
| throw new BuildException("Input file \"" | |||
| + f + "\" is the same as the output file."); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| Restrict existRc = new Restrict(); | |||
| existRc.add(EXISTS); | |||
| existRc.add(rc); | |||
| boolean outofdate = destinationFile == null || forceOverwrite; | |||
| if (!outofdate) { | |||
| for (Iterator i = existRc.iterator(); !outofdate && i.hasNext();) { | |||
| Resource r = (Resource) i.next(); | |||
| } | |||
| } | |||
| if (!outofdate) { | |||
| log(destinationFile + " is up-to-date.", Project.MSG_VERBOSE); | |||
| return; // no need to do anything | |||
| return null; // no need to do anything | |||
| } | |||
| } | |||
| // Do nothing if all the sources are not present | |||
| // And textBuffer is null | |||
| if (textBuffer == null && sourceFiles.size() == 0 | |||
| && header == null && footer == null) { | |||
| log("No existing files and no nested text, doing nothing", | |||
| Project.MSG_INFO); | |||
| return; | |||
| } | |||
| if (binary) { | |||
| binaryCat(); | |||
| return existRc; | |||
| } else { | |||
| cat(); | |||
| StringResource s = new StringResource(); | |||
| s.setProject(getProject()); | |||
| s.setValue(textBuffer.toString()); | |||
| return s; | |||
| } | |||
| } | |||
| /** | |||
| * execute the concat task. | |||
| * Execute the concat task. | |||
| */ | |||
| public void execute() { | |||
| try { | |||
| checkAndExecute(); | |||
| } finally { | |||
| resetTask(); | |||
| ResourceCollection c = validate(); | |||
| if (c == null) { | |||
| return; | |||
| } | |||
| } | |||
| /** | |||
| * Reset state to default. | |||
| */ | |||
| public void reset() { | |||
| append = false; | |||
| forceOverwrite = true; | |||
| destinationFile = null; | |||
| encoding = null; | |||
| outputEncoding = null; | |||
| fixLastLine = false; | |||
| sources.removeAllElements(); | |||
| sourceFiles.removeAllElements(); | |||
| filterChains = null; | |||
| footer = null; | |||
| header = null; | |||
| } | |||
| /** | |||
| * reset the used variables to allow the same task | |||
| * instance to be used again. | |||
| */ | |||
| private void resetTask() { | |||
| sourceFiles.clear(); | |||
| } | |||
| private void checkAddFiles(File base, String[] filenames) { | |||
| for (int i = 0; i < filenames.length; ++i) { | |||
| File file = new File(base, filenames[i]); | |||
| if (!file.exists()) { | |||
| log("File " + file + " does not exist.", Project.MSG_ERR); | |||
| continue; | |||
| } | |||
| if (destinationFile != null | |||
| && FILE_UTILS.fileNameEquals(destinationFile, file)) { | |||
| throw new BuildException("Input file \"" | |||
| + file + "\" " | |||
| + "is the same as the output file."); | |||
| } | |||
| sourceFiles.addElement(file); | |||
| // Do nothing if no resources (including nested text) | |||
| if (c.size() < 1 && header == null && footer == null) { | |||
| log("No existing resources and no nested text, doing nothing", | |||
| Project.MSG_INFO); | |||
| return; | |||
| } | |||
| if (binary) { | |||
| binaryCat(c); | |||
| } else { | |||
| cat(c); | |||
| } | |||
| } | |||
| /** perform the binary concatenation */ | |||
| private void binaryCat() { | |||
| log("Binary concatenation of " + sourceFiles.size() | |||
| + " files to " + destinationFile); | |||
| private void binaryCat(ResourceCollection c) { | |||
| log("Binary concatenation of " + c.size() | |||
| + " resources to " + destinationFile); | |||
| FileOutputStream out = null; | |||
| FileInputStream in = null; | |||
| InputStream in = null; | |||
| byte[] buffer = new byte[BUFFER_SIZE]; | |||
| try { | |||
| try { | |||
| out = new FileOutputStream(destinationFile); | |||
| } catch (Exception t) { | |||
| throw new BuildException( | |||
| "Unable to open " + destinationFile | |||
| + " for writing", t); | |||
| throw new BuildException("Unable to open " | |||
| + destinationFile + " for writing", t); | |||
| } | |||
| for (Iterator i = sourceFiles.iterator(); i.hasNext();) { | |||
| File sourceFile = (File) i.next(); | |||
| try { | |||
| in = new FileInputStream(sourceFile); | |||
| } catch (Exception t) { | |||
| throw new BuildException( | |||
| "Unable to open input file " + sourceFile, | |||
| t); | |||
| } | |||
| int count = 0; | |||
| do { | |||
| try { | |||
| count = in.read(buffer, 0, buffer.length); | |||
| } catch (Exception t) { | |||
| throw new BuildException( | |||
| "Unable to read from " + sourceFile, t); | |||
| } | |||
| try { | |||
| if (count > 0) { | |||
| out.write(buffer, 0, count); | |||
| } | |||
| } catch (Exception t) { | |||
| throw new BuildException( | |||
| "Unable to write to " + destinationFile, t); | |||
| } | |||
| } while (count > 0); | |||
| try { | |||
| in = new ConcatResourceInputStream(c); | |||
| ((ConcatResourceInputStream) in).setManagingComponent(this); | |||
| } catch (IOException e) { | |||
| throw new BuildException(e); | |||
| } | |||
| Thread t = new Thread(new StreamPumper(in, out)); | |||
| t.start(); | |||
| try { | |||
| t.join(); | |||
| } catch (InterruptedException e) { | |||
| try { | |||
| in.close(); | |||
| } catch (Exception t) { | |||
| throw new BuildException( | |||
| "Unable to close " + sourceFile, t); | |||
| t.join(); | |||
| } catch (InterruptedException ee) { | |||
| } | |||
| in = null; | |||
| } | |||
| } finally { | |||
| FileUtils.close(in); | |||
| if (out != null) { | |||
| try { | |||
| out.close(); | |||
| @@ -537,13 +513,11 @@ public class Concat extends Task { | |||
| } | |||
| /** perform the concatenation */ | |||
| private void cat() { | |||
| private void cat(ResourceCollection c) { | |||
| OutputStream os = null; | |||
| Reader reader = null; | |||
| char[] buffer = new char[BUFFER_SIZE]; | |||
| char[] buffer = new char[BUFFER_SIZE]; | |||
| try { | |||
| PrintWriter writer = null; | |||
| if (outputWriter != null) { | |||
| @@ -558,11 +532,9 @@ public class Concat extends Task { | |||
| if (!parent.exists()) { | |||
| parent.mkdirs(); | |||
| } | |||
| os = new FileOutputStream(destinationFile.getAbsolutePath(), | |||
| append); | |||
| } | |||
| if (outputEncoding == null) { | |||
| writer = new PrintWriter( | |||
| new BufferedWriter( | |||
| @@ -573,7 +545,6 @@ public class Concat extends Task { | |||
| new OutputStreamWriter(os, outputEncoding))); | |||
| } | |||
| } | |||
| if (header != null) { | |||
| if (header.getFiltering()) { | |||
| concatenate( | |||
| @@ -582,16 +553,9 @@ public class Concat extends Task { | |||
| writer.print(header.getValue()); | |||
| } | |||
| } | |||
| if (textBuffer != null) { | |||
| reader = new StringReader( | |||
| getProject().replaceProperties(textBuffer.substring(0))); | |||
| } else { | |||
| reader = new MultiReader(); | |||
| if (c.size() > 0) { | |||
| concatenate(buffer, writer, new MultiReader(c)); | |||
| } | |||
| concatenate(buffer, writer, reader); | |||
| if (footer != null) { | |||
| if (footer.getFiltering()) { | |||
| concatenate( | |||
| @@ -600,34 +564,18 @@ public class Concat extends Task { | |||
| writer.print(footer.getValue()); | |||
| } | |||
| } | |||
| writer.flush(); | |||
| if (os != null) { | |||
| os.flush(); | |||
| } | |||
| } catch (IOException ioex) { | |||
| throw new BuildException("Error while concatenating: " | |||
| + ioex.getMessage(), ioex); | |||
| } finally { | |||
| if (reader != null) { | |||
| try { | |||
| reader.close(); | |||
| } catch (IOException ignore) { | |||
| // ignore | |||
| } | |||
| } | |||
| if (os != null) { | |||
| try { | |||
| os.close(); | |||
| } catch (IOException ignore) { | |||
| // ignore | |||
| } | |||
| } | |||
| FILE_UTILS.close(os); | |||
| } | |||
| } | |||
| /** Concatenate a single reader to the writer using buffer */ | |||
| private void concatenate(char[] buffer, Writer writer, Reader in) | |||
| throws IOException { | |||
| @@ -639,7 +587,6 @@ public class Concat extends Task { | |||
| helper.setProject(getProject()); | |||
| in = new BufferedReader(helper.getAssembledReader()); | |||
| } | |||
| while (true) { | |||
| int nRead = in.read(buffer, 0, buffer.length); | |||
| if (nRead == -1) { | |||
| @@ -647,7 +594,6 @@ public class Concat extends Task { | |||
| } | |||
| writer.write(buffer, 0, nRead); | |||
| } | |||
| writer.flush(); | |||
| } | |||
| @@ -796,34 +742,34 @@ public class Concat extends Task { | |||
| * a single stream. | |||
| */ | |||
| private class MultiReader extends Reader { | |||
| private int pos = 0; | |||
| private Reader reader = null; | |||
| private int lastPos = 0; | |||
| private char[] lastChars = new char[eolString.length()]; | |||
| private boolean needAddSeparator = false; | |||
| private Iterator i; | |||
| private MultiReader(ResourceCollection c) { | |||
| i = c.iterator(); | |||
| } | |||
| private Reader getReader() throws IOException { | |||
| if (reader == null) { | |||
| log("Concating file " + sourceFiles.elementAt(pos), | |||
| Project.MSG_VERBOSE); | |||
| if (encoding == null) { | |||
| reader = new BufferedReader( | |||
| new FileReader((File) sourceFiles.elementAt(pos))); | |||
| } else { | |||
| // invoke the zoo of io readers | |||
| reader = new BufferedReader( | |||
| new InputStreamReader( | |||
| new FileInputStream( | |||
| (File) sourceFiles.elementAt(pos)), | |||
| encoding)); | |||
| } | |||
| for (int i = 0; i < lastChars.length; ++i) { | |||
| lastChars[i] = 0; | |||
| } | |||
| if (reader == null && i.hasNext()) { | |||
| Resource r = (Resource) i.next(); | |||
| log("Concating " + r.toLongString(), Project.MSG_VERBOSE); | |||
| InputStream is = r.getInputStream(); | |||
| reader = new BufferedReader(encoding == null | |||
| ? new InputStreamReader(is) | |||
| : new InputStreamReader(is, encoding)); | |||
| Arrays.fill(lastChars, (char) 0); | |||
| } | |||
| return reader; | |||
| } | |||
| private void nextReader() throws IOException { | |||
| close(); | |||
| reader = null; | |||
| } | |||
| /** | |||
| * Read a character from the current reader object. Advance | |||
| * to the next if the reader is finished. | |||
| @@ -840,12 +786,10 @@ public class Concat extends Task { | |||
| } | |||
| return ret; | |||
| } | |||
| while (pos < sourceFiles.size()) { | |||
| while (getReader() != null) { | |||
| int ch = getReader().read(); | |||
| if (ch == -1) { | |||
| reader.close(); | |||
| reader = null; | |||
| nextReader(); | |||
| if (fixLastLine && isMissingEndOfLine()) { | |||
| needAddSeparator = true; | |||
| lastPos = 0; | |||
| @@ -854,7 +798,6 @@ public class Concat extends Task { | |||
| addLastChar((char) ch); | |||
| return ch; | |||
| } | |||
| pos++; | |||
| } | |||
| return -1; | |||
| } | |||
| @@ -871,13 +814,12 @@ public class Concat extends Task { | |||
| throws IOException { | |||
| int amountRead = 0; | |||
| while (pos < sourceFiles.size() || (needAddSeparator)) { | |||
| while (getReader() != null || needAddSeparator) { | |||
| if (needAddSeparator) { | |||
| cbuf[off] = eolString.charAt(lastPos++); | |||
| if (lastPos >= eolString.length()) { | |||
| lastPos = 0; | |||
| needAddSeparator = false; | |||
| pos++; | |||
| } | |||
| len--; | |||
| off++; | |||
| @@ -889,13 +831,10 @@ public class Concat extends Task { | |||
| } | |||
| int nRead = getReader().read(cbuf, off, len); | |||
| if (nRead == -1 || nRead == 0) { | |||
| reader.close(); | |||
| reader = null; | |||
| nextReader(); | |||
| if (fixLastLine && isMissingEndOfLine()) { | |||
| needAddSeparator = true; | |||
| lastPos = 0; | |||
| } else { | |||
| pos++; | |||
| } | |||
| } else { | |||
| if (fixLastLine) { | |||
| @@ -931,6 +870,7 @@ public class Concat extends Task { | |||
| reader.close(); | |||
| } | |||
| } | |||
| /** | |||
| * if checking for end of line at end of file | |||
| * add a character to the lastchars buffer | |||
| @@ -21,18 +21,21 @@ import java.io.File; | |||
| import java.io.PrintStream; | |||
| import java.io.OutputStream; | |||
| import java.io.ByteArrayOutputStream; | |||
| import java.util.Vector; | |||
| import java.util.Iterator; | |||
| import org.apache.tools.ant.Task; | |||
| import org.apache.tools.ant.Project; | |||
| import org.apache.tools.ant.BuildException; | |||
| import org.apache.tools.ant.DirectoryScanner; | |||
| import org.apache.tools.ant.taskdefs.condition.Condition; | |||
| import org.apache.tools.ant.types.FileSet; | |||
| import org.apache.tools.ant.types.Resource; | |||
| import org.apache.tools.ant.types.Comparison; | |||
| import org.apache.tools.ant.types.ResourceCollection; | |||
| import org.apache.tools.ant.types.EnumeratedAttribute; | |||
| import org.apache.tools.ant.types.resources.Resources; | |||
| import org.apache.tools.ant.types.resources.FileResource; | |||
| import org.apache.tools.ant.util.FileUtils; | |||
| import org.apache.tools.ant.util.PropertyOutputStream; | |||
| /** | |||
| * Gets lengths: of files/resources, byte size; of strings, length (optionally trimmed). | |||
| @@ -52,9 +55,9 @@ public class Length extends Task implements Condition { | |||
| private String string; | |||
| private Boolean trim; | |||
| private String mode = ALL; | |||
| private When when = When.EQUAL; | |||
| private Comparison when = Comparison.EQUAL; | |||
| private Long length; | |||
| private Vector filesets; | |||
| private Resources resources; | |||
| /** | |||
| * The property in which the length will be stored. | |||
| @@ -69,9 +72,7 @@ public class Length extends Task implements Condition { | |||
| * @param file the <code>File</code> whose length to retrieve. | |||
| */ | |||
| public synchronized void setFile(File file) { | |||
| FileSet fs = new FileSet(); | |||
| fs.setFile(file); | |||
| add(fs); | |||
| add(new FileResource(file)); | |||
| } | |||
| /** | |||
| @@ -79,11 +80,20 @@ public class Length extends Task implements Condition { | |||
| * @param fs the <code>FileSet</code> to add. | |||
| */ | |||
| public synchronized void add(FileSet fs) { | |||
| if (fs == null) { | |||
| add((ResourceCollection) fs); | |||
| } | |||
| /** | |||
| * Add a ResourceCollection. | |||
| * @param c the <code>ResourceCollection</code> to add. | |||
| * @since Ant 1.7 | |||
| */ | |||
| public synchronized void add(ResourceCollection c) { | |||
| if (c == null) { | |||
| return; | |||
| } | |||
| filesets = (filesets == null) ? new Vector() : filesets; | |||
| filesets.add(fs); | |||
| resources = (resources == null) ? new Resources() : resources; | |||
| resources.add(c); | |||
| } | |||
| /** | |||
| @@ -95,12 +105,22 @@ public class Length extends Task implements Condition { | |||
| } | |||
| /** | |||
| * Set the comparison criteria for use as a Condition: | |||
| * "equal", "greater", "less". Default is "equal". | |||
| * Set the comparison for use as a Condition. | |||
| * @param w EnumeratedAttribute When. | |||
| * @see org.apache.tools.ant.types.Comparison | |||
| */ | |||
| public synchronized void setWhen(When w) { | |||
| when = w; | |||
| setWhen((Comparison) w); | |||
| } | |||
| /** | |||
| * Set the comparison for use as a Condition. | |||
| * @param c Comparison. | |||
| * @see org.apache.tools.ant.types.Comparison | |||
| * @since Ant 1.7 | |||
| */ | |||
| public synchronized void setWhen(Comparison c) { | |||
| when = c; | |||
| } | |||
| /** | |||
| @@ -142,7 +162,7 @@ public class Length extends Task implements Condition { | |||
| public void execute() { | |||
| validate(); | |||
| PrintStream ps = new PrintStream((property != null) | |||
| ? (OutputStream) new PropertyOutputStream() | |||
| ? (OutputStream) new PropertyOutputStream(getProject(), property) | |||
| : (OutputStream) new LogOutputStream(this, Project.MSG_INFO)); | |||
| if (STRING.equals(mode)) { | |||
| @@ -173,27 +193,23 @@ public class Length extends Task implements Condition { | |||
| handleResources(h); | |||
| ell = new Long(h.getLength()); | |||
| } | |||
| int w = when.getIndex(); | |||
| int comp = ell.compareTo(length); | |||
| return (w == 0 && comp == 0) | |||
| || (w == 1 && comp > 0) | |||
| || (w == 2 && comp < 0); | |||
| return when.evaluate(ell.compareTo(length)); | |||
| } | |||
| private void validate() { | |||
| if (string != null) { | |||
| if (filesets != null && filesets.size() > 0) { | |||
| if (resources != null) { | |||
| throw new BuildException("the string length function" | |||
| + " is incompatible with the file length function"); | |||
| + " is incompatible with the file/resource length function"); | |||
| } | |||
| if (!(STRING.equals(mode))) { | |||
| throw new BuildException("the mode attribute is for use" | |||
| + " with the file/resource length function"); | |||
| } | |||
| } else if (filesets != null) { | |||
| } else if (resources != null) { | |||
| if (!(EACH.equals(mode) || ALL.equals(mode))) { | |||
| throw new BuildException("invalid mode setting for" | |||
| + " file length function: \"" + mode + "\""); | |||
| + " file/resource length function: \"" + mode + "\""); | |||
| } else if (trim != null) { | |||
| throw new BuildException("the trim attribute is" | |||
| + " for use with the string length function only"); | |||
| @@ -201,30 +217,20 @@ public class Length extends Task implements Condition { | |||
| } else { | |||
| throw new BuildException("you must set either the string attribute" | |||
| + " or specify one or more files using the file attribute or" | |||
| + " nested filesets"); | |||
| + " nested resource collections"); | |||
| } | |||
| } | |||
| private void handleResources(Handler h) { | |||
| for (Iterator i = filesets.iterator(); i.hasNext();) { | |||
| FileSet fs = (FileSet) i.next(); | |||
| DirectoryScanner ds = fs.getDirectoryScanner(getProject()); | |||
| String[] f = ds.getIncludedFiles(); | |||
| for (int j = 0; j < f.length; j++) { | |||
| Resource r = ds.getResource(f[j]); | |||
| if (!r.isExists()) { | |||
| log(r.getName() + " does not exist", Project.MSG_ERR); | |||
| } else if (r.isDirectory()) { | |||
| log(r.getName() + " is a directory; length unspecified", | |||
| Project.MSG_ERR); | |||
| } else { | |||
| //force a full path: | |||
| File basedir = ds.getBasedir(); | |||
| String s = FileUtils.getFileUtils().resolveFile( | |||
| basedir, r.getName()).getAbsolutePath(); | |||
| h.handle(new Resource(s, true, | |||
| r.getLastModified(), false, r.getSize())); | |||
| } | |||
| for (Iterator i = resources.iterator(); i.hasNext();) { | |||
| Resource r = (Resource) i.next(); | |||
| if (!r.isExists()) { | |||
| log(r + " does not exist", Project.MSG_ERR); | |||
| } else if (r.isDirectory()) { | |||
| log(r + " is a directory; length unspecified", | |||
| Project.MSG_ERR); | |||
| } else { | |||
| h.handle(r); | |||
| } | |||
| } | |||
| h.complete(); | |||
| @@ -251,27 +257,8 @@ public class Length extends Task implements Condition { | |||
| /** | |||
| * EnumeratedAttribute for the when attribute. | |||
| */ | |||
| public static class When extends EnumeratedAttribute { | |||
| private static final String[] VALUES | |||
| = new String[] {"equal", "greater", "less"}; | |||
| private static final When EQUAL = new When("equal"); | |||
| public When() { | |||
| } | |||
| public When(String value) { | |||
| setValue(value); | |||
| } | |||
| public String[] getValues() { | |||
| return VALUES; | |||
| } | |||
| } | |||
| private class PropertyOutputStream extends ByteArrayOutputStream { | |||
| public void close() { | |||
| getProject().setNewProperty( | |||
| property, new String(toByteArray()).trim()); | |||
| } | |||
| public static class When extends Comparison { | |||
| //extend Comparison; retain for BC only | |||
| } | |||
| private abstract class Handler { | |||
| @@ -292,7 +279,7 @@ public class Length extends Task implements Condition { | |||
| super(ps); | |||
| } | |||
| protected void handle(Resource r) { | |||
| ps.print(r.getName()); | |||
| ps.print(r.toString()); | |||
| ps.print(" : "); | |||
| //when writing to the log, we'll see what's happening: | |||
| long size = r.getSize(); | |||
| @@ -312,7 +299,7 @@ public class Length extends Task implements Condition { | |||
| protected synchronized void handle(Resource r) { | |||
| long size = r.getSize(); | |||
| if (size == Resource.UNKNOWN_SIZE) { | |||
| log("Size unknown for " + r.getName(), Project.MSG_WARN); | |||
| log("Size unknown for " + r.toString(), Project.MSG_WARN); | |||
| } else { | |||
| accum += size; | |||
| } | |||
| @@ -17,21 +17,23 @@ | |||
| package org.apache.tools.ant.taskdefs; | |||
| import java.io.File; | |||
| import java.util.StringTokenizer; | |||
| import java.util.Vector; | |||
| import java.util.List; | |||
| import java.util.Vector; | |||
| import java.util.ArrayList; | |||
| import org.apache.tools.ant.BuildException; | |||
| import org.apache.tools.ant.Project; | |||
| import java.util.StringTokenizer; | |||
| import org.apache.tools.ant.Task; | |||
| import org.apache.tools.ant.Project; | |||
| import org.apache.tools.ant.BuildException; | |||
| import org.apache.tools.ant.taskdefs.condition.Os; | |||
| import org.apache.tools.ant.types.Path; | |||
| import org.apache.tools.ant.types.DirSet; | |||
| import org.apache.tools.ant.types.EnumeratedAttribute; | |||
| import org.apache.tools.ant.types.FileList; | |||
| import org.apache.tools.ant.types.Mapper; | |||
| import org.apache.tools.ant.types.FileSet; | |||
| import org.apache.tools.ant.types.Path; | |||
| import org.apache.tools.ant.types.FileList; | |||
| import org.apache.tools.ant.types.Reference; | |||
| import org.apache.tools.ant.types.Mapper; | |||
| import org.apache.tools.ant.types.ResourceCollection; | |||
| import org.apache.tools.ant.types.EnumeratedAttribute; | |||
| import org.apache.tools.ant.types.resources.Union; | |||
| import org.apache.tools.ant.util.FileNameMapper; | |||
| /** | |||
| @@ -43,11 +45,16 @@ import org.apache.tools.ant.util.FileNameMapper; | |||
| */ | |||
| public class PathConvert extends Task { | |||
| /** | |||
| * Set if we're running on windows | |||
| */ | |||
| private static boolean onWindows = Os.isFamily("dos"); | |||
| // Members | |||
| /** | |||
| * Path to be converted | |||
| */ | |||
| private Path path = null; | |||
| private Union path = null; | |||
| /** | |||
| * Reference to path/fileset to convert | |||
| */ | |||
| @@ -60,10 +67,6 @@ public class PathConvert extends Task { | |||
| * Set when targetOS is set to windows | |||
| */ | |||
| private boolean targetWindows = false; | |||
| /** | |||
| * Set if we're running on windows | |||
| */ | |||
| private boolean onWindows = false; | |||
| /** | |||
| * Set if we should create a new property even if the result is empty | |||
| */ | |||
| @@ -92,7 +95,6 @@ public class PathConvert extends Task { | |||
| * Construct a new instance of the PathConvert task. | |||
| */ | |||
| public PathConvert() { | |||
| onWindows = Os.isFamily("dos"); | |||
| } | |||
| /** | |||
| @@ -164,17 +166,36 @@ public class PathConvert extends Task { | |||
| } | |||
| /** | |||
| * Create a nested PATH element. | |||
| * Create a nested path element. | |||
| * @return a Path to be used by Ant reflection. | |||
| */ | |||
| public Path createPath() { | |||
| if (isReference()) { | |||
| throw noChildrenAllowed(); | |||
| } | |||
| Path result = new Path(getProject()); | |||
| add(result); | |||
| return result; | |||
| } | |||
| /** | |||
| * Add an arbitrary ResourceCollection. | |||
| * @param rc the ResourceCollection to add. | |||
| * @since Ant 1.7 | |||
| */ | |||
| public void add(ResourceCollection rc) { | |||
| if (isReference()) { | |||
| throw noChildrenAllowed(); | |||
| } | |||
| getPath().add(rc); | |||
| } | |||
| private synchronized Union getPath() { | |||
| if (path == null) { | |||
| path = new Path(getProject()); | |||
| path = new Union(); | |||
| path.setProject(getProject()); | |||
| } | |||
| return path.createPath(); | |||
| return path; | |||
| } | |||
| /** | |||
| @@ -283,28 +304,19 @@ public class PathConvert extends Task { | |||
| * @throws BuildException if something is invalid. | |||
| */ | |||
| public void execute() throws BuildException { | |||
| Path savedPath = path; | |||
| Union savedPath = path; | |||
| String savedPathSep = pathSep; // may be altered in validateSetup | |||
| String savedDirSep = dirSep; // may be altered in validateSetup | |||
| try { | |||
| // If we are a reference, create a Path from the reference | |||
| if (isReference()) { | |||
| path = new Path(getProject()).createPath(); | |||
| Object obj = refid.getReferencedObject(getProject()); | |||
| if (obj instanceof Path) { | |||
| path.setRefid(refid); | |||
| } else if (obj instanceof FileSet) { | |||
| path.addFileset((FileSet) obj); | |||
| } else if (obj instanceof DirSet) { | |||
| path.addDirset((DirSet) obj); | |||
| } else if (obj instanceof FileList) { | |||
| path.addFilelist((FileList) obj); | |||
| } else { | |||
| throw new BuildException("'refid' does not refer to a " | |||
| + "path, fileset, dirset, or filelist."); | |||
| Object o = refid.getReferencedObject(getProject()); | |||
| if (!(o instanceof ResourceCollection)) { | |||
| throw new BuildException("refid '" + refid.getRefId() | |||
| + "' does not refer to a resource collection."); | |||
| } | |||
| getPath().add((ResourceCollection) o); | |||
| } | |||
| validateSetup(); // validate our setup | |||
| @@ -355,9 +367,13 @@ public class PathConvert extends Task { | |||
| // unless setonempty == false | |||
| if (setonempty || rslt.length() > 0) { | |||
| String value = rslt.toString(); | |||
| log("Set property " + property + " = " + value, | |||
| Project.MSG_VERBOSE); | |||
| getProject().setNewProperty(property, value); | |||
| if (property == null) { | |||
| log(value); | |||
| } else { | |||
| log("Set property " + property + " = " + value, | |||
| Project.MSG_VERBOSE); | |||
| getProject().setNewProperty(property, value); | |||
| } | |||
| } | |||
| } finally { | |||
| path = savedPath; | |||
| @@ -423,7 +439,6 @@ public class PathConvert extends Task { | |||
| addMapper(m); | |||
| } | |||
| /** | |||
| * Validate that all our parameters have been properly initialized. | |||
| * | |||
| @@ -434,9 +449,6 @@ public class PathConvert extends Task { | |||
| if (path == null) { | |||
| throw new BuildException("You must specify a path to convert"); | |||
| } | |||
| if (property == null) { | |||
| throw new BuildException("You must specify a property"); | |||
| } | |||
| // Determine the separator strings. The dirsep and pathsep attributes | |||
| // override the targetOS settings. | |||
| String dsep = File.separator; | |||
| @@ -464,7 +476,7 @@ public class PathConvert extends Task { | |||
| * @return BuildException. | |||
| */ | |||
| private BuildException noChildrenAllowed() { | |||
| return new BuildException("You must not specify nested <path> " | |||
| return new BuildException("You must not specify nested " | |||
| + "elements when using the refid attribute."); | |||
| } | |||
| @@ -0,0 +1,124 @@ | |||
| /* | |||
| * Copyright 2005 The Apache Software Foundation | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * | |||
| */ | |||
| package org.apache.tools.ant.taskdefs; | |||
| import org.apache.tools.ant.Task; | |||
| import org.apache.tools.ant.Project; | |||
| import org.apache.tools.ant.BuildException; | |||
| import org.apache.tools.ant.taskdefs.condition.Condition; | |||
| import org.apache.tools.ant.types.Reference; | |||
| import org.apache.tools.ant.types.Comparison; | |||
| import org.apache.tools.ant.types.ResourceCollection; | |||
| /** | |||
| * Count resources from a ResourceCollection, storing to a property or | |||
| * writing to the log. Can also be used as a Condition. | |||
| * @since Ant 1.7 | |||
| */ | |||
| public class ResourceCount extends Task implements Condition { | |||
| private static final String ONE_NESTED_MESSAGE | |||
| = "ResourceCount can count resources from exactly one nested ResourceCollection."; | |||
| private static final String COUNT_REQUIRED | |||
| = "Use of the ResourceCount condition requires that the count attribute be set."; | |||
| private ResourceCollection rc; | |||
| private Comparison when = Comparison.EQUAL; | |||
| private Integer count; | |||
| private String property; | |||
| /** | |||
| * Add the ResourceCollection to count. | |||
| * @param r the ResourceCollection to count. | |||
| * @throws BuildException if already set. | |||
| */ | |||
| public void add(ResourceCollection r) { | |||
| if (rc != null) { | |||
| throw new BuildException(ONE_NESTED_MESSAGE); | |||
| } | |||
| rc = r; | |||
| } | |||
| /** | |||
| * Set the ResourceCollection reference. | |||
| * @param r the Reference. | |||
| */ | |||
| public void setRefid(Reference r) { | |||
| Object o = r.getReferencedObject(); | |||
| if (!(o instanceof ResourceCollection)) { | |||
| throw new BuildException(r.getRefId() | |||
| + " doesn\'t denote a ResourceCollection"); | |||
| } | |||
| add((ResourceCollection) o); | |||
| } | |||
| /** | |||
| * Execute as a Task. | |||
| */ | |||
| public void execute() { | |||
| if (rc == null) { | |||
| throw new BuildException(ONE_NESTED_MESSAGE); | |||
| } | |||
| if (property == null) { | |||
| log("resource count = " + rc.size()); | |||
| } else { | |||
| getProject().setNewProperty(property, Integer.toString(rc.size())); | |||
| } | |||
| } | |||
| /** | |||
| * Fulfill the condition contract. | |||
| * @return true if the specified ResourceCollection satisfies the set criteria. | |||
| * @throws BuildException if an error occurs. | |||
| */ | |||
| public boolean eval() { | |||
| if (rc == null) { | |||
| throw new BuildException(ONE_NESTED_MESSAGE); | |||
| } | |||
| if (count == null) { | |||
| throw new BuildException(COUNT_REQUIRED); | |||
| } | |||
| return when.evaluate(new Integer(rc.size()).compareTo(count)); | |||
| } | |||
| /** | |||
| * Set the target count number for use as a Condition. | |||
| * @param c number of Resources as int. | |||
| */ | |||
| public void setCount(int c) { | |||
| count = new Integer(c); | |||
| } | |||
| /** | |||
| * Set the comparison for use as a Condition. | |||
| * @param w EnumeratedAttribute When. | |||
| * @see org.apache.tools.ant.types.Comparison | |||
| */ | |||
| public void setWhen(Comparison c) { | |||
| when = c; | |||
| } | |||
| /** | |||
| * Set the name of the property to set in task mode. | |||
| * @param p the property name to set. | |||
| */ | |||
| public void setProperty(String p) { | |||
| property = p; | |||
| } | |||
| } | |||
| @@ -207,6 +207,7 @@ ildasm=org.apache.tools.ant.taskdefs.optional.dotnet.Ildasm | |||
| apt=org.apache.tools.ant.taskdefs.Apt | |||
| schemavalidate=org.apache.tools.ant.taskdefs.optional.SchemaValidate | |||
| verifyjar=org.apache.tools.ant.taskdefs.VerifyJar | |||
| resourcecount=org.apache.tools.ant.taskdefs.ResourceCount | |||
| # deprecated ant tasks (kept for back compatibility) | |||
| starteam=org.apache.tools.ant.taskdefs.optional.scm.AntStarTeamCheckOut | |||
| @@ -0,0 +1,93 @@ | |||
| /* | |||
| * Copyright 2005 The Apache Software Foundation | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * | |||
| */ | |||
| package org.apache.tools.ant.types; | |||
| import java.util.Arrays; | |||
| import org.apache.tools.ant.BuildException; | |||
| /** | |||
| * EnumeratedAttribute for generic comparisons. Accepts values | |||
| * "equal", "greater", "less", "ne" (not equal), "ge" (greater or equal), | |||
| * "le" (less or equal), "eq" (equal), "gt" (greater), "lt" (less). | |||
| * @since Ant 1.7 | |||
| */ | |||
| public class Comparison extends EnumeratedAttribute { | |||
| private static final String[] VALUES | |||
| = new String[] {"equal", "greater", "less", | |||
| "ne", "ge", "le", "eq", "gt", "lt"}; | |||
| /** Equal Comparison. */ | |||
| public static final Comparison EQUAL = new Comparison("equal"); | |||
| /** Not-Equal Comparison. */ | |||
| public static final Comparison NOT_EQUAL = new Comparison("ne"); | |||
| /** Greater Comparison. */ | |||
| public static final Comparison GREATER = new Comparison("greater"); | |||
| /** Less Comparison. */ | |||
| public static final Comparison LESS = new Comparison("less"); | |||
| /** Greater-or-Equal Comparison. */ | |||
| public static final Comparison GREATER_EQUAL = new Comparison("ge"); | |||
| /** Less-or-Equal Comparison. */ | |||
| public static final Comparison LESS_EQUAL = new Comparison("le"); | |||
| private static final int[] EQUAL_INDEX = {0, 4, 5, 6}; | |||
| private static final int[] LESS_INDEX = {2, 3, 5, 8}; | |||
| private static final int[] GREATER_INDEX = {1, 3, 4, 7}; | |||
| /** | |||
| * Default constructor. | |||
| */ | |||
| public Comparison() { | |||
| } | |||
| /** | |||
| * Construct a new Comparison with the specified value. | |||
| * @param value the EnumeratedAttribute value. | |||
| */ | |||
| public Comparison(String value) { | |||
| setValue(value); | |||
| } | |||
| /** | |||
| * Return the possible values. | |||
| * @return String[] of EnumeratedAttribute values. | |||
| */ | |||
| public String[] getValues() { | |||
| return VALUES; | |||
| } | |||
| /** | |||
| * Evaluate a comparison result as from Comparator.compare() or Comparable.compareTo(). | |||
| * @param comparisonResult the result to evaluate. | |||
| * @return true if the comparison result fell within the parameters of this Comparison. | |||
| */ | |||
| public boolean evaluate(int comparisonResult) { | |||
| if (getIndex() == -1) { | |||
| throw new BuildException("Comparison value not set."); | |||
| } | |||
| int[] i = comparisonResult < 0 ? LESS_INDEX | |||
| : comparisonResult > 0 ? GREATER_INDEX : EQUAL_INDEX; | |||
| return Arrays.binarySearch(i, getIndex()) >= 0; | |||
| } | |||
| } | |||
| @@ -17,13 +17,17 @@ | |||
| package org.apache.tools.ant.types; | |||
| import java.util.Iterator; | |||
| import org.apache.tools.ant.types.resources.FileResourceIterator; | |||
| /** | |||
| * Subclass as hint for supporting tasks that the included directories | |||
| * instead of files should be used. | |||
| * | |||
| * @since Ant 1.5 | |||
| */ | |||
| public class DirSet extends AbstractFileSet { | |||
| public class DirSet extends AbstractFileSet implements ResourceCollection { | |||
| /** | |||
| * Constructor for DirSet. | |||
| @@ -53,4 +57,38 @@ public class DirSet extends AbstractFileSet { | |||
| } | |||
| } | |||
| /** | |||
| * Fulfill the ResourceCollection contract. | |||
| * @return an Iterator of Resources. | |||
| * @since Ant 1.7 | |||
| */ | |||
| public Iterator iterator() { | |||
| if (isReference()) { | |||
| return ((DirSet) getRef(getProject())).iterator(); | |||
| } | |||
| return new FileResourceIterator(getDir(getProject()), | |||
| getDirectoryScanner(getProject()).getIncludedDirectories()); | |||
| } | |||
| /** | |||
| * Fulfill the ResourceCollection contract. | |||
| * @return number of elements as int. | |||
| * @since Ant 1.7 | |||
| */ | |||
| public int size() { | |||
| if (isReference()) { | |||
| return ((DirSet) getRef(getProject())).size(); | |||
| } | |||
| return getDirectoryScanner(getProject()).getIncludedDirsCount(); | |||
| } | |||
| /** | |||
| * Always returns true. | |||
| * @return true indicating that all elements will be FileResources. | |||
| * @since Ant 1.7 | |||
| */ | |||
| public boolean isFilesystemOnly() { | |||
| return true; | |||
| } | |||
| } | |||
| @@ -1,5 +1,5 @@ | |||
| /* | |||
| * Copyright 2001-2002,2004 The Apache Software Foundation | |||
| * Copyright 2001-2002,2004-2005 The Apache Software Foundation | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| @@ -21,8 +21,11 @@ import java.io.File; | |||
| import java.util.Stack; | |||
| import java.util.StringTokenizer; | |||
| import java.util.Vector; | |||
| import org.apache.tools.ant.BuildException; | |||
| import java.util.Iterator; | |||
| import org.apache.tools.ant.Project; | |||
| import org.apache.tools.ant.BuildException; | |||
| import org.apache.tools.ant.types.resources.FileResourceIterator; | |||
| /** | |||
| * FileList represents an explicitly named list of files. FileLists | |||
| @@ -31,7 +34,7 @@ import org.apache.tools.ant.Project; | |||
| * filter, only returning the name of a matched file if it currently | |||
| * exists in the file system. | |||
| */ | |||
| public class FileList extends DataType { | |||
| public class FileList extends DataType implements ResourceCollection { | |||
| private Vector filenames = new Vector(); | |||
| private File dir; | |||
| @@ -78,9 +81,7 @@ public class FileList extends DataType { | |||
| * @exception BuildException if an error occurs | |||
| */ | |||
| public void setDir(File dir) throws BuildException { | |||
| if (isReference()) { | |||
| throw tooManyAttributes(); | |||
| } | |||
| checkAttributesAllowed(); | |||
| this.dir = dir; | |||
| } | |||
| @@ -102,9 +103,7 @@ public class FileList extends DataType { | |||
| * by whitespace. | |||
| */ | |||
| public void setFiles(String filenames) { | |||
| if (isReference()) { | |||
| throw tooManyAttributes(); | |||
| } | |||
| checkAttributesAllowed(); | |||
| if (filenames != null && filenames.length() > 0) { | |||
| StringTokenizer tok = new StringTokenizer( | |||
| filenames, ", \t\n\r\f", false); | |||
| @@ -144,19 +143,7 @@ public class FileList extends DataType { | |||
| * @return the FileList represented by a referenced filelist. | |||
| */ | |||
| protected FileList getRef(Project p) { | |||
| if (!isChecked()) { | |||
| Stack stk = new Stack(); | |||
| stk.push(this); | |||
| dieOnCircularReference(stk, p); | |||
| } | |||
| Object o = getRefid().getReferencedObject(p); | |||
| if (!(o instanceof FileList)) { | |||
| String msg = getRefid().getRefId() + " doesn\'t denote a filelist"; | |||
| throw new BuildException(msg); | |||
| } else { | |||
| return (FileList) o; | |||
| } | |||
| return (FileList) getCheckedRef(p); | |||
| } | |||
| /** | |||
| @@ -194,4 +181,39 @@ public class FileList extends DataType { | |||
| } | |||
| filenames.addElement(name.getName()); | |||
| } | |||
| /** | |||
| * Fulfill the ResourceCollection contract. | |||
| * @return an Iterator of Resources. | |||
| * @since Ant 1.7 | |||
| */ | |||
| public Iterator iterator() { | |||
| if (isReference()) { | |||
| return ((FileList) getRef(getProject())).iterator(); | |||
| } | |||
| return new FileResourceIterator(dir, | |||
| (String[]) (filenames.toArray(new String[filenames.size()]))); | |||
| } | |||
| /** | |||
| * Fulfill the ResourceCollection contract. | |||
| * @return number of elements as int. | |||
| * @since Ant 1.7 | |||
| */ | |||
| public int size() { | |||
| if (isReference()) { | |||
| return ((FileList) getRef(getProject())).size(); | |||
| } | |||
| return filenames.size(); | |||
| } | |||
| /** | |||
| * Always returns true. | |||
| * @return true indicating that all elements will be FileResources. | |||
| * @since Ant 1.7 | |||
| */ | |||
| public boolean isFilesystemOnly() { | |||
| return true; | |||
| } | |||
| } | |||
| @@ -17,12 +17,16 @@ | |||
| package org.apache.tools.ant.types; | |||
| import java.util.Iterator; | |||
| import org.apache.tools.ant.types.resources.FileResourceIterator; | |||
| /** | |||
| * Moved out of MatchingTask to make it a standalone object that could | |||
| * be referenced (by scripts for example). | |||
| * | |||
| */ | |||
| public class FileSet extends AbstractFileSet { | |||
| public class FileSet extends AbstractFileSet implements ResourceCollection { | |||
| /** | |||
| * Constructor for FileSet. | |||
| @@ -52,4 +56,38 @@ public class FileSet extends AbstractFileSet { | |||
| } | |||
| } | |||
| /** | |||
| * Fulfill the ResourceCollection contract. | |||
| * @return an Iterator of Resources. | |||
| * @since Ant 1.7 | |||
| */ | |||
| public Iterator iterator() { | |||
| if (isReference()) { | |||
| return ((FileSet) getRef(getProject())).iterator(); | |||
| } | |||
| return new FileResourceIterator(getDir(getProject()), | |||
| getDirectoryScanner(getProject()).getIncludedFiles()); | |||
| } | |||
| /** | |||
| * Fulfill the ResourceCollection contract. | |||
| * @return number of elements as int. | |||
| * @since Ant 1.7 | |||
| */ | |||
| public int size() { | |||
| if (isReference()) { | |||
| return ((FileSet) getRef(getProject())).size(); | |||
| } | |||
| return getDirectoryScanner(getProject()).getIncludedFilesCount(); | |||
| } | |||
| /** | |||
| * Always returns true. | |||
| * @return true indicating that all elements will be FileResources. | |||
| * @since Ant 1.7 | |||
| */ | |||
| public boolean isFilesystemOnly() { | |||
| return true; | |||
| } | |||
| } | |||
| @@ -18,17 +18,22 @@ | |||
| package org.apache.tools.ant.types; | |||
| import java.io.File; | |||
| import java.util.Enumeration; | |||
| import java.util.Locale; | |||
| import java.util.Set; | |||
| import java.util.Stack; | |||
| import java.util.Locale; | |||
| import java.util.Vector; | |||
| import java.util.HashSet; | |||
| import java.util.Iterator; | |||
| import java.util.Collection; | |||
| import java.util.Enumeration; | |||
| import org.apache.tools.ant.BuildException; | |||
| import org.apache.tools.ant.PathTokenizer; | |||
| import org.apache.tools.ant.Project; | |||
| import org.apache.tools.ant.types.resources.Union; | |||
| import org.apache.tools.ant.types.resources.FileResourceIterator; | |||
| import org.apache.tools.ant.util.FileUtils; | |||
| import org.apache.tools.ant.util.JavaEnvUtils; | |||
| /** | |||
| * This object represents a path as used by CLASSPATH or PATH | |||
| * environment variable. | |||
| @@ -56,28 +61,25 @@ import org.apache.tools.ant.util.JavaEnvUtils; | |||
| * | |||
| */ | |||
| public class Path extends DataType implements Cloneable { | |||
| private Vector elements; | |||
| public class Path extends Union { | |||
| /** The system classspath as a Path object */ | |||
| /** The system classpath as a Path object */ | |||
| public static Path systemClasspath = | |||
| new Path(null, System.getProperty("java.class.path")); | |||
| /** | |||
| * The system bootclassspath as a Path object. | |||
| * The system bootclasspath as a Path object. | |||
| * | |||
| * @since Ant 1.6.2 | |||
| */ | |||
| public static Path systemBootClasspath = | |||
| new Path(null, System.getProperty("sun.boot.class.path")); | |||
| /** | |||
| * Helper class, holds the nested <code><pathelement></code> values. | |||
| */ | |||
| public class PathElement { | |||
| public class PathElement implements ResourceCollection { | |||
| private String[] parts; | |||
| /** | |||
| @@ -106,6 +108,19 @@ public class Path extends DataType implements Cloneable { | |||
| public String[] getParts() { | |||
| return parts; | |||
| } | |||
| public Iterator iterator() { | |||
| return new FileResourceIterator(null, parts); | |||
| } | |||
| public boolean isFilesystemOnly() { | |||
| return true; | |||
| } | |||
| public int size() { | |||
| return parts == null ? 0 : parts.length; | |||
| } | |||
| } | |||
| /** | |||
| @@ -125,7 +140,6 @@ public class Path extends DataType implements Cloneable { | |||
| */ | |||
| public Path(Project project) { | |||
| setProject(project); | |||
| elements = new Vector(); | |||
| } | |||
| /** | |||
| @@ -135,22 +149,17 @@ public class Path extends DataType implements Cloneable { | |||
| * @throws BuildException on error | |||
| */ | |||
| public void setLocation(File location) throws BuildException { | |||
| if (isReference()) { | |||
| throw tooManyAttributes(); | |||
| } | |||
| checkAttributesAllowed(); | |||
| createPathElement().setLocation(location); | |||
| } | |||
| /** | |||
| * Parses a path definition and creates single PathElements. | |||
| * @param path the <code>String</code> path definition. | |||
| * @throws BuildException on error | |||
| */ | |||
| public void setPath(String path) throws BuildException { | |||
| if (isReference()) { | |||
| throw tooManyAttributes(); | |||
| } | |||
| checkAttributesAllowed(); | |||
| createPathElement().setPath(path); | |||
| } | |||
| @@ -163,10 +172,9 @@ public class Path extends DataType implements Cloneable { | |||
| * @throws BuildException on error | |||
| */ | |||
| public void setRefid(Reference r) throws BuildException { | |||
| if (!elements.isEmpty()) { | |||
| if (!getResourceCollections().isEmpty()) { | |||
| throw tooManyAttributes(); | |||
| } | |||
| elements.addElement(r); | |||
| super.setRefid(r); | |||
| } | |||
| @@ -180,7 +188,7 @@ public class Path extends DataType implements Cloneable { | |||
| throw noChildrenAllowed(); | |||
| } | |||
| PathElement pe = new PathElement(); | |||
| elements.addElement(pe); | |||
| add(pe); | |||
| return pe; | |||
| } | |||
| @@ -190,11 +198,7 @@ public class Path extends DataType implements Cloneable { | |||
| * @throws BuildException on error | |||
| */ | |||
| public void addFileset(FileSet fs) throws BuildException { | |||
| if (isReference()) { | |||
| throw noChildrenAllowed(); | |||
| } | |||
| elements.addElement(fs); | |||
| setChecked(false); | |||
| add(fs); | |||
| } | |||
| /** | |||
| @@ -203,11 +207,7 @@ public class Path extends DataType implements Cloneable { | |||
| * @throws BuildException on error | |||
| */ | |||
| public void addFilelist(FileList fl) throws BuildException { | |||
| if (isReference()) { | |||
| throw noChildrenAllowed(); | |||
| } | |||
| elements.addElement(fl); | |||
| setChecked(false); | |||
| add(fl); | |||
| } | |||
| /** | |||
| @@ -216,11 +216,7 @@ public class Path extends DataType implements Cloneable { | |||
| * @throws BuildException on error | |||
| */ | |||
| public void addDirset(DirSet dset) throws BuildException { | |||
| if (isReference()) { | |||
| throw noChildrenAllowed(); | |||
| } | |||
| elements.addElement(dset); | |||
| setChecked(false); | |||
| add(dset); | |||
| } | |||
| /** | |||
| @@ -230,12 +226,7 @@ public class Path extends DataType implements Cloneable { | |||
| * @since Ant 1.6 | |||
| */ | |||
| public void add(Path path) throws BuildException { | |||
| if (isReference()) { | |||
| throw noChildrenAllowed(); | |||
| } | |||
| elements.addElement(path); | |||
| setChecked(false); | |||
| add((ResourceCollection) path); | |||
| } | |||
| /** | |||
| @@ -244,12 +235,8 @@ public class Path extends DataType implements Cloneable { | |||
| * @throws BuildException on error | |||
| */ | |||
| public Path createPath() throws BuildException { | |||
| if (isReference()) { | |||
| throw noChildrenAllowed(); | |||
| } | |||
| Path p = new Path(getProject()); | |||
| elements.addElement(p); | |||
| setChecked(false); | |||
| add(p); | |||
| return p; | |||
| } | |||
| @@ -261,17 +248,12 @@ public class Path extends DataType implements Cloneable { | |||
| if (other == null) { | |||
| return; | |||
| } | |||
| String[] l = other.list(); | |||
| for (int i = 0; i < l.length; i++) { | |||
| if (elements.indexOf(l[i]) == -1) { | |||
| elements.addElement(l[i]); | |||
| } | |||
| } | |||
| add(other); | |||
| } | |||
| /** | |||
| /** | |||
| * Adds the components on the given path which exist to this | |||
| * Path. Components that don't exist, aren't added. | |||
| * Path. Components that don't exist aren't added. | |||
| * | |||
| * @param source - source path whose components are examined for existence | |||
| */ | |||
| @@ -309,92 +291,29 @@ public class Path extends DataType implements Cloneable { | |||
| } | |||
| /** | |||
| * Returns all path elements defined by this and nested path objects. | |||
| * @return list of path elements. | |||
| */ | |||
| public String[] list() { | |||
| if (!isChecked()) { | |||
| // make sure we don't have a circular reference here | |||
| Stack stk = new Stack(); | |||
| stk.push(this); | |||
| dieOnCircularReference(stk, getProject()); | |||
| } | |||
| Vector result = new Vector(2 * elements.size()); | |||
| for (int i = 0; i < elements.size(); i++) { | |||
| Object o = elements.elementAt(i); | |||
| if (o instanceof Reference) { | |||
| Reference r = (Reference) o; | |||
| o = r.getReferencedObject(getProject()); | |||
| // we only support references to paths right now | |||
| if (!(o instanceof Path)) { | |||
| String msg = r.getRefId() + " doesn\'t denote a path " + o; | |||
| throw new BuildException(msg); | |||
| } | |||
| * Override <code>Union.getCollection()</code> | |||
| * so we can check our children first. | |||
| * @return a Collection. | |||
| */ | |||
| protected Collection getCollection() { | |||
| for (Iterator i = getResourceCollections().iterator(); i.hasNext();) { | |||
| ResourceCollection rc = (ResourceCollection) i.next(); | |||
| if (!(rc.isFilesystemOnly())) { | |||
| throw new BuildException(getDataTypeName() | |||
| + " allows only filesystem resources."); | |||
| } | |||
| if (o instanceof String) { | |||
| // obtained via append | |||
| addUnlessPresent(result, (String) o); | |||
| } else if (o instanceof PathElement) { | |||
| String[] parts = ((PathElement) o).getParts(); | |||
| if (parts == null) { | |||
| throw new BuildException("You must either set location or" | |||
| + " path on <pathelement>"); | |||
| } | |||
| for (int j = 0; j < parts.length; j++) { | |||
| addUnlessPresent(result, parts[j]); | |||
| } | |||
| } else if (o instanceof Path) { | |||
| Path p = (Path) o; | |||
| if (rc instanceof PathElement | |||
| && ((PathElement) rc).getParts() == null) { | |||
| throw new BuildException( | |||
| "Either location or path must be set on a pathelement."); | |||
| } else if (rc instanceof Path) { | |||
| Path p = (Path) rc; | |||
| if (p.getProject() == null) { | |||
| p.setProject(getProject()); | |||
| } | |||
| String[] parts = p.list(); | |||
| for (int j = 0; j < parts.length; j++) { | |||
| addUnlessPresent(result, parts[j]); | |||
| } | |||
| } else if (o instanceof DirSet) { | |||
| DirSet dset = (DirSet) o; | |||
| addUnlessPresent(result, dset.getDir(getProject()), | |||
| dset.getDirectoryScanner(getProject()).getIncludedDirectories()); | |||
| } else if (o instanceof FileSet) { | |||
| FileSet fs = (FileSet) o; | |||
| addUnlessPresent(result, fs.getDir(getProject()), | |||
| fs.getDirectoryScanner(getProject()).getIncludedFiles()); | |||
| } else if (o instanceof FileList) { | |||
| FileList fl = (FileList) o; | |||
| addUnlessPresent(result, | |||
| fl.getDir(getProject()), fl.getFiles(getProject())); | |||
| } | |||
| } | |||
| String[] res = new String[result.size()]; | |||
| result.copyInto(res); | |||
| return res; | |||
| } | |||
| /** | |||
| * Returns a textual representation of the path, which can be used as | |||
| * CLASSPATH or PATH environment variable definition. | |||
| * @return a textual representation of the path. | |||
| */ | |||
| public String toString() { | |||
| final String[] list = list(); | |||
| // empty path return empty string | |||
| if (list.length == 0) { | |||
| return ""; | |||
| } | |||
| // path containing one or more elements | |||
| final StringBuffer result = new StringBuffer(list[0].toString()); | |||
| for (int i = 1; i < list.length; i++) { | |||
| result.append(File.pathSeparatorChar); | |||
| result.append(list[i]); | |||
| } | |||
| return result.toString(); | |||
| return super.getCollection(); | |||
| } | |||
| /** | |||
| @@ -466,62 +385,6 @@ public class Path extends DataType implements Cloneable { | |||
| return false; | |||
| } | |||
| /** | |||
| * How many parts does this Path instance consist of. | |||
| * @return the number of parts | |||
| */ | |||
| public int size() { | |||
| return list().length; | |||
| } | |||
| /** | |||
| * Return a Path that holds the same elements as this instance. | |||
| * @return a copy of the path | |||
| */ | |||
| public Object clone() { | |||
| try { | |||
| Path p = (Path) super.clone(); | |||
| p.elements = (Vector) elements.clone(); | |||
| return p; | |||
| } catch (CloneNotSupportedException e) { | |||
| throw new BuildException(e); | |||
| } | |||
| } | |||
| /** | |||
| * Overrides the version of DataType to recurse on all DataType | |||
| * child elements that may have been added. | |||
| * @param stk the stack of data types to use (recursively) | |||
| * @param p the project to use to dereference the references | |||
| * @throws BuildException on error | |||
| */ | |||
| protected void dieOnCircularReference(Stack stk, Project p) | |||
| throws BuildException { | |||
| if (isChecked()) { | |||
| return; | |||
| } | |||
| Enumeration e = elements.elements(); | |||
| while (e.hasMoreElements()) { | |||
| Object o = e.nextElement(); | |||
| if (o instanceof Reference) { | |||
| o = ((Reference) o).getReferencedObject(p); | |||
| } | |||
| if (o instanceof DataType) { | |||
| if (stk.contains(o)) { | |||
| throw circularReference(); | |||
| } else { | |||
| stk.push(o); | |||
| ((DataType) o).dieOnCircularReference(stk, p); | |||
| stk.pop(); | |||
| } | |||
| } | |||
| } | |||
| setChecked(true); | |||
| } | |||
| /** | |||
| * Resolve a filename with Project's help - if we know one that is. | |||
| */ | |||
| @@ -530,27 +393,6 @@ public class Path extends DataType implements Cloneable { | |||
| (project == null) ? null : project.getBaseDir(), relativeName); | |||
| } | |||
| /** | |||
| * Adds a String to the Vector if it isn't already included. | |||
| */ | |||
| private static void addUnlessPresent(Vector v, String s) { | |||
| if (v.indexOf(s) == -1) { | |||
| v.addElement(s); | |||
| } | |||
| } | |||
| /** | |||
| * Adds absolute path names of listed files in the given directory | |||
| * to the Vector if they are not already included. | |||
| */ | |||
| private static void addUnlessPresent(Vector v, File dir, String[] s) { | |||
| for (int j = 0; j < s.length; j++) { | |||
| File d = new File(dir, s[j]); | |||
| String absolutePath = d.getAbsolutePath(); | |||
| addUnlessPresent(v, translateFile(absolutePath)); | |||
| } | |||
| } | |||
| /** | |||
| * Concatenates the system class path in the order specified by | |||
| * the ${build.sysclasspath} property - using "last" as | |||
| @@ -737,4 +579,5 @@ public class Path extends DataType implements Cloneable { | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @@ -30,6 +30,8 @@ import java.util.Vector; | |||
| import org.apache.tools.ant.BuildException; | |||
| import org.apache.tools.ant.Project; | |||
| import org.apache.tools.ant.types.ResourceCollection; | |||
| import org.apache.tools.ant.types.resources.PropertyResource; | |||
| import org.apache.tools.ant.util.FileNameMapper; | |||
| import org.apache.tools.ant.util.regexp.RegexpMatcher; | |||
| import org.apache.tools.ant.util.regexp.RegexpMatcherFactory; | |||
| @@ -39,7 +41,7 @@ import org.apache.tools.ant.util.regexp.RegexpMatcherFactory; | |||
| * | |||
| * @since Ant 1.6 | |||
| */ | |||
| public class PropertySet extends DataType { | |||
| public class PropertySet extends DataType implements ResourceCollection { | |||
| private boolean dynamic = true; | |||
| private boolean negate = false; | |||
| @@ -463,4 +465,40 @@ public class PropertySet extends DataType { | |||
| return b.toString(); | |||
| } | |||
| /** | |||
| * Fulfill the ResourceCollection interface. | |||
| * @return an Iterator of Resources. | |||
| * @since Ant 1.7 | |||
| */ | |||
| public Iterator iterator() { | |||
| final Enumeration e = getProperties().propertyNames(); | |||
| return new Iterator() { | |||
| public boolean hasNext() { | |||
| return e.hasMoreElements(); | |||
| } | |||
| public Object next() { | |||
| return new PropertyResource(getProject(), (String) e.nextElement()); | |||
| } | |||
| public void remove() { | |||
| throw new UnsupportedOperationException(); | |||
| } | |||
| }; | |||
| } | |||
| /** | |||
| * Fulfill the ResourceCollection contract. | |||
| * @return the size of this ResourceCollection. | |||
| */ | |||
| public int size() { | |||
| return isReference() ? getRef().size() : getProperties().size(); | |||
| } | |||
| /** | |||
| * Fulfill the ResourceCollection contract. | |||
| * @return whether this is a filesystem-only resource collection. | |||
| */ | |||
| public boolean isFilesystemOnly() { | |||
| return isReference() && getRef().isFilesystemOnly(); | |||
| } | |||
| } | |||
| @@ -16,24 +16,51 @@ | |||
| */ | |||
| package org.apache.tools.ant.types; | |||
| import java.io.InputStream; | |||
| import java.io.IOException; | |||
| import java.io.OutputStream; | |||
| import java.math.BigInteger; | |||
| import java.util.Stack; | |||
| import java.util.Iterator; | |||
| import java.util.NoSuchElementException; | |||
| import org.apache.tools.ant.BuildException; | |||
| /** | |||
| * Describes a File or a ZipEntry. | |||
| * Describes a "File-like" resource (File, ZipEntry, etc.). | |||
| * | |||
| * This class is meant to be used by classes needing to record path | |||
| * and date/time information about a file, a zip entry or some similar | |||
| * resource (URL, archive in a version control repository, ...). | |||
| * | |||
| * @since Ant 1.5.2 | |||
| * @see org.apache.tools.ant.types.resources.Touchable | |||
| */ | |||
| public class Resource implements Cloneable, Comparable { | |||
| public class Resource extends DataType | |||
| implements Cloneable, Comparable, ResourceCollection { | |||
| /** Constant unknown size */ | |||
| public static final long UNKNOWN_SIZE = -1; | |||
| /** Magic number */ | |||
| protected static final int MAGIC = getMagicNumber("Resource".getBytes()); | |||
| private static final int NULL_NAME = getMagicNumber("null name".getBytes()); | |||
| /** | |||
| * Create a "magic number" for use in hashCode calculations. | |||
| * @param seed byte[] to seed with. | |||
| * @return a magic number as int. | |||
| */ | |||
| protected static int getMagicNumber(byte[] seed) { | |||
| return new BigInteger(seed).intValue(); | |||
| } | |||
| private String name = null; | |||
| private boolean exists = true; | |||
| private long lastmodified = 0; | |||
| private boolean directory = false; | |||
| private long size = UNKNOWN_SIZE; | |||
| private Boolean exists = null; | |||
| private Long lastmodified = null; | |||
| private Boolean directory = null; | |||
| private Long size = null; | |||
| /** | |||
| * Default constructor. | |||
| @@ -112,7 +139,7 @@ public class Resource implements Cloneable, Comparable { | |||
| * @return the name of this resource. | |||
| */ | |||
| public String getName() { | |||
| return name; | |||
| return isReference() ? ((Resource) getCheckedRef()).getName() : name; | |||
| } | |||
| /** | |||
| @@ -121,6 +148,7 @@ public class Resource implements Cloneable, Comparable { | |||
| * "/" to be used as the directory separator. | |||
| */ | |||
| public void setName(String name) { | |||
| checkAttributesAllowed(); | |||
| this.name = name; | |||
| } | |||
| @@ -129,7 +157,11 @@ public class Resource implements Cloneable, Comparable { | |||
| * @return true if this resource exists. | |||
| */ | |||
| public boolean isExists() { | |||
| return exists; | |||
| if (isReference()) { | |||
| return ((Resource) getCheckedRef()).isExists(); | |||
| } | |||
| //default true: | |||
| return exists == null || exists.booleanValue(); | |||
| } | |||
| /** | |||
| @@ -137,7 +169,8 @@ public class Resource implements Cloneable, Comparable { | |||
| * @param exists if true, this resource exists. | |||
| */ | |||
| public void setExists(boolean exists) { | |||
| this.exists = exists; | |||
| checkAttributesAllowed(); | |||
| this.exists = exists ? Boolean.TRUE : Boolean.FALSE; | |||
| } | |||
| /** | |||
| @@ -147,7 +180,14 @@ public class Resource implements Cloneable, Comparable { | |||
| * of {@link java.io.File File}. | |||
| */ | |||
| public long getLastModified() { | |||
| return !exists || lastmodified < 0 ? 0L : lastmodified; | |||
| if (isReference()) { | |||
| return ((Resource) getCheckedRef()).getLastModified(); | |||
| } | |||
| if (!isExists() || lastmodified == null) { | |||
| return 0L; | |||
| } | |||
| long result = lastmodified.longValue(); | |||
| return result < 0L ? 0L : result; | |||
| } | |||
| /** | |||
| @@ -155,7 +195,8 @@ public class Resource implements Cloneable, Comparable { | |||
| * @param lastmodified the modification time in milliseconds since 01.01.1970. | |||
| */ | |||
| public void setLastModified(long lastmodified) { | |||
| this.lastmodified = lastmodified; | |||
| checkAttributesAllowed(); | |||
| this.lastmodified = new Long(lastmodified); | |||
| } | |||
| /** | |||
| @@ -163,7 +204,11 @@ public class Resource implements Cloneable, Comparable { | |||
| * @return boolean flag indicating if the resource is a directory. | |||
| */ | |||
| public boolean isDirectory() { | |||
| return directory; | |||
| if (isReference()) { | |||
| return ((Resource) getCheckedRef()).isDirectory(); | |||
| } | |||
| //default false: | |||
| return directory != null && directory.booleanValue(); | |||
| } | |||
| /** | |||
| @@ -171,26 +216,31 @@ public class Resource implements Cloneable, Comparable { | |||
| * @param directory if true, this resource is a directory. | |||
| */ | |||
| public void setDirectory(boolean directory) { | |||
| this.directory = directory; | |||
| checkAttributesAllowed(); | |||
| this.directory = directory ? Boolean.TRUE : Boolean.FALSE; | |||
| } | |||
| /** | |||
| * Set the size of this Resource. | |||
| * @param size the size, as a long. | |||
| * @since Ant 1.7 | |||
| * @since Ant 1.6.3 | |||
| */ | |||
| public void setSize(long size) { | |||
| this.size = (size > UNKNOWN_SIZE) ? size : UNKNOWN_SIZE; | |||
| checkAttributesAllowed(); | |||
| this.size = new Long(size > UNKNOWN_SIZE ? size : UNKNOWN_SIZE); | |||
| } | |||
| /** | |||
| * Get the size of this Resource. | |||
| * @return the size, as a long, 0 if the Resource does not exist (for | |||
| * compatibility with java.io.File), or UNKNOWN_SIZE if not known. | |||
| * @since Ant 1.7 | |||
| * @since Ant 1.6.3 | |||
| */ | |||
| public long getSize() { | |||
| return (exists) ? size : 0L; | |||
| if (isReference()) { | |||
| return ((Resource) getCheckedRef()).getSize(); | |||
| } | |||
| return isExists() && size != null ? size.longValue() : 0L; | |||
| } | |||
| /** | |||
| @@ -215,12 +265,168 @@ public class Resource implements Cloneable, Comparable { | |||
| * @since Ant 1.6 | |||
| */ | |||
| public int compareTo(Object other) { | |||
| if (isReference()) { | |||
| return ((Comparable) getCheckedRef()).compareTo(other); | |||
| } | |||
| if (!(other instanceof Resource)) { | |||
| throw new IllegalArgumentException("Can only be compared with " | |||
| + "Resources"); | |||
| throw new IllegalArgumentException( | |||
| "Can only be compared with Resources"); | |||
| } | |||
| Resource r = (Resource) other; | |||
| return getName().compareTo(r.getName()); | |||
| String name = getName(); | |||
| String oname = r.getName(); | |||
| if (name == null && oname == null) { | |||
| return 0; | |||
| } | |||
| if (name == null) { | |||
| return -1; | |||
| } | |||
| return oname == null ? 1 : name.compareTo(oname); | |||
| } | |||
| /** | |||
| * Implement basic Resource equality. | |||
| * @return true if the specified Object is equal to this Resource. | |||
| * @since Ant 1.7 | |||
| */ | |||
| public boolean equals(Object other) { | |||
| if (isReference()) { | |||
| return getCheckedRef().equals(other); | |||
| } | |||
| return other.getClass().equals(getClass()) && compareTo(other) == 0; | |||
| } | |||
| /** | |||
| * Get the hash code for this Resource. | |||
| * @return hash code as int. | |||
| * @since Ant 1.7 | |||
| */ | |||
| public int hashCode() { | |||
| if (isReference()) { | |||
| return getCheckedRef().hashCode(); | |||
| } | |||
| String name = getName(); | |||
| return MAGIC * (name == null ? name.hashCode() : NULL_NAME); | |||
| } | |||
| /** | |||
| * Get an InputStream for the Resource. | |||
| * @return an InputStream containing this Resource's content. | |||
| * @throws IOException if unable to provide the content of this | |||
| * Resource as a stream. | |||
| * @throws UnsupportedOperationException if InputStreams are not | |||
| * supported for this Resource type. | |||
| * @since Ant 1.7 | |||
| */ | |||
| public InputStream getInputStream() throws IOException { | |||
| if (isReference()) { | |||
| return ((Resource) getCheckedRef()).getInputStream(); | |||
| } | |||
| throw new UnsupportedOperationException(); | |||
| } | |||
| /** | |||
| * Get an OutputStream for the Resource. | |||
| * @return an OutputStream to which content can be written. | |||
| * @throws IOException if unable to provide the content of this | |||
| * Resource as a stream. | |||
| * @throws UnsupportedOperationException if OutputStreams are not | |||
| * supported for this Resource type. | |||
| * @since Ant 1.7 | |||
| */ | |||
| public OutputStream getOutputStream() throws IOException { | |||
| if (isReference()) { | |||
| return ((Resource) getCheckedRef()).getOutputStream(); | |||
| } | |||
| throw new UnsupportedOperationException(); | |||
| } | |||
| /** | |||
| * Fulfill the ResourceCollection contract. | |||
| * @return an Iterator of Resources. | |||
| * @since Ant 1.7 | |||
| */ | |||
| public Iterator iterator() { | |||
| return isReference() ? ((Resource) getCheckedRef()).iterator() | |||
| : new Iterator() { | |||
| boolean done = false; | |||
| public boolean hasNext() { | |||
| return !done; | |||
| } | |||
| public Object next() { | |||
| if (done) { | |||
| throw new NoSuchElementException(); | |||
| } | |||
| done = true; | |||
| return Resource.this; | |||
| } | |||
| public void remove() { | |||
| throw new UnsupportedOperationException(); | |||
| } | |||
| }; | |||
| } | |||
| /** | |||
| * Fulfill the ResourceCollection contract. | |||
| * @return the size of this ResourceCollection. | |||
| * @since Ant 1.7 | |||
| */ | |||
| public int size() { | |||
| return isReference() ? ((Resource) getCheckedRef()).size() : 1; | |||
| } | |||
| /** | |||
| * Fulfill the ResourceCollection contract. | |||
| * @return whether this Resource is a FileResource. | |||
| * @since Ant 1.7 | |||
| */ | |||
| public boolean isFilesystemOnly() { | |||
| //default false: | |||
| return isReference() && ((Resource) getCheckedRef()).isFilesystemOnly(); | |||
| } | |||
| /** | |||
| * Get the string representation of this Resource. | |||
| * @return this Resource formatted as a String. | |||
| * @since Ant 1.7 | |||
| */ | |||
| public String toString() { | |||
| if (isReference()) { | |||
| return getCheckedRef().toString(); | |||
| } | |||
| String n = getName(); | |||
| if (n != null) { | |||
| return n; | |||
| } | |||
| String classname = getClass().getName(); | |||
| return "anonymous " + classname.substring(classname.lastIndexOf('.') + 1); | |||
| } | |||
| /** | |||
| * Get a long String representation of this Resource. | |||
| * This typically should be the value of <code>toString()</code> | |||
| * prefixed by a type description. | |||
| * @return this Resource formatted as a long String. | |||
| * @since Ant 1.7 | |||
| */ | |||
| public final String toLongString() { | |||
| return isReference() ? ((Resource) getCheckedRef()).toLongString() | |||
| : getDataTypeName() + " \"" + toString() + '"'; | |||
| } | |||
| /** | |||
| * Overrides the base version. | |||
| * @param r the Reference to set. | |||
| */ | |||
| public void setRefid(Reference r) { | |||
| if (name != null | |||
| || exists != null | |||
| || lastmodified != null | |||
| || directory != null | |||
| || size != null) { | |||
| throw tooManyAttributes(); | |||
| } | |||
| super.setRefid(r); | |||
| } | |||
| } | |||
| @@ -0,0 +1,49 @@ | |||
| /* | |||
| * Copyright 2005 The Apache Software Foundation | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * | |||
| */ | |||
| package org.apache.tools.ant.types; | |||
| import java.util.Iterator; | |||
| /** | |||
| * Interface describing a collection of Resources. | |||
| * @since Ant 1.7 | |||
| */ | |||
| public interface ResourceCollection { | |||
| /** | |||
| * Get an Iterator over the contents of this ResourceCollection, whose elements | |||
| * are <code>org.apache.tools.ant.types.Resource</code> instances. | |||
| * @return an Iterator of Resources. | |||
| */ | |||
| public Iterator iterator(); | |||
| /** | |||
| * Learn the number of contained Resources. | |||
| * @return number of elements as int. | |||
| */ | |||
| public int size(); | |||
| /** | |||
| * Indicate whether this ResourceCollection is composed entirely of | |||
| * Resources accessible via local filesystem conventions. If true, | |||
| * all Resources returned from this ResourceCollection should be | |||
| * instances of FileResource. | |||
| * @return whether this is a filesystem-only resource collection. | |||
| */ | |||
| public boolean isFilesystemOnly(); | |||
| } | |||
| @@ -18,6 +18,7 @@ package org.apache.tools.ant.types; | |||
| import java.io.File; | |||
| import java.util.Stack; | |||
| import java.util.Iterator; | |||
| import org.apache.tools.ant.BuildException; | |||
| import org.apache.tools.ant.DirectoryScanner; | |||
| import org.apache.tools.ant.Project; | |||
| @@ -62,6 +63,8 @@ public class ZipFileSet extends FileSet { | |||
| private boolean fileModeHasBeenSet = false; | |||
| private boolean dirModeHasBeenSet = false; | |||
| private String encoding = null; | |||
| /** Constructor for ZipFileSet */ | |||
| public ZipFileSet() { | |||
| super(); | |||
| @@ -89,6 +92,7 @@ public class ZipFileSet extends FileSet { | |||
| dirMode = fileset.dirMode; | |||
| fileModeHasBeenSet = fileset.fileModeHasBeenSet; | |||
| dirModeHasBeenSet = fileset.dirModeHasBeenSet; | |||
| encoding = fileset.encoding; | |||
| } | |||
| /** | |||
| @@ -98,9 +102,7 @@ public class ZipFileSet extends FileSet { | |||
| * @throws BuildException on error | |||
| */ | |||
| public void setDir(File dir) throws BuildException { | |||
| if (isReference()) { | |||
| throw tooManyAttributes(); | |||
| } | |||
| checkAttributesAllowed(); | |||
| if (srcFile != null) { | |||
| throw new BuildException("Cannot set both dir and src attributes"); | |||
| } else { | |||
| @@ -116,9 +118,7 @@ public class ZipFileSet extends FileSet { | |||
| * @param srcFile The zip file from which to extract entries. | |||
| */ | |||
| public void setSrc(File srcFile) { | |||
| if (isReference()) { | |||
| throw tooManyAttributes(); | |||
| } | |||
| checkAttributesAllowed(); | |||
| if (hasDir) { | |||
| throw new BuildException("Cannot set both dir and src attributes"); | |||
| } | |||
| @@ -189,6 +189,24 @@ public class ZipFileSet extends FileSet { | |||
| return fullpath; | |||
| } | |||
| /** | |||
| * Set the encoding used for this ZipFileSet. | |||
| * @param enc encoding as String. | |||
| * @since Ant 1.7 | |||
| */ | |||
| public void setEncoding(String enc) { | |||
| this.encoding = enc; | |||
| } | |||
| /** | |||
| * Get the encoding used for this ZipFileSet. | |||
| * @return String encoding. | |||
| * @since Ant 1.7 | |||
| */ | |||
| public String getEncoding() { | |||
| return encoding; | |||
| } | |||
| /** | |||
| * Return the DirectoryScanner associated with this FileSet. | |||
| * If the ZipFileSet defines a source Zip file, then a ZipScanner | |||
| @@ -200,16 +218,60 @@ public class ZipFileSet extends FileSet { | |||
| if (isReference()) { | |||
| return getRef(p).getDirectoryScanner(p); | |||
| } | |||
| if (srcFile != null) { | |||
| ZipScanner zs = new ZipScanner(); | |||
| zs.setSrc(srcFile); | |||
| super.setDir(p.getBaseDir()); | |||
| setupDirectoryScanner(zs, p); | |||
| zs.init(); | |||
| return zs; | |||
| } else { | |||
| if (srcFile == null) { | |||
| return super.getDirectoryScanner(p); | |||
| } | |||
| ZipScanner zs = new ZipScanner(); | |||
| zs.setSrc(srcFile); | |||
| super.setDir(p.getBaseDir()); | |||
| setupDirectoryScanner(zs, p); | |||
| zs.init(); | |||
| zs.setEncoding(encoding); | |||
| return zs; | |||
| } | |||
| /** | |||
| * Fulfill the ResourceCollection contract. | |||
| * @return Iterator of Resources. | |||
| * @since Ant 1.7 | |||
| */ | |||
| public Iterator iterator() { | |||
| if (isReference()) { | |||
| return ((ResourceCollection) (getRef(getProject()))).iterator(); | |||
| } | |||
| if (srcFile == null) { | |||
| return super.iterator(); | |||
| } | |||
| ZipScanner zs = (ZipScanner) getDirectoryScanner(getProject()); | |||
| return zs.getResourceFiles(); | |||
| } | |||
| /** | |||
| * Fulfill the ResourceCollection contract. | |||
| * @return size of the collection as int. | |||
| * @since Ant 1.7 | |||
| */ | |||
| public int size() { | |||
| if (isReference()) { | |||
| return ((ResourceCollection) (getRef(getProject()))).size(); | |||
| } | |||
| if (srcFile == null) { | |||
| return super.size(); | |||
| } | |||
| ZipScanner zs = (ZipScanner) getDirectoryScanner(getProject()); | |||
| return zs.getIncludedFilesCount(); | |||
| } | |||
| /** | |||
| * Indicate whether this ResourceCollection is composed entirely of | |||
| * Resources accessible via local filesystem conventions. If true, | |||
| * all Resources returned from this ResourceCollection should be | |||
| * instances of FileResource. | |||
| * @return whether this is a filesystem-only resource collection. | |||
| * @since Ant 1.7 | |||
| */ | |||
| public boolean isFilesystemOnly() { | |||
| return srcFile == null; | |||
| } | |||
| /** | |||
| @@ -297,11 +359,7 @@ public class ZipFileSet extends FileSet { | |||
| * @return the abstract fileset instance | |||
| */ | |||
| protected AbstractFileSet getRef(Project p) { | |||
| if (!isChecked()) { | |||
| Stack stk = new Stack(); | |||
| stk.push(this); | |||
| dieOnCircularReference(stk, p); | |||
| } | |||
| dieOnCircularReference(p); | |||
| Object o = getRefid().getReferencedObject(p); | |||
| if (o instanceof ZipFileSet) { | |||
| return (AbstractFileSet) o; | |||
| @@ -319,6 +377,7 @@ public class ZipFileSet extends FileSet { | |||
| throw new BuildException(msg); | |||
| } | |||
| } | |||
| /** | |||
| * Return a ZipFileSet that has the same properties | |||
| * as this one. | |||
| @@ -19,14 +19,20 @@ package org.apache.tools.ant.types; | |||
| import java.io.File; | |||
| import java.io.IOException; | |||
| import java.util.Arrays; | |||
| import java.util.Vector; | |||
| import java.util.Set; | |||
| import java.util.TreeMap; | |||
| import java.util.Iterator; | |||
| import java.util.ArrayList; | |||
| import java.util.Hashtable; | |||
| import java.util.Comparator; | |||
| import java.util.Collections; | |||
| import java.util.Enumeration; | |||
| import java.util.zip.ZipException; | |||
| import org.apache.tools.ant.BuildException; | |||
| import org.apache.tools.ant.DirectoryScanner; | |||
| import org.apache.tools.ant.types.resources.ZipResource; | |||
| import org.apache.tools.ant.types.resources.FileResourceIterator; | |||
| import org.apache.tools.zip.ZipEntry; | |||
| import org.apache.tools.zip.ZipFile; | |||
| @@ -44,14 +50,31 @@ public class ZipScanner extends DirectoryScanner { | |||
| * The zip file which should be scanned. | |||
| */ | |||
| protected File srcFile; | |||
| /** | |||
| * to record the last scanned zip file with its modification date | |||
| */ | |||
| private Resource lastScannedResource; | |||
| /** | |||
| * record list of all file zip entries | |||
| */ | |||
| private TreeMap fileEntries = new TreeMap(); | |||
| /** | |||
| * record list of all zip entries | |||
| * record list of all directory zip entries | |||
| */ | |||
| private Hashtable myentries; | |||
| private TreeMap dirEntries = new TreeMap(); | |||
| /** | |||
| * record list of matching file zip entries | |||
| */ | |||
| private TreeMap matchFileEntries = new TreeMap(); | |||
| /** | |||
| * record list of matching directory zip entries | |||
| */ | |||
| private TreeMap matchDirEntries = new TreeMap(); | |||
| /** | |||
| * encoding of file names. | |||
| @@ -60,6 +83,17 @@ public class ZipScanner extends DirectoryScanner { | |||
| */ | |||
| private String encoding; | |||
| /** | |||
| * Don't scan when we have no zipfile. | |||
| * @since Ant 1.7 | |||
| */ | |||
| public void scan() { | |||
| if (srcFile == null) { | |||
| return; | |||
| } | |||
| super.scan(); | |||
| } | |||
| /** | |||
| * Sets the srcFile for scanning. This is the jar or zip file that | |||
| * is scanned for matching entries. | |||
| @@ -88,23 +122,25 @@ public class ZipScanner extends DirectoryScanner { | |||
| * include patterns and none of the exclude patterns. | |||
| */ | |||
| public String[] getIncludedFiles() { | |||
| if (srcFile != null) { | |||
| Vector myvector = new Vector(); | |||
| // first check if the archive needs to be scanned again | |||
| scanme(); | |||
| for (Enumeration e = myentries.elements(); e.hasMoreElements();) { | |||
| Resource myresource = (Resource) e.nextElement(); | |||
| if (!myresource.isDirectory() && match(myresource.getName())) { | |||
| myvector.addElement(myresource.getName()); | |||
| } | |||
| } | |||
| String[] files = new String[myvector.size()]; | |||
| myvector.copyInto(files); | |||
| Arrays.sort(files); | |||
| return files; | |||
| } else { | |||
| if (srcFile == null) { | |||
| return super.getIncludedFiles(); | |||
| } | |||
| scanme(); | |||
| Set s = matchFileEntries.keySet(); | |||
| return (String[]) (s.toArray(new String[s.size()])); | |||
| } | |||
| /** | |||
| * Override parent implementation. | |||
| * @return count of included files. | |||
| * @since Ant 1.7 | |||
| */ | |||
| public int getIncludedFilesCount() { | |||
| if (srcFile == null) { | |||
| return super.getIncludedFilesCount(); | |||
| } | |||
| scanme(); | |||
| return matchFileEntries.size(); | |||
| } | |||
| /** | |||
| @@ -116,23 +152,51 @@ public class ZipScanner extends DirectoryScanner { | |||
| * include patterns and none of the exclude patterns. | |||
| */ | |||
| public String[] getIncludedDirectories() { | |||
| if (srcFile != null) { | |||
| Vector myvector = new Vector(); | |||
| // first check if the archive needs to be scanned again | |||
| scanme(); | |||
| for (Enumeration e = myentries.elements(); e.hasMoreElements();) { | |||
| Resource myresource = (Resource) e.nextElement(); | |||
| if (myresource.isDirectory() && match(myresource.getName())) { | |||
| myvector.addElement(myresource.getName()); | |||
| } | |||
| } | |||
| String[] files = new String[myvector.size()]; | |||
| myvector.copyInto(files); | |||
| Arrays.sort(files); | |||
| return files; | |||
| } else { | |||
| if (srcFile == null) { | |||
| return super.getIncludedDirectories(); | |||
| } | |||
| scanme(); | |||
| Set s = matchDirEntries.keySet(); | |||
| return (String[]) (s.toArray(new String[s.size()])); | |||
| } | |||
| /** | |||
| * Override parent implementation. | |||
| * @return count of included directories. | |||
| * @since Ant 1.7 | |||
| */ | |||
| public int getIncludedDirsCount() { | |||
| if (srcFile == null) { | |||
| return super.getIncludedDirsCount(); | |||
| } | |||
| scanme(); | |||
| return matchDirEntries.size(); | |||
| } | |||
| /** | |||
| * Get the set of Resources that represent files. | |||
| * @return an Iterator of Resources. | |||
| * @since Ant 1.7 | |||
| */ | |||
| /* package-private for now */ Iterator getResourceFiles() { | |||
| if (srcFile == null) { | |||
| return new FileResourceIterator(getBasedir(), getIncludedFiles()); | |||
| } | |||
| scanme(); | |||
| return matchFileEntries.values().iterator(); | |||
| } | |||
| /** | |||
| * Get the set of Resources that represent directories. | |||
| * @return an Iterator of Resources. | |||
| * @since Ant 1.7 | |||
| */ | |||
| /* package-private for now */ Iterator getResourceDirectories() { | |||
| if (srcFile == null) { | |||
| return new FileResourceIterator(getBasedir(), getIncludedDirectories()); | |||
| } | |||
| scanme(); | |||
| return matchDirEntries.values().iterator(); | |||
| } | |||
| /** | |||
| @@ -165,6 +229,7 @@ public class ZipScanner extends DirectoryScanner { | |||
| } | |||
| /** | |||
| * Get the named Resource. | |||
| * @param name path name of the file sought in the archive | |||
| * @return the resource | |||
| * @since Ant 1.5.2 | |||
| @@ -172,34 +237,35 @@ public class ZipScanner extends DirectoryScanner { | |||
| public Resource getResource(String name) { | |||
| if (srcFile == null) { | |||
| return super.getResource(name); | |||
| } else if (name.equals("")) { | |||
| } | |||
| if (name.equals("")) { | |||
| // special case in ZIPs, we do not want this thing included | |||
| return new Resource("", true, Long.MAX_VALUE, true); | |||
| } | |||
| // first check if the archive needs to be scanned again | |||
| scanme(); | |||
| if (myentries.containsKey(name)) { | |||
| return (Resource) myentries.get(name); | |||
| } else if (myentries.containsKey(name + "/")) { | |||
| return (Resource) myentries.get(name + "/"); | |||
| } else { | |||
| return new Resource(name); | |||
| if (fileEntries.containsKey(name)) { | |||
| return (Resource) fileEntries.get(name); | |||
| } | |||
| name = trimSeparator(name); | |||
| if (dirEntries.containsKey(name)) { | |||
| return (Resource) dirEntries.get(name); | |||
| } | |||
| return new Resource(name); | |||
| } | |||
| /** | |||
| * if the datetime of the archive did not change since | |||
| * lastScannedResource was initialized returns immediately else if | |||
| * the archive has not been scanned yet, then all the zip entries | |||
| * are put into the vector myentries as a vector of the resource | |||
| * type | |||
| * are put into the appropriate tables. | |||
| */ | |||
| private void scanme() { | |||
| //do not use a FileResource b/c it pulls File info from the filesystem: | |||
| Resource thisresource = new Resource(srcFile.getAbsolutePath(), | |||
| srcFile.exists(), | |||
| srcFile.lastModified()); | |||
| // spare scanning again and again | |||
| if (lastScannedResource != null | |||
| && lastScannedResource.getName().equals(thisresource.getName()) | |||
| @@ -207,10 +273,15 @@ public class ZipScanner extends DirectoryScanner { | |||
| == thisresource.getLastModified()) { | |||
| return; | |||
| } | |||
| init(); | |||
| ZipEntry entry = null; | |||
| ZipFile zf = null; | |||
| myentries = new Hashtable(); | |||
| fileEntries.clear(); | |||
| dirEntries.clear(); | |||
| matchFileEntries.clear(); | |||
| matchDirEntries.clear(); | |||
| try { | |||
| try { | |||
| zf = new ZipFile(srcFile, encoding); | |||
| @@ -219,15 +290,23 @@ public class ZipScanner extends DirectoryScanner { | |||
| } catch (IOException ex) { | |||
| throw new BuildException("problem opening " + srcFile, ex); | |||
| } | |||
| Enumeration e = zf.getEntries(); | |||
| while (e.hasMoreElements()) { | |||
| entry = (ZipEntry) e.nextElement(); | |||
| myentries.put(new String(entry.getName()), | |||
| new Resource(entry.getName(), true, | |||
| entry.getTime(), | |||
| entry.isDirectory(), | |||
| entry.getSize())); | |||
| Resource r = new ZipResource(srcFile, encoding, entry); | |||
| String name = entry.getName(); | |||
| if (entry.isDirectory()) { | |||
| name = trimSeparator(name); | |||
| dirEntries.put(name, r); | |||
| if (match(name)) { | |||
| matchDirEntries.put(name, r); | |||
| } | |||
| } else { | |||
| fileEntries.put(name, r); | |||
| if (match(name)) { | |||
| matchFileEntries.put(name, r); | |||
| } | |||
| } | |||
| } | |||
| } finally { | |||
| if (zf != null) { | |||
| @@ -241,4 +320,9 @@ public class ZipScanner extends DirectoryScanner { | |||
| // record data about the last scanned resource | |||
| lastScannedResource = thisresource; | |||
| } | |||
| private static String trimSeparator(String s) { | |||
| return s.endsWith("/") ? s.substring(0, s.length() - 1) : s; | |||
| } | |||
| } | |||
| @@ -1,8 +1,4 @@ | |||
| classfileset=org.apache.tools.ant.types.optional.depend.ClassfileSet | |||
| description=org.apache.tools.ant.types.Description | |||
| dirset=org.apache.tools.ant.types.DirSet | |||
| filelist=org.apache.tools.ant.types.FileList | |||
| fileset=org.apache.tools.ant.types.FileSet | |||
| filterchain=org.apache.tools.ant.types.FilterChain | |||
| filterreader=org.apache.tools.ant.types.AntFilterReader | |||
| filterset=org.apache.tools.ant.types.FilterSet | |||
| @@ -20,19 +16,15 @@ compositemapper=org.apache.tools.ant.util.CompositeMapper | |||
| chainedmapper=org.apache.tools.ant.util.ChainedMapper | |||
| filtermapper=org.apache.tools.ant.types.mappers.FilterMapper | |||
| path=org.apache.tools.ant.types.Path | |||
| patternset=org.apache.tools.ant.types.PatternSet | |||
| regexp=org.apache.tools.ant.types.RegularExpression | |||
| substitution=org.apache.tools.ant.types.Substitution | |||
| xmlcatalog=org.apache.tools.ant.types.XMLCatalog | |||
| extensionSet=org.apache.tools.ant.taskdefs.optional.extension.ExtensionSet | |||
| extension=org.apache.tools.ant.taskdefs.optional.extension.ExtensionAdapter | |||
| libfileset=org.apache.tools.ant.taskdefs.optional.extension.LibFileSet | |||
| selector=org.apache.tools.ant.types.selectors.SelectSelector | |||
| signedselector=org.apache.tools.ant.types.selectors.SignedSelector | |||
| zipfileset=org.apache.tools.ant.types.ZipFileSet | |||
| scriptfilter=org.apache.tools.ant.types.optional.ScriptFilter | |||
| propertyset=org.apache.tools.ant.types.PropertySet | |||
| assertions=org.apache.tools.ant.types.Assertions | |||
| concatfilter=org.apache.tools.ant.filters.ConcatFilter | |||
| issigned=org.apache.tools.ant.taskdefs.condition.IsSigned | |||
| @@ -45,3 +37,28 @@ xor=org.apache.tools.ant.taskdefs.condition.Xor | |||
| parsersupports=org.apache.tools.ant.taskdefs.condition.ParserSupports | |||
| scriptmapper=org.apache.tools.ant.types.optional.ScriptMapper | |||
| isfailure=org.apache.tools.ant.taskdefs.condition.IsFailure | |||
| #ResourceCollections: | |||
| dirset=org.apache.tools.ant.types.DirSet | |||
| filelist=org.apache.tools.ant.types.FileList | |||
| fileset=org.apache.tools.ant.types.FileSet | |||
| path=org.apache.tools.ant.types.Path | |||
| propertyset=org.apache.tools.ant.types.PropertySet | |||
| zipfileset=org.apache.tools.ant.types.ZipFileSet | |||
| classfileset=org.apache.tools.ant.types.optional.depend.ClassfileSet | |||
| libfileset=org.apache.tools.ant.taskdefs.optional.extension.LibFileSet | |||
| files=org.apache.tools.ant.types.resources.Files | |||
| restrict=org.apache.tools.ant.types.resources.Restrict | |||
| union=org.apache.tools.ant.types.resources.Union | |||
| difference=org.apache.tools.ant.types.resources.Difference | |||
| intersect=org.apache.tools.ant.types.resources.Intersect | |||
| sort=org.apache.tools.ant.types.resources.Sort | |||
| resources=org.apache.tools.ant.types.resources.Resources | |||
| #Resources (single-element ResourceCollections): | |||
| resource=org.apache.tools.ant.types.Resource | |||
| file=org.apache.tools.ant.types.resources.FileResource | |||
| url=org.apache.tools.ant.types.resources.URLResource | |||
| string=org.apache.tools.ant.types.resources.StringResource | |||
| zipentry=org.apache.tools.ant.types.resources.ZipResource | |||
| propertyresource=org.apache.tools.ant.types.resources.PropertyResource | |||
| @@ -0,0 +1,223 @@ | |||
| /* | |||
| * Copyright 2005 The Apache Software Foundation | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * | |||
| */ | |||
| package org.apache.tools.ant.types.resources; | |||
| import java.io.File; | |||
| import java.util.List; | |||
| import java.util.Stack; | |||
| import java.util.HashSet; | |||
| import java.util.Iterator; | |||
| import java.util.ArrayList; | |||
| import java.util.Hashtable; | |||
| import java.util.Collection; | |||
| import java.util.Collections; | |||
| import java.util.NoSuchElementException; | |||
| import java.util.ConcurrentModificationException; | |||
| import org.apache.tools.ant.Project; | |||
| import org.apache.tools.ant.BuildException; | |||
| import org.apache.tools.ant.types.DataType; | |||
| import org.apache.tools.ant.types.Resource; | |||
| import org.apache.tools.ant.types.ResourceCollection; | |||
| /** | |||
| * Base class for ResourceCollections that nest multiple ResourceCollections. | |||
| * @since Ant 1.7 | |||
| */ | |||
| public abstract class BaseResourceCollectionContainer | |||
| extends DataType implements ResourceCollection, Cloneable { | |||
| private List rc = new ArrayList(); | |||
| private Collection coll = null; | |||
| /** | |||
| * Add a ResourceCollection to the container. | |||
| * @param c the ResourceCollection to add. | |||
| * @throws BuildException on error. | |||
| */ | |||
| public synchronized void add(ResourceCollection c) throws BuildException { | |||
| if (isReference()) { | |||
| throw noChildrenAllowed(); | |||
| } | |||
| if (c == null) { | |||
| return; | |||
| } | |||
| rc.add(c); | |||
| FailFast.invalidate(this); | |||
| coll = null; | |||
| setChecked(false); | |||
| } | |||
| /** | |||
| * Add the Collection of ResourceCollections to the container. | |||
| * @param c the Collection whose elements to add. | |||
| * @throws BuildException on error. | |||
| */ | |||
| public synchronized void addAll(Collection c) throws BuildException { | |||
| if (isReference()) { | |||
| throw noChildrenAllowed(); | |||
| } | |||
| try { | |||
| for (Iterator i = c.iterator(); i.hasNext();) { | |||
| add((ResourceCollection) i.next()); | |||
| } | |||
| } catch (ClassCastException e) { | |||
| throw new BuildException(e); | |||
| } | |||
| } | |||
| /** | |||
| * Fulfill the ResourceCollection contract. The Iterator returned | |||
| * will throw ConcurrentModificationExceptions if ResourceCollections | |||
| * are added to this container while the Iterator is in use. | |||
| * @return a "fail-fast" Iterator. | |||
| */ | |||
| public synchronized final Iterator iterator() { | |||
| if (isReference()) { | |||
| return ((BaseResourceCollectionContainer) getCheckedRef()).iterator(); | |||
| } | |||
| dieOnCircularReference(); | |||
| cacheCollection(); | |||
| return new FailFast(this, coll.iterator()); | |||
| } | |||
| /** | |||
| * Fulfill the ResourceCollection contract. | |||
| * @return number of elements as int. | |||
| */ | |||
| public synchronized int size() { | |||
| if (isReference()) { | |||
| return ((BaseResourceCollectionContainer) getCheckedRef()).size(); | |||
| } | |||
| dieOnCircularReference(); | |||
| cacheCollection(); | |||
| return coll.size(); | |||
| } | |||
| /** | |||
| * Fulfill the ResourceCollection contract. | |||
| * @return whether this is a filesystem-only resource collection. | |||
| */ | |||
| public synchronized boolean isFilesystemOnly() { | |||
| if (isReference()) { | |||
| return ((BaseResourceCollectionContainer) getCheckedRef()).isFilesystemOnly(); | |||
| } | |||
| dieOnCircularReference(); | |||
| //first the easy way, if all children are filesystem-only, return true: | |||
| boolean goEarly = true; | |||
| for (Iterator i = rc.iterator(); goEarly && i.hasNext();) { | |||
| goEarly &= ((ResourceCollection) i.next()).isFilesystemOnly(); | |||
| } | |||
| if (goEarly) { | |||
| return true; | |||
| } | |||
| /* now check each Resource in case the child only | |||
| lets through files from any children IT may have: */ | |||
| cacheCollection(); | |||
| for (Iterator i = coll.iterator(); i.hasNext();) { | |||
| if (!(i.next() instanceof FileResource)) { | |||
| return false; | |||
| } | |||
| } | |||
| return true; | |||
| } | |||
| /** | |||
| * Overrides the version of DataType to recurse on all DataType | |||
| * child elements that may have been added. | |||
| * @param stk the stack of data types to use (recursively). | |||
| * @param p the project to use to dereference the references. | |||
| * @throws BuildException on error. | |||
| */ | |||
| protected void dieOnCircularReference(Stack stk, Project p) | |||
| throws BuildException { | |||
| if (isChecked()) { | |||
| return; | |||
| } | |||
| if (isReference()) { | |||
| super.dieOnCircularReference(stk, p); | |||
| } else { | |||
| for (Iterator i = rc.iterator(); i.hasNext();) { | |||
| Object o = i.next(); | |||
| if (o instanceof DataType) { | |||
| stk.push(o); | |||
| invokeCircularReferenceCheck((DataType) o, stk, p); | |||
| stk.pop(); | |||
| } | |||
| } | |||
| setChecked(true); | |||
| } | |||
| } | |||
| /** | |||
| * Get the nested ResourceCollections. | |||
| * @return List. | |||
| */ | |||
| protected synchronized final List getResourceCollections() { | |||
| dieOnCircularReference(); | |||
| return Collections.unmodifiableList(rc); | |||
| } | |||
| /** | |||
| * Template method for subclasses to return a Collection object of Resources. | |||
| * @return Collection. | |||
| */ | |||
| protected abstract Collection getCollection(); | |||
| /** | |||
| * Implement clone. The set of nested resource | |||
| * collections is shallowly cloned. | |||
| * @return a cloned instance. | |||
| */ | |||
| public Object clone() { | |||
| try { | |||
| BaseResourceCollectionContainer c | |||
| = (BaseResourceCollectionContainer) super.clone(); | |||
| c.rc = new ArrayList(rc); | |||
| c.coll = null; | |||
| return c; | |||
| } catch (CloneNotSupportedException e) { | |||
| throw new BuildException(e); | |||
| } | |||
| } | |||
| /** | |||
| * Format this BaseResourceCollectionContainer as a String. | |||
| * @return a descriptive <code>String</code>. | |||
| */ | |||
| public String toString() { | |||
| if (isReference()) { | |||
| return getCheckedRef().toString(); | |||
| } | |||
| cacheCollection(); | |||
| if (coll.size() == 0) { | |||
| return ""; | |||
| } | |||
| StringBuffer sb = new StringBuffer(); | |||
| for (Iterator i = coll.iterator(); i.hasNext();) { | |||
| if (sb.length() > 0) { | |||
| sb.append(File.pathSeparatorChar); | |||
| } | |||
| sb.append(i.next()); | |||
| } | |||
| return sb.toString(); | |||
| } | |||
| private synchronized void cacheCollection() { | |||
| coll = (coll == null) ? getCollection() : coll; | |||
| } | |||
| } | |||
| @@ -0,0 +1,67 @@ | |||
| /* | |||
| * Copyright 2005 The Apache Software Foundation | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * | |||
| */ | |||
| package org.apache.tools.ant.types.resources; | |||
| import java.util.List; | |||
| import java.util.HashSet; | |||
| import java.util.Iterator; | |||
| import java.util.ArrayList; | |||
| import java.util.Collection; | |||
| import org.apache.tools.ant.Project; | |||
| import org.apache.tools.ant.BuildException; | |||
| import org.apache.tools.ant.types.ResourceCollection; | |||
| /** | |||
| * ResourceCollection representing the difference between | |||
| * two or more nested ResourceCollections. | |||
| * @since Ant 1.7 | |||
| */ | |||
| public class Difference extends BaseResourceCollectionContainer { | |||
| /** | |||
| * Calculate the difference of the nested ResourceCollections. | |||
| * @return a Collection of Resources. | |||
| */ | |||
| protected Collection getCollection() { | |||
| List rc = getResourceCollections(); | |||
| int size = rc.size(); | |||
| if (size < 2) { | |||
| throw new BuildException("The difference of " + size | |||
| + " resource collection" + ((size == 1) ? "" : "s") | |||
| + " is undefined."); | |||
| } | |||
| HashSet hs = new HashSet(); | |||
| ArrayList al = new ArrayList(); | |||
| for (Iterator rcIter = rc.iterator(); rcIter.hasNext();) { | |||
| for (Iterator r = nextRC(rcIter).iterator(); r.hasNext();) { | |||
| Object next = r.next(); | |||
| if (hs.add(next)) { | |||
| al.add(next); | |||
| } else { | |||
| al.remove(next); | |||
| } | |||
| } | |||
| } | |||
| return al; | |||
| } | |||
| private static ResourceCollection nextRC(Iterator i) { | |||
| return (ResourceCollection) i.next(); | |||
| } | |||
| } | |||
| @@ -0,0 +1,132 @@ | |||
| /* | |||
| * Copyright 2005 The Apache Software Foundation | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * | |||
| */ | |||
| package org.apache.tools.ant.types.resources; | |||
| import java.util.Set; | |||
| import java.util.HashSet; | |||
| import java.util.Iterator; | |||
| import java.util.WeakHashMap; | |||
| import java.util.NoSuchElementException; | |||
| import java.util.ConcurrentModificationException; | |||
| /** | |||
| * Helper class for ResourceCollections to return Iterators | |||
| * that fail on changes to the object. | |||
| * @since Ant 1.7 | |||
| */ | |||
| /*package-private*/ class FailFast implements Iterator { | |||
| private static final WeakHashMap map = new WeakHashMap(); | |||
| /** | |||
| * Invalidate any in-use Iterators from the specified Object. | |||
| * @param o the parent Object. | |||
| */ | |||
| static synchronized void invalidate(Object o) { | |||
| Set s = (Set) (map.get(o)); | |||
| if (s != null) { | |||
| s.clear(); | |||
| } | |||
| } | |||
| private static synchronized void add(FailFast f) { | |||
| Set s = (Set) (map.get(f.parent)); | |||
| if (s == null) { | |||
| s = new HashSet(); | |||
| map.put(f.parent, s); | |||
| } | |||
| s.add(f); | |||
| } | |||
| private static synchronized void remove(FailFast f) { | |||
| Set s = (Set) (map.get(f.parent)); | |||
| if (s != null) { | |||
| s.remove(f); | |||
| } | |||
| } | |||
| private static synchronized void failFast(FailFast f) { | |||
| Set s = (Set) (map.get(f.parent)); | |||
| if (!s.contains(f)) { | |||
| throw new ConcurrentModificationException(); | |||
| } | |||
| } | |||
| private Object parent; | |||
| private Iterator wrapped; | |||
| /** | |||
| * Construct a new FailFast Iterator wrapping the specified Iterator | |||
| * and dependent upon the specified parent Object. | |||
| * @param o the parent Object. | |||
| * @param i the wrapped Iterator. | |||
| */ | |||
| FailFast(Object o, Iterator i) { | |||
| if (o == null) { | |||
| throw new IllegalArgumentException("parent object is null"); | |||
| } | |||
| if (i == null) { | |||
| throw new IllegalArgumentException("cannot wrap null iterator"); | |||
| } | |||
| parent = o; | |||
| if (i.hasNext()) { | |||
| wrapped = i; | |||
| add(this); | |||
| } | |||
| } | |||
| /** | |||
| * Fulfill the Iterator contract. | |||
| * @return true if there are more elements. | |||
| */ | |||
| public boolean hasNext() { | |||
| if (wrapped == null) { | |||
| return false; | |||
| } | |||
| failFast(this); | |||
| return wrapped.hasNext(); | |||
| } | |||
| /** | |||
| * Fulfill the Iterator contract. | |||
| * @return the next element. | |||
| * @throws NoSuchElementException if no more elements. | |||
| */ | |||
| public Object next() { | |||
| if (wrapped == null || !wrapped.hasNext()) { | |||
| throw new NoSuchElementException(); | |||
| } | |||
| failFast(this); | |||
| try { | |||
| return wrapped.next(); | |||
| } finally { | |||
| if (!wrapped.hasNext()) { | |||
| wrapped = null; | |||
| remove(this); | |||
| } | |||
| } | |||
| } | |||
| /** | |||
| * Fulfill the Iterator contract. | |||
| * @throws UnsupportedOperationException always. | |||
| */ | |||
| public void remove() { | |||
| throw new UnsupportedOperationException(); | |||
| } | |||
| } | |||
| @@ -0,0 +1,300 @@ | |||
| /* | |||
| * Copyright 2005 The Apache Software Foundation | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * | |||
| */ | |||
| package org.apache.tools.ant.types.resources; | |||
| import java.io.File; | |||
| import java.io.IOException; | |||
| import java.io.InputStream; | |||
| import java.io.OutputStream; | |||
| import java.io.FileInputStream; | |||
| import java.io.FileOutputStream; | |||
| import org.apache.tools.ant.Project; | |||
| import org.apache.tools.ant.BuildException; | |||
| import org.apache.tools.ant.util.FileUtils; | |||
| import org.apache.tools.ant.types.Resource; | |||
| import org.apache.tools.ant.types.Reference; | |||
| /** | |||
| * A Resource representation of a File. | |||
| * @since Ant 1.7 | |||
| */ | |||
| public class FileResource extends Resource implements Touchable { | |||
| private static final FileUtils FILE_UTILS = FileUtils.getFileUtils(); | |||
| private static final int NULL_FILE | |||
| = Resource.getMagicNumber("null file".getBytes()); | |||
| private File file; | |||
| private File base; | |||
| /** | |||
| * Default constructor. | |||
| */ | |||
| public FileResource() { | |||
| } | |||
| /** | |||
| * Construct a new FileResource using the specified base File and relative name. | |||
| * @param b the base File (directory). | |||
| * @param name the relative filename. | |||
| */ | |||
| public FileResource(File b, String name) { | |||
| setFile(FILE_UTILS.resolveFile(b, name)); | |||
| setBase(b); | |||
| } | |||
| /** | |||
| * Construct a new FileResource from a File. | |||
| * @param f the File represented. | |||
| */ | |||
| public FileResource(File f) { | |||
| setFile(f); | |||
| } | |||
| /** | |||
| * Constructor for Ant attribute introspection. | |||
| * @param p the Project against which to resolve <code>s</code>. | |||
| * @param s the absolute or Project-relative filename as a String. | |||
| * @see org.apache.tools.ant.IntrospectionHelper | |||
| */ | |||
| public FileResource(Project p, String s) { | |||
| this(p.resolveFile(s)); | |||
| setProject(p); | |||
| } | |||
| /** | |||
| * Set the File for this FileResource. | |||
| * @param f the File to be represented. | |||
| */ | |||
| public void setFile(File f) { | |||
| checkAttributesAllowed(); | |||
| file = f; | |||
| } | |||
| /** | |||
| * Get the file represented by this FileResource. | |||
| * @return the File. | |||
| */ | |||
| public File getFile() { | |||
| return isReference() ? ((FileResource) getCheckedRef()).getFile() : file; | |||
| } | |||
| /** | |||
| * Set the base File for this FileResource. | |||
| * @param b the base File. | |||
| */ | |||
| public void setBase(File b) { | |||
| checkAttributesAllowed(); | |||
| base = b; | |||
| } | |||
| /** | |||
| * Return the base to which the name is relative. | |||
| * @return the base File. | |||
| */ | |||
| public File getBase() { | |||
| return isReference() | |||
| ? ((FileResource) getCheckedRef()).getBase() : base; | |||
| } | |||
| /** | |||
| * Overrides the super version. | |||
| * @param r the Reference to set. | |||
| */ | |||
| public void setRefid(Reference r) { | |||
| if (file != null || base != null) { | |||
| throw tooManyAttributes(); | |||
| } | |||
| super.setRefid(r); | |||
| } | |||
| /** | |||
| * Get the name of this FileResource relative to its base, if any. | |||
| * @return the name of this resource. | |||
| */ | |||
| public String getName() { | |||
| if (isReference()) { | |||
| return ((Resource) getCheckedRef()).getName(); | |||
| } | |||
| File b = getBase(); | |||
| return b == null ? getNotNullFile().getAbsolutePath() | |||
| : FILE_UTILS.removeLeadingPath(b, getNotNullFile()); | |||
| } | |||
| /** | |||
| * Learn whether this file exists. | |||
| * @return true if this resource exists. | |||
| */ | |||
| public boolean isExists() { | |||
| return isReference() ? ((Resource) getCheckedRef()).isExists() | |||
| : getNotNullFile().exists(); | |||
| } | |||
| /** | |||
| * Get the modification time in milliseconds since 01.01.1970 . | |||
| * @return 0 if the resource does not exist. | |||
| */ | |||
| public long getLastModified() { | |||
| return isReference() | |||
| ? ((Resource) getCheckedRef()).getLastModified() | |||
| : getNotNullFile().lastModified(); | |||
| } | |||
| /** | |||
| * Learn whether the resource is a directory. | |||
| * @return boolean flag indicating if the resource is a directory. | |||
| */ | |||
| public boolean isDirectory() { | |||
| return isReference() ? ((Resource) getCheckedRef()).isDirectory() | |||
| : getNotNullFile().isDirectory(); | |||
| } | |||
| /** | |||
| * Get the size of this Resource. | |||
| * @return the size, as a long, 0 if the Resource does not exist. | |||
| */ | |||
| public long getSize() { | |||
| return isReference() ? ((Resource) getCheckedRef()).getSize() | |||
| : getNotNullFile().length(); | |||
| } | |||
| /** | |||
| * Return an InputStream for reading the contents of this Resource. | |||
| * @return an InputStream object. | |||
| * @throws IOException if an error occurs. | |||
| */ | |||
| public InputStream getInputStream() throws IOException { | |||
| return isReference() | |||
| ? ((Resource) getCheckedRef()).getInputStream() | |||
| : new FileInputStream(getNotNullFile()); | |||
| } | |||
| /** | |||
| * Get an OutputStream for the Resource. | |||
| * @return an OutputStream to which content can be written. | |||
| * @throws IOException if unable to provide the content of this | |||
| * Resource as a stream. | |||
| * @throws UnsupportedOperationException if OutputStreams are not | |||
| * supported for this Resource type. | |||
| */ | |||
| public OutputStream getOutputStream() throws IOException { | |||
| if (isReference()) { | |||
| return ((Resource) getCheckedRef()).getOutputStream(); | |||
| } | |||
| File f = getNotNullFile(); | |||
| if (f.exists()) { | |||
| if (f.isFile()) { | |||
| f.delete(); | |||
| } | |||
| } else { | |||
| File p = f.getParentFile(); | |||
| if (p != null && !(p.exists())) { | |||
| p.mkdirs(); | |||
| } | |||
| } | |||
| return new FileOutputStream(f); | |||
| } | |||
| /** | |||
| * Compare this FileResource to another Resource. | |||
| * @param another the other Resource against which to compare. | |||
| * @return a negative integer, zero, or a positive integer as this FileResource | |||
| * is less than, equal to, or greater than the specified Resource. | |||
| */ | |||
| public int compareTo(Object another) { | |||
| if (isReference()) { | |||
| return ((Comparable) getCheckedRef()).compareTo(another); | |||
| } | |||
| return this.equals(another) ? 0 : super.compareTo(another); | |||
| } | |||
| /** | |||
| * Compare another Object to this FileResource for equality. | |||
| * @param another the other Object to compare. | |||
| * @return true if another is a FileResource representing the same file. | |||
| */ | |||
| public boolean equals(Object another) { | |||
| if (this == another) { | |||
| return true; | |||
| } | |||
| if (isReference()) { | |||
| return getCheckedRef().equals(another); | |||
| } | |||
| if (!(another.getClass().equals(getClass()))) { | |||
| return false; | |||
| } | |||
| FileResource otherfr = (FileResource) another; | |||
| return getFile() == null | |||
| ? otherfr.getFile() == null | |||
| : getFile().equals(otherfr.getFile()); | |||
| } | |||
| /** | |||
| * Get the hash code for this Resource. | |||
| * @return hash code as int. | |||
| */ | |||
| public int hashCode() { | |||
| if (isReference()) { | |||
| return getCheckedRef().hashCode(); | |||
| } | |||
| return MAGIC * (getFile() == null ? NULL_FILE : getFile().hashCode()); | |||
| } | |||
| /** | |||
| * Get the string representation of this Resource. | |||
| * @return this FileResource formatted as a String. | |||
| */ | |||
| public String toString() { | |||
| return isReference() ? getCheckedRef().toString() | |||
| : FILE_UTILS.normalize(file.getAbsolutePath()).getAbsolutePath(); | |||
| } | |||
| /** | |||
| * Fulfill the ResourceCollection contract. | |||
| * @return whether this Resource is a FileResource. | |||
| */ | |||
| public boolean isFilesystemOnly() { | |||
| return !isReference() | |||
| || ((FileResource) getCheckedRef()).isFilesystemOnly(); | |||
| } | |||
| /** | |||
| * Implement the Touchable interface. | |||
| * @param modTime new last modification time. | |||
| */ | |||
| public void touch(long modTime) { | |||
| if (isReference()) { | |||
| ((FileResource) getCheckedRef()).touch(modTime); | |||
| return; | |||
| } | |||
| getNotNullFile().setLastModified(modTime); | |||
| } | |||
| /** | |||
| * Get the file represented by this FileResource, ensuring it is not null. | |||
| * @return the not-null File. | |||
| * @throws BuildException if file is null. | |||
| */ | |||
| protected File getNotNullFile() { | |||
| if (getFile() == null) { | |||
| throw new BuildException("file attribute is null!"); | |||
| } | |||
| return getFile(); | |||
| } | |||
| } | |||
| @@ -0,0 +1,108 @@ | |||
| /* | |||
| * Copyright 2005 The Apache Software Foundation | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * | |||
| */ | |||
| package org.apache.tools.ant.types.resources; | |||
| import java.io.File; | |||
| import java.util.Arrays; | |||
| import java.util.Iterator; | |||
| import java.util.ArrayList; | |||
| import java.util.NoSuchElementException; | |||
| /** | |||
| * Iterator of FileResources from filenames. | |||
| * @since Ant 1.7 | |||
| */ | |||
| public class FileResourceIterator implements Iterator { | |||
| private File basedir; | |||
| private String[] files; | |||
| private int pos = 0; | |||
| /** | |||
| * Construct a new FileResourceIterator. | |||
| */ | |||
| public FileResourceIterator() { | |||
| } | |||
| /** | |||
| * Construct a new FileResourceIterator relative to the specified | |||
| * base directory. | |||
| * @param f the base directory of this instance. | |||
| */ | |||
| public FileResourceIterator(File f) { | |||
| basedir = f; | |||
| } | |||
| /** | |||
| * Construct a new FileResourceIterator over the specified filenames, | |||
| * relative to the specified base directory. | |||
| * @param f the base directory of this instance. | |||
| * @param files the String[] of filenames. | |||
| */ | |||
| public FileResourceIterator(File f, String[] s) { | |||
| this(f); | |||
| addFiles(s); | |||
| } | |||
| /** | |||
| * Add an array of filenames to this FileResourceIterator. | |||
| * @param s the filenames to add. | |||
| */ | |||
| public void addFiles(String[] s) { | |||
| int start = (files == null) ? 0 : files.length; | |||
| String[] newfiles = new String[start + s.length]; | |||
| if (start > 0) { | |||
| System.arraycopy(files, 0, newfiles, 0, start); | |||
| } | |||
| files = newfiles; | |||
| System.arraycopy(s, 0, files, start, s.length); | |||
| } | |||
| /** | |||
| * Find out whether this FileResourceIterator has more elements. | |||
| * @return whether there are more Resources to iterate over. | |||
| */ | |||
| public boolean hasNext() { | |||
| return pos < files.length; | |||
| } | |||
| /** | |||
| * Get the next element from this FileResourceIterator. | |||
| * @return the next Object. | |||
| */ | |||
| public Object next() { | |||
| return nextResource(); | |||
| } | |||
| /** | |||
| * Not implemented. | |||
| */ | |||
| public void remove() { | |||
| throw new UnsupportedOperationException(); | |||
| } | |||
| /** | |||
| * Convenience method to return the next resource. | |||
| * @return the next File. | |||
| */ | |||
| public FileResource nextResource() { | |||
| if (!hasNext()) { | |||
| throw new NoSuchElementException(); | |||
| } | |||
| return new FileResource(basedir, files[pos++]); | |||
| } | |||
| } | |||
| @@ -0,0 +1,503 @@ | |||
| /* | |||
| * Copyright 2005 The Apache Software Foundation | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * | |||
| */ | |||
| package org.apache.tools.ant.types.resources; | |||
| import java.io.File; | |||
| import java.util.Stack; | |||
| import java.util.Arrays; | |||
| import java.util.Vector; | |||
| import java.util.Iterator; | |||
| import java.util.ArrayList; | |||
| import java.util.Collections; | |||
| import java.util.Enumeration; | |||
| import org.apache.tools.ant.Project; | |||
| import org.apache.tools.ant.BuildException; | |||
| import org.apache.tools.ant.DirectoryScanner; | |||
| import org.apache.tools.ant.types.Reference; | |||
| import org.apache.tools.ant.types.PatternSet; | |||
| import org.apache.tools.ant.types.ResourceCollection; | |||
| import org.apache.tools.ant.types.selectors.FileSelector; | |||
| import org.apache.tools.ant.types.selectors.AbstractSelectorContainer; | |||
| /** | |||
| * ResourceCollection implementation; like AbstractFileSet with absolute paths. | |||
| * @since Ant 1.7 | |||
| */ | |||
| public class Files extends AbstractSelectorContainer | |||
| implements Cloneable, ResourceCollection { | |||
| private static final Iterator EMPTY_ITERATOR | |||
| = Collections.EMPTY_SET.iterator(); | |||
| private PatternSet defaultPatterns = new PatternSet(); | |||
| private Vector additionalPatterns = new Vector(); | |||
| private Vector selectors = new Vector(); | |||
| private boolean useDefaultExcludes = true; | |||
| private boolean caseSensitive = true; | |||
| private boolean followSymlinks = true; | |||
| /* cached DirectoryScanner instance */ | |||
| private DirectoryScanner ds = null; | |||
| /** | |||
| * Construct a new <code>Files</code> collection. | |||
| */ | |||
| public Files() { | |||
| super(); | |||
| } | |||
| /** | |||
| * Construct a new <code>Files</code> collection, shallowly cloned | |||
| * from the specified <code>Files</code>. | |||
| * @param f the <code>Files</code> to use as a template. | |||
| */ | |||
| protected Files(Files f) { | |||
| this.defaultPatterns = f.defaultPatterns; | |||
| this.additionalPatterns = f.additionalPatterns; | |||
| this.selectors = f.selectors; | |||
| this.useDefaultExcludes = f.useDefaultExcludes; | |||
| this.caseSensitive = f.caseSensitive; | |||
| this.followSymlinks = f.followSymlinks; | |||
| this.ds = f.ds; | |||
| setProject(f.getProject()); | |||
| } | |||
| /** | |||
| * Make this instance in effect a reference to another instance. | |||
| * | |||
| * <p>You must not set another attribute or nest elements inside | |||
| * this element if you make it a reference.</p> | |||
| * @param r the <code>Reference</code> to use. | |||
| */ | |||
| public void setRefid(Reference r) throws BuildException { | |||
| if (hasPatterns(defaultPatterns)) { | |||
| throw tooManyAttributes(); | |||
| } | |||
| if (!additionalPatterns.isEmpty()) { | |||
| throw noChildrenAllowed(); | |||
| } | |||
| if (!selectors.isEmpty()) { | |||
| throw noChildrenAllowed(); | |||
| } | |||
| super.setRefid(r); | |||
| } | |||
| /** | |||
| * Create a nested patternset. | |||
| * @return <code>PatternSet</code>. | |||
| */ | |||
| public synchronized PatternSet createPatternSet() { | |||
| if (isReference()) { | |||
| throw noChildrenAllowed(); | |||
| } | |||
| PatternSet patterns = new PatternSet(); | |||
| additionalPatterns.addElement(patterns); | |||
| ds = null; | |||
| return patterns; | |||
| } | |||
| /** | |||
| * Add a name entry to the include list. | |||
| * @return <code>PatternSet.NameEntry</code>. | |||
| */ | |||
| public synchronized PatternSet.NameEntry createInclude() { | |||
| if (isReference()) { | |||
| throw noChildrenAllowed(); | |||
| } | |||
| ds = null; | |||
| return defaultPatterns.createInclude(); | |||
| } | |||
| /** | |||
| * Add a name entry to the include files list. | |||
| * @return <code>PatternSet.NameEntry</code>. | |||
| */ | |||
| public synchronized PatternSet.NameEntry createIncludesFile() { | |||
| if (isReference()) { | |||
| throw noChildrenAllowed(); | |||
| } | |||
| ds = null; | |||
| return defaultPatterns.createIncludesFile(); | |||
| } | |||
| /** | |||
| * Add a name entry to the exclude list. | |||
| * @return <code>PatternSet.NameEntry</code>. | |||
| */ | |||
| public synchronized PatternSet.NameEntry createExclude() { | |||
| if (isReference()) { | |||
| throw noChildrenAllowed(); | |||
| } | |||
| ds = null; | |||
| return defaultPatterns.createExclude(); | |||
| } | |||
| /** | |||
| * Add a name entry to the excludes files list. | |||
| * @return <code>PatternSet.NameEntry</code>. | |||
| */ | |||
| public synchronized PatternSet.NameEntry createExcludesFile() { | |||
| if (isReference()) { | |||
| throw noChildrenAllowed(); | |||
| } | |||
| ds = null; | |||
| return defaultPatterns.createExcludesFile(); | |||
| } | |||
| /** | |||
| * Append <code>includes</code> to the current list of include | |||
| * patterns. | |||
| * | |||
| * <p>Patterns may be separated by a comma or a space.</p> | |||
| * | |||
| * @param includes the <code>String</code> containing the include patterns. | |||
| */ | |||
| public synchronized void setIncludes(String includes) { | |||
| checkAttributesAllowed(); | |||
| defaultPatterns.setIncludes(includes); | |||
| ds = null; | |||
| } | |||
| /** | |||
| * Append <code>includes</code> to the current list of include | |||
| * patterns. | |||
| * | |||
| * @param includes array containing the include patterns. | |||
| */ | |||
| public synchronized void appendIncludes(String[] includes) { | |||
| checkAttributesAllowed(); | |||
| if (includes != null) { | |||
| for (int i = 0; i < includes.length; i++) { | |||
| defaultPatterns.createInclude().setName(includes[i]); | |||
| } | |||
| ds = null; | |||
| } | |||
| } | |||
| /** | |||
| * Append <code>excludes</code> to the current list of exclude | |||
| * patterns. | |||
| * | |||
| * <p>Patterns may be separated by a comma or a space.</p> | |||
| * | |||
| * @param excludes the <code>String</code> containing the exclude patterns. | |||
| */ | |||
| public synchronized void setExcludes(String excludes) { | |||
| checkAttributesAllowed(); | |||
| defaultPatterns.setExcludes(excludes); | |||
| ds = null; | |||
| } | |||
| /** | |||
| * Append <code>excludes</code> to the current list of include | |||
| * patterns. | |||
| * | |||
| * @param excludes array containing the exclude patterns. | |||
| */ | |||
| public synchronized void appendExcludes(String[] excludes) { | |||
| checkAttributesAllowed(); | |||
| if (excludes != null) { | |||
| for (int i = 0; i < excludes.length; i++) { | |||
| defaultPatterns.createExclude().setName(excludes[i]); | |||
| } | |||
| ds = null; | |||
| } | |||
| } | |||
| /** | |||
| * Set the <code>File</code> containing the includes patterns. | |||
| * | |||
| * @param incl <code>File</code> instance. | |||
| */ | |||
| public synchronized void setIncludesfile(File incl) throws BuildException { | |||
| checkAttributesAllowed(); | |||
| defaultPatterns.setIncludesfile(incl); | |||
| ds = null; | |||
| } | |||
| /** | |||
| * Set the <code>File</code> containing the excludes patterns. | |||
| * | |||
| * @param excl <code>File</code> instance. | |||
| */ | |||
| public synchronized void setExcludesfile(File excl) throws BuildException { | |||
| checkAttributesAllowed(); | |||
| defaultPatterns.setExcludesfile(excl); | |||
| ds = null; | |||
| } | |||
| /** | |||
| * Set whether default exclusions should be used or not. | |||
| * | |||
| * @param useDefaultExcludes <code>boolean</code>. | |||
| */ | |||
| public synchronized void setDefaultexcludes(boolean useDefaultExcludes) { | |||
| checkAttributesAllowed(); | |||
| this.useDefaultExcludes = useDefaultExcludes; | |||
| ds = null; | |||
| } | |||
| /** | |||
| * Get whether default exclusions should be used or not. | |||
| */ | |||
| public synchronized boolean getDefaultexcludes() { | |||
| return (isReference()) | |||
| ? getRef().getDefaultexcludes() : useDefaultExcludes; | |||
| } | |||
| /** | |||
| * Set case-sensitivity of the Files collection. | |||
| * | |||
| * @param caseSensitive <code>boolean</code>. | |||
| */ | |||
| public synchronized void setCaseSensitive(boolean caseSensitive) { | |||
| checkAttributesAllowed(); | |||
| this.caseSensitive = caseSensitive; | |||
| ds = null; | |||
| } | |||
| /** | |||
| * Find out if this Files collection is case-sensitive. | |||
| * | |||
| * @return <code>boolean</code> indicating whether the Files | |||
| * collection is case-sensitive. | |||
| */ | |||
| public synchronized boolean isCaseSensitive() { | |||
| return (isReference()) | |||
| ? getRef().isCaseSensitive() : caseSensitive; | |||
| } | |||
| /** | |||
| * Set whether or not symbolic links should be followed. | |||
| * | |||
| * @param followSymlinks whether or not symbolic links should be followed. | |||
| */ | |||
| public synchronized void setFollowSymlinks(boolean followSymlinks) { | |||
| checkAttributesAllowed(); | |||
| this.followSymlinks = followSymlinks; | |||
| ds = null; | |||
| } | |||
| /** | |||
| * Find out whether symbolic links should be followed. | |||
| * | |||
| * @return <code>boolean</code> indicating whether symbolic links | |||
| * should be followed. | |||
| */ | |||
| public synchronized boolean isFollowSymlinks() { | |||
| return (isReference()) | |||
| ? getRef().isFollowSymlinks() : followSymlinks; | |||
| } | |||
| /** | |||
| * Fulfill the ResourceCollection contract. | |||
| * @return an Iterator of Resources. | |||
| */ | |||
| public synchronized Iterator iterator() { | |||
| if (isReference()) { | |||
| return getRef().iterator(); | |||
| } | |||
| ensureDirectoryScannerSetup(); | |||
| ds.scan(); | |||
| int fct = ds.getIncludedFilesCount(); | |||
| int dct = ds.getIncludedDirsCount(); | |||
| if (fct + dct == 0) { | |||
| return EMPTY_ITERATOR; | |||
| } | |||
| FileResourceIterator result = new FileResourceIterator(); | |||
| if (fct > 0) { | |||
| result.addFiles(ds.getIncludedFiles()); | |||
| } | |||
| if (dct > 0) { | |||
| result.addFiles(ds.getIncludedDirectories()); | |||
| } | |||
| return result; | |||
| } | |||
| /** | |||
| * Fulfill the ResourceCollection contract. | |||
| * @return number of elements as int. | |||
| */ | |||
| public synchronized int size() { | |||
| if (isReference()) { | |||
| return getRef().size(); | |||
| } | |||
| ensureDirectoryScannerSetup(); | |||
| ds.scan(); | |||
| return ds.getIncludedFilesCount() + ds.getIncludedDirsCount(); | |||
| } | |||
| /** | |||
| * Find out whether this Files collection has patterns. | |||
| * | |||
| * @return whether any patterns are in this container. | |||
| */ | |||
| public synchronized boolean hasPatterns() { | |||
| if (isReference()) { | |||
| return getRef().hasPatterns(); | |||
| } | |||
| if (hasPatterns(defaultPatterns)) { | |||
| return true; | |||
| } | |||
| for (Iterator i = additionalPatterns.iterator(); i.hasNext();) { | |||
| if (hasPatterns((PatternSet) i.next())) { | |||
| return true; | |||
| } | |||
| } | |||
| return false; | |||
| } | |||
| /** | |||
| * Add a new selector into this container. | |||
| * | |||
| * @param selector the new <code>FileSelector</code> to add. | |||
| */ | |||
| public synchronized void appendSelector(FileSelector selector) { | |||
| if (isReference()) { | |||
| throw noChildrenAllowed(); | |||
| } | |||
| super.appendSelector(selector); | |||
| ds = null; | |||
| } | |||
| /** | |||
| * Format this Files collection as a String. | |||
| * @return a descriptive <code>String</code>. | |||
| */ | |||
| public String toString() { | |||
| if (isReference()) { | |||
| return getRef().toString(); | |||
| } | |||
| Iterator i = iterator(); | |||
| if (!i.hasNext()) { | |||
| return ""; | |||
| } | |||
| StringBuffer sb = new StringBuffer(); | |||
| while (i.hasNext()) { | |||
| if (sb.length() > 0) { | |||
| sb.append(File.pathSeparatorChar); | |||
| } | |||
| sb.append(i.next()); | |||
| } | |||
| return sb.toString(); | |||
| } | |||
| /** | |||
| * Create a deep clone of this instance, except for the nested selectors | |||
| * (the list of selectors is a shallow clone of this instance's list). | |||
| * @return a cloned Object. | |||
| */ | |||
| public synchronized Object clone() { | |||
| if (isReference()) { | |||
| return getRef().clone(); | |||
| } | |||
| try { | |||
| Files f = (Files) super.clone(); | |||
| f.defaultPatterns = (PatternSet) defaultPatterns.clone(); | |||
| f.additionalPatterns = new Vector(additionalPatterns.size()); | |||
| for (Iterator iter = additionalPatterns.iterator(); iter.hasNext();) { | |||
| PatternSet ps = (PatternSet) iter.next(); | |||
| f.additionalPatterns.add(ps.clone()); | |||
| } | |||
| f.selectors = new Vector(selectors); | |||
| return f; | |||
| } catch (CloneNotSupportedException e) { | |||
| throw new BuildException(e); | |||
| } | |||
| } | |||
| /** | |||
| * Get the merged include patterns for this Files collection. | |||
| * @param p Project instance. | |||
| * @return the include patterns of the default pattern set and all | |||
| * nested patternsets. | |||
| */ | |||
| public String[] mergeIncludes(Project p) { | |||
| return mergePatterns(p).getIncludePatterns(p); | |||
| } | |||
| /** | |||
| * Get the merged exclude patterns for this Files collection. | |||
| * @param p Project instance. | |||
| * @return the exclude patterns of the default pattern set and all | |||
| * nested patternsets. | |||
| */ | |||
| public String[] mergeExcludes(Project p) { | |||
| return mergePatterns(p).getExcludePatterns(p); | |||
| } | |||
| /** | |||
| * Get the merged patterns for this Files collection. | |||
| * @param p Project instance. | |||
| * @return the default patternset merged with the additional sets | |||
| * in a new PatternSet instance. | |||
| */ | |||
| public synchronized PatternSet mergePatterns(Project p) { | |||
| if (isReference()) { | |||
| return getRef().mergePatterns(p); | |||
| } | |||
| PatternSet ps = new PatternSet(); | |||
| ps.append(defaultPatterns, p); | |||
| final int count = additionalPatterns.size(); | |||
| for (int i = 0; i < count; i++) { | |||
| Object o = additionalPatterns.elementAt(i); | |||
| ps.append((PatternSet) o, p); | |||
| } | |||
| return ps; | |||
| } | |||
| /** | |||
| * Always returns true. | |||
| * @return true indicating that all elements of a Files collection | |||
| * will be FileResources. | |||
| */ | |||
| public boolean isFilesystemOnly() { | |||
| return true; | |||
| } | |||
| /** | |||
| * Perform the check for circular references and return the | |||
| * referenced Files collection. | |||
| * @return <code>FileCollection</code>. | |||
| */ | |||
| protected Files getRef() { | |||
| return (Files) getCheckedRef(); | |||
| } | |||
| private synchronized void ensureDirectoryScannerSetup() { | |||
| if (ds == null) { | |||
| ds = new DirectoryScanner(); | |||
| PatternSet ps = mergePatterns(getProject()); | |||
| ds.setIncludes(ps.getIncludePatterns(getProject())); | |||
| ds.setExcludes(ps.getExcludePatterns(getProject())); | |||
| ds.setSelectors(getSelectors(getProject())); | |||
| if (useDefaultExcludes) { | |||
| ds.addDefaultExcludes(); | |||
| } | |||
| ds.setCaseSensitive(caseSensitive); | |||
| ds.setFollowSymlinks(followSymlinks); | |||
| } | |||
| } | |||
| private boolean hasPatterns(PatternSet ps) { | |||
| return ps.getIncludePatterns(getProject()).length > 0 | |||
| || ps.getExcludePatterns(getProject()).length > 0; | |||
| } | |||
| } | |||
| @@ -0,0 +1,44 @@ | |||
| /* | |||
| * Copyright 2005 The Apache Software Foundation | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * | |||
| */ | |||
| package org.apache.tools.ant.types.resources; | |||
| import java.io.IOException; | |||
| /** | |||
| * Exception thrown when an attempt is made to get an OutputStream | |||
| * from an immutable Resource. | |||
| * @since Ant 1.7 | |||
| */ | |||
| public class ImmutableResourceException extends IOException { | |||
| /** | |||
| * Default constructor. | |||
| */ | |||
| public ImmutableResourceException() { | |||
| super(); | |||
| } | |||
| /** | |||
| * Construct a new ImmutableResourceException with the specified message. | |||
| * @param s the message String. | |||
| */ | |||
| public ImmutableResourceException(String s) { | |||
| super(s); | |||
| } | |||
| } | |||
| @@ -0,0 +1,62 @@ | |||
| /* | |||
| * Copyright 2005 The Apache Software Foundation | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * | |||
| */ | |||
| package org.apache.tools.ant.types.resources; | |||
| import java.util.List; | |||
| import java.util.Iterator; | |||
| import java.util.ArrayList; | |||
| import java.util.Collection; | |||
| import org.apache.tools.ant.BuildException; | |||
| import org.apache.tools.ant.types.ResourceCollection; | |||
| /** | |||
| * ResourceCollection representing the intersection | |||
| * of multiple nested ResourceCollections. | |||
| * @since Ant 1.7 | |||
| */ | |||
| public class Intersect extends BaseResourceCollectionContainer { | |||
| /** | |||
| * Calculate the intersection of the nested ResourceCollections. | |||
| * @return a Collection of Resources. | |||
| */ | |||
| protected Collection getCollection() { | |||
| List rcs = getResourceCollections(); | |||
| int size = rcs.size(); | |||
| if (size < 2) { | |||
| throw new BuildException("The intersection of " + size | |||
| + " resource collection" + ((size == 1) ? "" : "s") | |||
| + " is undefined."); | |||
| } | |||
| ArrayList al = new ArrayList(); | |||
| Iterator rc = rcs.iterator(); | |||
| al.addAll(collect(rc.next())); | |||
| while (rc.hasNext()) { | |||
| al.retainAll(collect(rc.next())); | |||
| } | |||
| return al; | |||
| } | |||
| private ArrayList collect(Object o) { | |||
| ArrayList result = new ArrayList(); | |||
| for (Iterator i = ((ResourceCollection) o).iterator(); i.hasNext();) { | |||
| result.add(i.next()); | |||
| } | |||
| return result; | |||
| } | |||
| } | |||
| @@ -0,0 +1,133 @@ | |||
| /* | |||
| * Copyright 2005 The Apache Software Foundation | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * | |||
| */ | |||
| package org.apache.tools.ant.types.resources; | |||
| import java.io.IOException; | |||
| import java.io.InputStream; | |||
| import java.io.OutputStream; | |||
| import java.io.ByteArrayInputStream; | |||
| import org.apache.tools.ant.Project; | |||
| import org.apache.tools.ant.types.Resource; | |||
| import org.apache.tools.ant.util.PropertyOutputStream; | |||
| /** | |||
| * Exposes an Ant property as a Resource. | |||
| * @since Ant 1.7 | |||
| */ | |||
| public class PropertyResource extends Resource { | |||
| /** Magic number */ | |||
| private static final int PROPERTY_MAGIC | |||
| = Resource.getMagicNumber("PropertyResource".getBytes()); | |||
| private static final InputStream UNSET = new InputStream() { | |||
| public int read() { | |||
| return -1; | |||
| } | |||
| }; | |||
| /** | |||
| * Default constructor. | |||
| */ | |||
| public PropertyResource() { | |||
| } | |||
| /** | |||
| * Construct a new PropertyResource with the specified name. | |||
| * @param n the String name of this PropertyResource (Ant property name/key). | |||
| */ | |||
| public PropertyResource(Project p, String n) { | |||
| super(n); | |||
| setProject(p); | |||
| } | |||
| /** | |||
| * Get the value of this PropertyResource. | |||
| * @return the value of the specified Property. | |||
| */ | |||
| public String getValue() { | |||
| Project p = getProject(); | |||
| return p == null ? null : p.getProperty(getName()); | |||
| } | |||
| /** | |||
| * Find out whether this Resource exists. | |||
| * @return true if the Property is set, false otherwise. | |||
| */ | |||
| public boolean isExists() { | |||
| return getValue() != null; | |||
| } | |||
| /** | |||
| * Get the size of this Resource. | |||
| * @return the size, as a long, 0 if the Resource does not exist (for | |||
| * compatibility with java.io.File), or UNKNOWN_SIZE if not known. | |||
| */ | |||
| public long getSize() { | |||
| if (isReference()) { | |||
| return ((Resource) getCheckedRef()).getSize(); | |||
| } | |||
| return isExists() ? (long) getValue().length() : 0L; | |||
| } | |||
| /** | |||
| * Get the hash code for this Resource. | |||
| * @return hash code as int. | |||
| */ | |||
| public int hashCode() { | |||
| if (isReference()) { | |||
| return getCheckedRef().hashCode(); | |||
| } | |||
| return super.hashCode() * PROPERTY_MAGIC; | |||
| } | |||
| /** | |||
| * Get an InputStream for the Resource. | |||
| * @return an InputStream containing this Resource's content. | |||
| * @throws IOException if unable to provide the content of this | |||
| * Resource as a stream. | |||
| * @throws UnsupportedOperationException if InputStreams are not | |||
| * supported for this Resource type. | |||
| */ | |||
| public InputStream getInputStream() throws IOException { | |||
| if (isReference()) { | |||
| return ((Resource) getCheckedRef()).getInputStream(); | |||
| } | |||
| return isExists() ? new ByteArrayInputStream(getValue().getBytes()) : UNSET; | |||
| } | |||
| /** | |||
| * Get an OutputStream for the Resource. | |||
| * @return an OutputStream to which content can be written. | |||
| * @throws IOException if unable to provide the content of this | |||
| * Resource as a stream. | |||
| * @throws UnsupportedOperationException if OutputStreams are not | |||
| * supported for this Resource type. | |||
| */ | |||
| public OutputStream getOutputStream() throws IOException { | |||
| if (isReference()) { | |||
| return ((Resource) getCheckedRef()).getOutputStream(); | |||
| } | |||
| if (isExists()) { | |||
| throw new ImmutableResourceException(); | |||
| } | |||
| return new PropertyOutputStream(getProject(), getName()); | |||
| } | |||
| } | |||
| @@ -0,0 +1,187 @@ | |||
| /* | |||
| * Copyright 2005 The Apache Software Foundation | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * | |||
| */ | |||
| package org.apache.tools.ant.types.resources; | |||
| import java.util.List; | |||
| import java.util.Stack; | |||
| import java.util.Vector; | |||
| import java.util.Iterator; | |||
| import java.util.Collection; | |||
| import java.util.AbstractCollection; | |||
| import java.util.NoSuchElementException; | |||
| import org.apache.tools.ant.Project; | |||
| import org.apache.tools.ant.BuildException; | |||
| import org.apache.tools.ant.types.DataType; | |||
| import org.apache.tools.ant.types.ResourceCollection; | |||
| /** | |||
| * Generic ResourceCollection: Either stores nested ResourceCollections, | |||
| * making no attempt to remove duplicates, or references another ResourceCollection. | |||
| * @since Ant 1.7 | |||
| */ | |||
| public class Resources extends DataType implements ResourceCollection { | |||
| private class MyCollection extends AbstractCollection { | |||
| int size; | |||
| MyCollection() { | |||
| size = 0; | |||
| for (Iterator rci = rc.iterator(); rci.hasNext();) { | |||
| size += ((ResourceCollection) rci.next()).size(); | |||
| } | |||
| } | |||
| public int size() { | |||
| return size; | |||
| } | |||
| public Iterator iterator() { | |||
| return new MyIterator(); | |||
| } | |||
| private class MyIterator implements Iterator { | |||
| Iterator rci = rc.iterator(); | |||
| Iterator ri = null; | |||
| public boolean hasNext() { | |||
| if ((ri == null || !ri.hasNext()) && rci.hasNext()) { | |||
| ri = ((ResourceCollection) rci.next()).iterator(); | |||
| } | |||
| return ri != null && ri.hasNext(); | |||
| } | |||
| public Object next() { | |||
| if (!hasNext()) { | |||
| throw new NoSuchElementException(); | |||
| } | |||
| return ri.next(); | |||
| } | |||
| public void remove() { | |||
| throw new UnsupportedOperationException(); | |||
| } | |||
| } | |||
| } | |||
| private Vector rc = null; | |||
| private Collection coll = null; | |||
| /** | |||
| * Add a ResourceCollection. | |||
| * @param c the ResourceCollection to add. | |||
| */ | |||
| public synchronized void add(ResourceCollection c) { | |||
| if (isReference()) { | |||
| throw noChildrenAllowed(); | |||
| } | |||
| rc = (rc == null) ? new Vector() : rc; | |||
| rc.add(c); | |||
| FailFast.invalidate(this); | |||
| coll = null; | |||
| setChecked(false); | |||
| } | |||
| /** | |||
| * Fulfill the ResourceCollection contract. | |||
| * @return an Iterator of Resources. | |||
| */ | |||
| public synchronized Iterator iterator() { | |||
| if (isReference()) { | |||
| return getRef().iterator(); | |||
| } | |||
| validate(); | |||
| return new FailFast(this, coll.iterator()); | |||
| } | |||
| /** | |||
| * Fulfill the ResourceCollection contract. | |||
| * @return number of elements as int. | |||
| */ | |||
| public synchronized int size() { | |||
| if (isReference()) { | |||
| return getRef().size(); | |||
| } | |||
| validate(); | |||
| return coll.size(); | |||
| } | |||
| /** | |||
| * Fulfill the ResourceCollection contract. | |||
| * @return true if all Resources represent files. | |||
| */ | |||
| public boolean isFilesystemOnly() { | |||
| if (isReference()) { | |||
| return getRef().isFilesystemOnly(); | |||
| } | |||
| validate(); | |||
| //first the easy way, if all children are filesystem-only, return true: | |||
| boolean goEarly = true; | |||
| for (Iterator i = rc.iterator(); goEarly && i.hasNext();) { | |||
| goEarly &= ((ResourceCollection) i.next()).isFilesystemOnly(); | |||
| } | |||
| if (goEarly) { | |||
| return true; | |||
| } | |||
| /* now check each Resource in case the child only | |||
| lets through files from any children IT may have: */ | |||
| for (Iterator i = coll.iterator(); i.hasNext();) { | |||
| if (!(i.next() instanceof FileResource)) { | |||
| return false; | |||
| } | |||
| } | |||
| return true; | |||
| } | |||
| /** | |||
| * Overrides the version of DataType to recurse on all DataType | |||
| * child elements that may have been added. | |||
| * @param stk the stack of data types to use (recursively). | |||
| * @param p the project to use to dereference the references. | |||
| * @throws BuildException on error. | |||
| */ | |||
| protected void dieOnCircularReference(Stack stk, Project p) | |||
| throws BuildException { | |||
| if (isChecked()) { | |||
| return; | |||
| } | |||
| if (isReference()) { | |||
| super.dieOnCircularReference(stk, p); | |||
| } else { | |||
| for (Iterator i = rc.iterator(); i.hasNext();) { | |||
| Object o = i.next(); | |||
| if (o instanceof DataType) { | |||
| invokeCircularReferenceCheck((DataType) o, stk, p); | |||
| } | |||
| } | |||
| setChecked(true); | |||
| } | |||
| } | |||
| /** | |||
| * Resolves references, allowing any ResourceCollection. | |||
| * @return the referenced ResourceCollection. | |||
| */ | |||
| private ResourceCollection getRef() { | |||
| return (ResourceCollection) getCheckedRef( | |||
| ResourceCollection.class, "ResourceCollection"); | |||
| } | |||
| private synchronized void validate() { | |||
| dieOnCircularReference(); | |||
| if (rc == null || rc.size() == 0) { | |||
| throw new BuildException("Resources: no resources specified."); | |||
| } | |||
| coll = (coll == null) ? new MyCollection() : coll; | |||
| } | |||
| } | |||
| @@ -0,0 +1,137 @@ | |||
| /* | |||
| * Copyright 2005 The Apache Software Foundation | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * | |||
| */ | |||
| package org.apache.tools.ant.types.resources; | |||
| import java.util.Iterator; | |||
| import java.util.ArrayList; | |||
| import java.util.Collection; | |||
| import org.apache.tools.ant.BuildException; | |||
| import org.apache.tools.ant.types.Resource; | |||
| import org.apache.tools.ant.types.ResourceCollection; | |||
| import org.apache.tools.ant.types.resources.selectors.ResourceSelector; | |||
| import org.apache.tools.ant.types.resources.selectors.ResourceSelectorContainer; | |||
| /** | |||
| * ResourceCollection that allows a number of selectors to be | |||
| * applied to a single ResourceCollection for the purposes of | |||
| * restricting or narrowing results. | |||
| * @since Ant 1.7 | |||
| */ | |||
| public class Restrict | |||
| extends ResourceSelectorContainer implements ResourceCollection { | |||
| private static final String ONE_NESTED_MESSAGE | |||
| = "Restriction is to be applied to exactly one nested resource collection."; | |||
| private ResourceCollection rc; | |||
| /** | |||
| * Add the ResourceCollection. | |||
| * @param c the ResourceCollection to add. | |||
| */ | |||
| public synchronized void add(ResourceCollection c) { | |||
| if (isReference()) { | |||
| throw noChildrenAllowed(); | |||
| } | |||
| if (rc != null) { | |||
| throw new BuildException(ONE_NESTED_MESSAGE); | |||
| } | |||
| rc = c; | |||
| } | |||
| /** | |||
| * Add a ResourceSelector. | |||
| * @param the ResourceSelector to add. | |||
| */ | |||
| public synchronized void add(ResourceSelector s) { | |||
| super.add(s); | |||
| FailFast.invalidate(this); | |||
| } | |||
| /** | |||
| * Fulfill the ResourceCollection contract. | |||
| * @return an Iterator of Resources. | |||
| */ | |||
| public final synchronized Iterator iterator() { | |||
| if (isReference()) { | |||
| return ((Restrict) getCheckedRef()).iterator(); | |||
| } | |||
| dieOnCircularReference(); | |||
| if (rc == null) { | |||
| throw new BuildException(ONE_NESTED_MESSAGE); | |||
| } | |||
| return new FailFast(this, getCollection().iterator()); | |||
| } | |||
| /** | |||
| * Fulfill the ResourceCollection contract. | |||
| * @return number of elements as int. | |||
| */ | |||
| public synchronized int size() { | |||
| if (isReference()) { | |||
| return ((Restrict) getCheckedRef()).size(); | |||
| } | |||
| dieOnCircularReference(); | |||
| return getCollection().size(); | |||
| } | |||
| /** | |||
| * Fulfill the ResourceCollection contract. | |||
| * @return whether this is a filesystem-only resource collection. | |||
| */ | |||
| public synchronized boolean isFilesystemOnly() { | |||
| if (isReference()) { | |||
| return ((Restrict) getCheckedRef()).isFilesystemOnly(); | |||
| } | |||
| dieOnCircularReference(); | |||
| if (rc == null) { | |||
| throw new BuildException(ONE_NESTED_MESSAGE); | |||
| } | |||
| //first the easy way, if child is filesystem-only, return true: | |||
| if (rc.isFilesystemOnly()) { | |||
| return true; | |||
| } | |||
| /* now check each Resource in case the child only | |||
| lets through files from any children IT may have: */ | |||
| for (Iterator i = getCollection().iterator(); i.hasNext();) { | |||
| if (!(i.next() instanceof FileResource)) { | |||
| return false; | |||
| } | |||
| } | |||
| return true; | |||
| } | |||
| /** | |||
| * Restrict the nested ResourceCollection based on the nested selectors. | |||
| * @return a Collection of Resources. | |||
| */ | |||
| protected Collection getCollection() { | |||
| ArrayList result = new ArrayList(); | |||
| outer: for (Iterator ri = rc.iterator(); ri.hasNext();) { | |||
| Resource r = (Resource) ri.next(); | |||
| for (Iterator i = getSelectors(); i.hasNext();) { | |||
| if (!((ResourceSelector) (i.next())).isSelected(r)) { | |||
| continue outer; | |||
| } | |||
| } | |||
| result.add(r); | |||
| } | |||
| return result; | |||
| } | |||
| } | |||
| @@ -0,0 +1,107 @@ | |||
| /* | |||
| * Copyright 2005 The Apache Software Foundation | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * | |||
| */ | |||
| package org.apache.tools.ant.types.resources; | |||
| import java.util.List; | |||
| import java.util.Stack; | |||
| import java.util.Iterator; | |||
| import java.util.ArrayList; | |||
| import java.util.Collection; | |||
| import java.util.Collections; | |||
| import org.apache.tools.ant.Project; | |||
| import org.apache.tools.ant.BuildException; | |||
| import org.apache.tools.ant.types.DataType; | |||
| import org.apache.tools.ant.types.ResourceCollection; | |||
| import org.apache.tools.ant.types.resources.comparators.ResourceComparator; | |||
| /** | |||
| * ResourceCollection that sorts another ResourceCollection. | |||
| * @since Ant 1.7 | |||
| */ | |||
| public class Sort extends BaseResourceCollectionContainer { | |||
| private static final String ONE_NESTED_MESSAGE | |||
| = "Sorting is to be applied to exactly one nested resource collection."; | |||
| private Stack compStack = new Stack(); | |||
| /** | |||
| * Sort the contained elements. | |||
| * @return a Collection of Resources. | |||
| */ | |||
| protected Collection getCollection() { | |||
| List rcs = getResourceCollections(); | |||
| if (rcs.size() != 1) { | |||
| throw new BuildException(ONE_NESTED_MESSAGE); | |||
| } | |||
| Iterator nested = ((ResourceCollection) (rcs.get(0))).iterator(); | |||
| if (!(nested.hasNext())) { | |||
| return Collections.EMPTY_SET; | |||
| } | |||
| ArrayList al = new ArrayList(); | |||
| while (nested.hasNext()) { | |||
| al.add(nested.next()); | |||
| } | |||
| if (compStack.empty()) { | |||
| Collections.sort(al); | |||
| } else { | |||
| for (Stack s = (Stack) compStack.clone(); !s.empty();) { | |||
| Collections.sort(al, (ResourceComparator) s.pop()); | |||
| } | |||
| } | |||
| return al; | |||
| } | |||
| /** | |||
| * Add a ResourceComparator to this Sort ResourceCollection. | |||
| * If multiple ResourceComparator are added, they will be processed in LIFO order. | |||
| * @param c the ResourceComparator to add. | |||
| */ | |||
| public void add(ResourceComparator c) { | |||
| if (isReference()) { | |||
| throw noChildrenAllowed(); | |||
| } | |||
| compStack.push(c); | |||
| } | |||
| /** | |||
| * Overrides the BaseResourceCollectionContainer version | |||
| * to recurse on nested ResourceComparators. | |||
| * @param stk the stack of data types to use (recursively). | |||
| * @param p the project to use to dereference the references. | |||
| * @throws BuildException on error. | |||
| */ | |||
| protected void dieOnCircularReference(Stack stk, Project p) | |||
| throws BuildException { | |||
| if (isChecked()) { | |||
| return; | |||
| } | |||
| if (isReference()) { | |||
| super.dieOnCircularReference(stk, p); | |||
| } else { | |||
| for (Iterator i = compStack.iterator(); i.hasNext();) { | |||
| Object o = i.next(); | |||
| if (o instanceof DataType) { | |||
| stk.push(o); | |||
| invokeCircularReferenceCheck((DataType) o, stk, p); | |||
| } | |||
| } | |||
| setChecked(true); | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,204 @@ | |||
| /* | |||
| * Copyright 2005 The Apache Software Foundation | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * | |||
| */ | |||
| package org.apache.tools.ant.types.resources; | |||
| import java.io.IOException; | |||
| import java.io.InputStream; | |||
| import java.io.OutputStream; | |||
| import java.io.FilterOutputStream; | |||
| import java.io.ByteArrayInputStream; | |||
| import java.io.ByteArrayOutputStream; | |||
| import org.apache.tools.ant.Project; | |||
| import org.apache.tools.ant.BuildException; | |||
| import org.apache.tools.ant.types.Resource; | |||
| import org.apache.tools.ant.types.Reference; | |||
| /** | |||
| * Exposes a string as a Resource. | |||
| * @since Ant 1.7 | |||
| */ | |||
| public class StringResource extends Resource { | |||
| /** Magic number */ | |||
| private static final int STRING_MAGIC | |||
| = Resource.getMagicNumber("StringResource".getBytes()); | |||
| private String encoding = null; | |||
| /** | |||
| * Default constructor. | |||
| */ | |||
| public StringResource() { | |||
| } | |||
| /** | |||
| * Construct a StringResource with the supplied value. | |||
| * @param value the value of this StringResource. | |||
| */ | |||
| public StringResource(String value) { | |||
| setValue(value); | |||
| } | |||
| /** | |||
| * Enforce String immutability. | |||
| * @param s the new name/value for this StringResource. | |||
| */ | |||
| public synchronized void setName(String s) { | |||
| if (getName() != null) { | |||
| throw new BuildException(new ImmutableResourceException()); | |||
| } | |||
| super.setName(s); | |||
| } | |||
| /** | |||
| * The value attribute is a semantically superior alias for the name attribute. | |||
| * @param s the String's value. | |||
| */ | |||
| public synchronized void setValue(String s) { | |||
| setName(s); | |||
| } | |||
| /** | |||
| * Synchronize access. | |||
| * @return the name/value of this StringResource. | |||
| */ | |||
| public synchronized String getName() { | |||
| return super.getName(); | |||
| } | |||
| /** | |||
| * Get the value of this StringResource. | |||
| * @return the represented String. | |||
| */ | |||
| public synchronized String getValue() { | |||
| return getName(); | |||
| } | |||
| /** | |||
| * Set the encoding to be used for this StringResource. | |||
| * @param s the encoding name. | |||
| */ | |||
| public synchronized void setEncoding(String s) { | |||
| encoding = s; | |||
| } | |||
| /** | |||
| * Get the encoding used by this StringResource. | |||
| * @return the encoding name. | |||
| */ | |||
| public synchronized String getEncoding() { | |||
| return encoding; | |||
| } | |||
| /** | |||
| * Get the size of this Resource. | |||
| * @return the size, as a long, 0 if the Resource does not exist (for | |||
| * compatibility with java.io.File), or UNKNOWN_SIZE if not known. | |||
| */ | |||
| public synchronized long getSize() { | |||
| return isReference() | |||
| ? ((Resource) getCheckedRef()).getSize() | |||
| : (long) getContent().length(); | |||
| } | |||
| /** | |||
| * Get the hash code for this Resource. | |||
| * @return hash code as int. | |||
| */ | |||
| public synchronized int hashCode() { | |||
| if (isReference()) { | |||
| return getCheckedRef().hashCode(); | |||
| } | |||
| return super.hashCode() * STRING_MAGIC; | |||
| } | |||
| /** | |||
| * Get an InputStream for the Resource. | |||
| * @return an InputStream containing this Resource's content. | |||
| * @throws IOException if unable to provide the content of this | |||
| * Resource as a stream. | |||
| * @throws UnsupportedOperationException if InputStreams are not | |||
| * supported for this Resource type. | |||
| */ | |||
| public synchronized InputStream getInputStream() throws IOException { | |||
| if (isReference()) { | |||
| return ((Resource) getCheckedRef()).getInputStream(); | |||
| } | |||
| //I can't get my head around this; is encoding treatment needed here? | |||
| return | |||
| //new oata.util.ReaderInputStream(new InputStreamReader( | |||
| new ByteArrayInputStream(getContent().getBytes()) | |||
| //, encoding), encoding) | |||
| ; | |||
| } | |||
| /** | |||
| * Get an OutputStream for the Resource. | |||
| * @return an OutputStream to which content can be written. | |||
| * @throws IOException if unable to provide the content of this | |||
| * Resource as a stream. | |||
| * @throws UnsupportedOperationException if OutputStreams are not | |||
| * supported for this Resource type. | |||
| */ | |||
| public synchronized OutputStream getOutputStream() throws IOException { | |||
| if (isReference()) { | |||
| return ((Resource) getCheckedRef()).getOutputStream(); | |||
| } | |||
| if (getValue() != null) { | |||
| throw new ImmutableResourceException(); | |||
| } | |||
| final ByteArrayOutputStream baos = new ByteArrayOutputStream(); | |||
| return new FilterOutputStream(baos) { | |||
| public void close() throws IOException { | |||
| super.close(); | |||
| StringResource.this.setValue(encoding == null | |||
| ? baos.toString() : baos.toString(encoding)); | |||
| } | |||
| }; | |||
| } | |||
| /** | |||
| * Overrides the super version. | |||
| * @param r the Reference to set. | |||
| */ | |||
| public void setRefid(Reference r) { | |||
| if (encoding != null) { | |||
| throw tooManyAttributes(); | |||
| } | |||
| super.setRefid(r); | |||
| } | |||
| /** | |||
| * Get the content of this StringResource. | |||
| * @return a String; if the Project has been set properties | |||
| * replacement will be attempted. | |||
| */ | |||
| protected synchronized String getContent() { | |||
| if (isReference()) { | |||
| return ((StringResource) getCheckedRef()).getContent(); | |||
| } | |||
| String value = getValue(); | |||
| if (value == null) { | |||
| return value; | |||
| } | |||
| return getProject() == null | |||
| ? value : getProject().replaceProperties(value); | |||
| } | |||
| } | |||
| @@ -0,0 +1,26 @@ | |||
| /* | |||
| * Copyright 2005 The Apache Software Foundation | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * | |||
| */ | |||
| package org.apache.tools.ant.types.resources; | |||
| /** | |||
| * Interface to be implemented by "touchable" resources; i.e. those | |||
| * whose modification time can be altered. | |||
| * @since Ant 1.7 | |||
| */ | |||
| public interface Touchable { | |||
| void touch(long modTime); | |||
| } | |||
| @@ -0,0 +1,373 @@ | |||
| /* | |||
| * Copyright 2005 The Apache Software Foundation | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * | |||
| */ | |||
| package org.apache.tools.ant.types.resources; | |||
| import java.io.File; | |||
| import java.io.IOException; | |||
| import java.io.InputStream; | |||
| import java.io.OutputStream; | |||
| import java.net.URL; | |||
| import java.net.URLConnection; | |||
| import java.net.MalformedURLException; | |||
| import org.apache.tools.ant.Project; | |||
| import org.apache.tools.ant.AntClassLoader; | |||
| import org.apache.tools.ant.BuildException; | |||
| import org.apache.tools.ant.types.Path; | |||
| import org.apache.tools.ant.types.Resource; | |||
| import org.apache.tools.ant.types.Reference; | |||
| import org.apache.tools.ant.util.FileUtils; | |||
| /** | |||
| * Exposes a URL as a Resource. | |||
| * @since Ant 1.7 | |||
| */ | |||
| public class URLResource extends Resource { | |||
| private static final FileUtils FILE_UTILS = FileUtils.getFileUtils(); | |||
| private static final int NULL_URL | |||
| = Resource.getMagicNumber("null URL".getBytes()); | |||
| private URL url; | |||
| private String javaResource; | |||
| private URLConnection conn; | |||
| private Path classpath; | |||
| /** | |||
| * Default constructor. | |||
| */ | |||
| public URLResource() { | |||
| } | |||
| /** | |||
| * Convenience constructor. | |||
| * @param u the URL to expose. | |||
| */ | |||
| public URLResource(URL u) { | |||
| setURL(u); | |||
| } | |||
| /** | |||
| * Convenience constructor. | |||
| * @param f the File to set as a URL. | |||
| */ | |||
| public URLResource(File f) { | |||
| setFile(f); | |||
| } | |||
| /** | |||
| * String constructor for Ant attribute introspection. | |||
| * @param u String representation of this URL. | |||
| * @see org.apache.tools.ant.IntrospectionHelper | |||
| */ | |||
| public URLResource(String u) { | |||
| this(newURL(u)); | |||
| } | |||
| /** | |||
| * Set the URL for this URLResource. | |||
| * @param u the URL to expose. | |||
| */ | |||
| public synchronized void setURL(URL u) { | |||
| checkAttributesAllowed(); | |||
| url = u; | |||
| } | |||
| /** | |||
| * Set the URL from a File. | |||
| * @param f the File to set as a URL. | |||
| */ | |||
| public synchronized void setFile(File f) { | |||
| try { | |||
| setURL(FILE_UTILS.getFileURL(f)); | |||
| } catch (MalformedURLException e) { | |||
| throw new BuildException(e); | |||
| } | |||
| } | |||
| /** | |||
| * Set the resource name with which to expose a Java resource. | |||
| * @param s the Java resource name. | |||
| * @see java.lang.ClassLoader#getResource() | |||
| */ | |||
| public synchronized void setJavaResource(String s) { | |||
| checkAttributesAllowed(); | |||
| javaResource = s; | |||
| } | |||
| /** | |||
| * Set the classpath for this URLResource. | |||
| * @param p the Path against which to resolve Java resources. | |||
| */ | |||
| public synchronized void setClasspath(Path p) { | |||
| checkAttributesAllowed(); | |||
| addConfiguredClasspath(p); | |||
| } | |||
| /** | |||
| * Create a nested classpath element. | |||
| * @return a Path object. | |||
| */ | |||
| public synchronized void addConfiguredClasspath(Path p) { | |||
| checkChildrenAllowed(); | |||
| if (classpath == null) { | |||
| classpath = new Path(getProject()); | |||
| } | |||
| classpath.add(p); | |||
| } | |||
| /** | |||
| * Get the URL used by this URLResource. | |||
| * @return a URL object. | |||
| */ | |||
| public synchronized URL getURL() { | |||
| if (isReference()) { | |||
| return ((URLResource) getCheckedRef()).getURL(); | |||
| } | |||
| if (url == null && javaResource != null) { | |||
| ClassLoader cl = null; | |||
| AntClassLoader acl = null; | |||
| if (classpath != null) { | |||
| acl = getProject().createClassLoader(classpath); | |||
| cl = acl; | |||
| } else { | |||
| cl = getClass().getClassLoader(); | |||
| if (cl == null) { | |||
| cl = ClassLoader.getSystemClassLoader(); | |||
| } | |||
| } | |||
| if (cl != null) { | |||
| setURL(cl.getResource(javaResource)); | |||
| if (acl != null) { | |||
| acl.cleanup(); | |||
| } | |||
| } | |||
| } | |||
| return url; | |||
| } | |||
| /** | |||
| * Overrides the super version. | |||
| * @param r the Reference to set. | |||
| */ | |||
| public synchronized void setRefid(Reference r) { | |||
| //not using the accessor in this case to avoid side effects | |||
| if (url != null || javaResource != null) { | |||
| throw tooManyAttributes(); | |||
| } | |||
| super.setRefid(r); | |||
| } | |||
| /** | |||
| * Get the name of this URLResource | |||
| * (its file component minus the leading separator). | |||
| * @return the name of this resource. | |||
| */ | |||
| public synchronized String getName() { | |||
| return isReference() ? ((Resource) getCheckedRef()).getName() | |||
| : getURL().getFile().substring(1); | |||
| } | |||
| /** | |||
| * Return this URLResource formatted as a String. | |||
| * @return a String representation of this URLResource. | |||
| */ | |||
| public synchronized String toString() { | |||
| return isReference() | |||
| ? getCheckedRef().toString() : String.valueOf(getURL()); | |||
| } | |||
| /** | |||
| * Find out whether the URL exists . | |||
| * @return true if this resource exists. | |||
| */ | |||
| public synchronized boolean isExists() { | |||
| if (isReference()) { | |||
| return ((Resource) getCheckedRef()).isExists(); | |||
| } | |||
| if (getURL() == null) { | |||
| return false; | |||
| } | |||
| try { | |||
| connect(); | |||
| return true; | |||
| } catch (IOException e) { | |||
| return false; | |||
| } | |||
| } | |||
| /** | |||
| * Tells the modification time in milliseconds since 01.01.1970 . | |||
| * | |||
| * @return 0 if the resource does not exist to mirror the behavior | |||
| * of {@link java.io.File File}. | |||
| */ | |||
| public synchronized long getLastModified() { | |||
| if (isReference()) { | |||
| return ((Resource) getCheckedRef()).getLastModified(); | |||
| } | |||
| if (!isExists()) { | |||
| return 0L; | |||
| } | |||
| try { | |||
| connect(); | |||
| return conn.getLastModified(); | |||
| } catch (IOException e) { | |||
| return 0L; | |||
| } | |||
| } | |||
| /** | |||
| * Tells if the resource is a directory. | |||
| * @return boolean whether the resource is a directory. | |||
| */ | |||
| public synchronized boolean isDirectory() { | |||
| return isReference() | |||
| ? ((Resource) getCheckedRef()).isDirectory() | |||
| : getName().endsWith("/"); | |||
| } | |||
| /** | |||
| * Get the size of this Resource. | |||
| * @return the size, as a long, 0 if the Resource does not exist (for | |||
| * compatibility with java.io.File), or UNKNOWN_SIZE if not known. | |||
| */ | |||
| public synchronized long getSize() { | |||
| if (isReference()) { | |||
| return ((Resource) getCheckedRef()).getSize(); | |||
| } | |||
| if (!isExists()) { | |||
| return 0L; | |||
| } | |||
| try { | |||
| connect(); | |||
| return conn.getContentLength(); | |||
| } catch (IOException e) { | |||
| return UNKNOWN_SIZE; | |||
| } | |||
| } | |||
| /** | |||
| * Test whether an Object equals this URLResource. | |||
| * @param another the other Object to compare. | |||
| * @return true if the specified Object is equal to this Resource. | |||
| */ | |||
| public synchronized boolean equals(Object another) { | |||
| if (this == another) { | |||
| return true; | |||
| } | |||
| if (isReference()) { | |||
| return getCheckedRef().equals(another); | |||
| } | |||
| if (!(another.getClass().equals(getClass()))) { | |||
| return false; | |||
| } | |||
| URLResource otheru = (URLResource) another; | |||
| return getURL() == null | |||
| ? otheru.getURL() == null | |||
| : getURL().equals(otheru.getURL()); | |||
| } | |||
| /** | |||
| * Get the hash code for this Resource. | |||
| * @return hash code as int. | |||
| */ | |||
| public synchronized int hashCode() { | |||
| if (isReference()) { | |||
| return getCheckedRef().hashCode(); | |||
| } | |||
| return MAGIC * ((getURL() == null) ? NULL_URL : getURL().hashCode()); | |||
| } | |||
| /** | |||
| * Get an InputStream for the Resource. | |||
| * @return an InputStream containing this Resource's content. | |||
| * @throws IOException if unable to provide the content of this | |||
| * Resource as a stream. | |||
| * @throws UnsupportedOperationException if InputStreams are not | |||
| * supported for this Resource type. | |||
| */ | |||
| public synchronized InputStream getInputStream() throws IOException { | |||
| if (isReference()) { | |||
| return ((Resource) getCheckedRef()).getInputStream(); | |||
| } | |||
| connect(); | |||
| try { | |||
| return conn.getInputStream(); | |||
| } finally { | |||
| conn = null; | |||
| } | |||
| } | |||
| /** | |||
| * Get an OutputStream for the Resource. | |||
| * @return an OutputStream to which content can be written. | |||
| * @throws IOException if unable to provide the content of this | |||
| * Resource as a stream. | |||
| * @throws UnsupportedOperationException if OutputStreams are not | |||
| * supported for this Resource type. | |||
| */ | |||
| public synchronized OutputStream getOutputStream() throws IOException { | |||
| if (isReference()) { | |||
| return ((Resource) getCheckedRef()).getOutputStream(); | |||
| } | |||
| connect(); | |||
| try { | |||
| return conn.getOutputStream(); | |||
| } finally { | |||
| conn = null; | |||
| } | |||
| } | |||
| /** | |||
| * Ensure that we have a connection. | |||
| */ | |||
| protected synchronized void connect() throws IOException { | |||
| URL u = getURL(); | |||
| if (u == null) { | |||
| throw new BuildException("URL not set"); | |||
| } | |||
| if (conn == null) { | |||
| try { | |||
| conn = u.openConnection(); | |||
| conn.connect(); | |||
| } catch (IOException e) { | |||
| log(e.toString(), Project.MSG_ERR); | |||
| conn = null; | |||
| throw e; | |||
| } | |||
| } | |||
| } | |||
| /** | |||
| * Finalize this URLResource. | |||
| * @throws Throwable on error. | |||
| */ | |||
| protected void finalize() throws Throwable { | |||
| conn = null; | |||
| super.finalize(); | |||
| } | |||
| private static URL newURL(String u) { | |||
| try { | |||
| return new URL(u); | |||
| } catch (MalformedURLException e) { | |||
| throw new BuildException(e); | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,85 @@ | |||
| /* | |||
| * Copyright 2005 The Apache Software Foundation | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * | |||
| */ | |||
| package org.apache.tools.ant.types.resources; | |||
| import java.util.List; | |||
| import java.util.Iterator; | |||
| import java.util.ArrayList; | |||
| import java.util.Collection; | |||
| import java.util.Collections; | |||
| import org.apache.tools.ant.types.ResourceCollection; | |||
| /** | |||
| * ResourceCollection representing the union of multiple nested ResourceCollections. | |||
| * @since Ant 1.7 | |||
| */ | |||
| public class Union extends BaseResourceCollectionContainer { | |||
| /** | |||
| * Returns all Resources in String format. Moved up from | |||
| * Path for convenience. | |||
| * @return String array of Resources. | |||
| */ | |||
| public String[] list() { | |||
| if (isReference()) { | |||
| return ((Union) getCheckedRef()).list(); | |||
| } | |||
| Collection result = getCollection(true); | |||
| return (String[]) (result.toArray(new String[result.size()])); | |||
| } | |||
| /** | |||
| * Unify the contained Resources. | |||
| * @return a Collection of Resources. | |||
| */ | |||
| protected Collection getCollection() { | |||
| return getCollection(false); | |||
| } | |||
| /** | |||
| * Unify the contained Resources. | |||
| * @param asString indicates whether the resulting Collection | |||
| * should contain Strings instead of Resources. | |||
| * @return a Collection of Resources. | |||
| */ | |||
| protected Collection getCollection(boolean asString) { | |||
| List rc = getResourceCollections(); | |||
| if (rc.isEmpty()) { | |||
| return Collections.EMPTY_LIST; | |||
| } | |||
| //preserve order-encountered using a list; enforce set logic manually: | |||
| ArrayList union = new ArrayList(rc.size() * 2); | |||
| for (Iterator rcIter = rc.iterator(); rcIter.hasNext();) { | |||
| for (Iterator r = nextRC(rcIter).iterator(); r.hasNext();) { | |||
| Object o = r.next(); | |||
| if (asString) { | |||
| o = o.toString(); | |||
| } | |||
| if (!(union.contains(o))) { | |||
| union.add(o); | |||
| } | |||
| } | |||
| } | |||
| return union; | |||
| } | |||
| private static ResourceCollection nextRC(Iterator i) { | |||
| return (ResourceCollection) i.next(); | |||
| } | |||
| } | |||
| @@ -0,0 +1,299 @@ | |||
| /* | |||
| * Copyright 2005 The Apache Software Foundation | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * | |||
| */ | |||
| package org.apache.tools.ant.types.resources; | |||
| import java.io.File; | |||
| import java.io.InputStream; | |||
| import java.io.OutputStream; | |||
| import java.io.IOException; | |||
| import java.io.FilterInputStream; | |||
| import org.apache.tools.ant.Project; | |||
| import org.apache.tools.ant.BuildException; | |||
| import org.apache.tools.ant.types.Resource; | |||
| import org.apache.tools.ant.types.Reference; | |||
| import org.apache.tools.ant.util.FileUtils; | |||
| import org.apache.tools.zip.ZipFile; | |||
| import org.apache.tools.zip.ZipEntry; | |||
| /** | |||
| * A Resource representation of an entry in a zipfile. | |||
| * @since Ant 1.7 | |||
| */ | |||
| public class ZipResource extends Resource { | |||
| private static final int NULL_ZIPFILE | |||
| = Resource.getMagicNumber("null zipfile".getBytes()); | |||
| private String encoding; | |||
| private File zipfile; | |||
| private boolean haveEntry = false; | |||
| /** | |||
| * Default constructor. | |||
| */ | |||
| public ZipResource() { | |||
| } | |||
| /** | |||
| * Construct a ZipResource representing the specified | |||
| * entry in the specified zipfile. | |||
| * @param z the zipfile as File. | |||
| * @param enc the encoding used for filenames. | |||
| * @param e the ZipEntry. | |||
| */ | |||
| public ZipResource(File z, String enc, ZipEntry e) { | |||
| setEntry(e); | |||
| setZipfile(z); | |||
| setEncoding(enc); | |||
| } | |||
| /** | |||
| * Set the zipfile that holds this ZipResource. | |||
| * @param z the zipfile as a File. | |||
| */ | |||
| public void setZipfile(File z) { | |||
| checkAttributesAllowed(); | |||
| zipfile = z; | |||
| } | |||
| /** | |||
| * Get the zipfile that holds this ZipResource. | |||
| * @return the zipfile as a File. | |||
| */ | |||
| public File getZipfile() { | |||
| return isReference() | |||
| ? ((ZipResource) getCheckedRef()).getZipfile() : zipfile; | |||
| } | |||
| /** | |||
| * Set the encoding to use with the zipfile. | |||
| * @param enc the String encoding. | |||
| */ | |||
| public void setEncoding(String enc) { | |||
| checkAttributesAllowed(); | |||
| encoding = enc; | |||
| } | |||
| /** | |||
| * Get the encoding to use with the zipfile. | |||
| * @return String encoding. | |||
| */ | |||
| public String getEncoding() { | |||
| return isReference() | |||
| ? ((ZipResource) getCheckedRef()).getEncoding() : encoding; | |||
| } | |||
| /** | |||
| * Get the last modified date of this ZipResource. | |||
| * @return the last modification date. | |||
| */ | |||
| public long getLastModified() { | |||
| if (isReference()) { | |||
| return ((Resource) getCheckedRef()).getLastModified(); | |||
| } | |||
| checkEntry(); | |||
| return super.getLastModified(); | |||
| } | |||
| /** | |||
| * Get the size of this ZipResource. | |||
| * @return the long size of this ZipResource. | |||
| */ | |||
| public long getSize() { | |||
| if (isReference()) { | |||
| return ((Resource) getCheckedRef()).getSize(); | |||
| } | |||
| checkEntry(); | |||
| return super.getSize(); | |||
| } | |||
| /** | |||
| * Learn whether this ZipResource represents a directory. | |||
| * @return boolean flag indicating whether the zip entry is a directory. | |||
| */ | |||
| public boolean isDirectory() { | |||
| if (isReference()) { | |||
| return ((Resource) getCheckedRef()).isDirectory(); | |||
| } | |||
| checkEntry(); | |||
| return super.isDirectory(); | |||
| } | |||
| /** | |||
| * Find out whether this ZipResource represents an existing Resource. | |||
| * @return boolean existence flag. | |||
| */ | |||
| public boolean isExists() { | |||
| if (isReference()) { | |||
| return ((Resource) getCheckedRef()).isExists(); | |||
| } | |||
| checkEntry(); | |||
| return super.isExists(); | |||
| } | |||
| /** | |||
| * Overrides the super version. | |||
| * @param r the Reference to set. | |||
| */ | |||
| public void setRefid(Reference r) { | |||
| if (encoding != null || zipfile != null) { | |||
| throw tooManyAttributes(); | |||
| } | |||
| super.setRefid(r); | |||
| } | |||
| /** | |||
| * Return an InputStream for reading the contents of this Resource. | |||
| * @return an InputStream object. | |||
| * @throws IOException if the zip file cannot be opened, | |||
| * or the entry cannot be read. | |||
| */ | |||
| public InputStream getInputStream() throws IOException { | |||
| if (isReference()) { | |||
| return ((Resource) getCheckedRef()).getInputStream(); | |||
| } | |||
| final ZipFile z = new ZipFile(getZipfile(), getEncoding()); | |||
| return new FilterInputStream(z.getInputStream(z.getEntry(getName()))) { | |||
| public void close() throws IOException { | |||
| FileUtils.close(in); | |||
| z.close(); | |||
| } | |||
| protected void finalize() throws Throwable { | |||
| try { | |||
| close(); | |||
| } finally { | |||
| super.finalize(); | |||
| } | |||
| } | |||
| }; | |||
| } | |||
| /** | |||
| * Get an OutputStream for the Resource. | |||
| * @return an OutputStream to which content can be written. | |||
| * @throws IOException if unable to provide the content of this | |||
| * Resource as a stream. | |||
| * @throws UnsupportedOperationException if OutputStreams are not | |||
| * supported for this Resource type. | |||
| */ | |||
| public OutputStream getOutputStream() throws IOException { | |||
| if (isReference()) { | |||
| return ((Resource) getCheckedRef()).getOutputStream(); | |||
| } | |||
| throw new UnsupportedOperationException( | |||
| "Use the zip task for zip output."); | |||
| } | |||
| /** | |||
| * Compare this ZipResource to another Resource. | |||
| * @param another the other Resource against which to compare. | |||
| * @return a negative integer, zero, or a positive integer as this ZipResource | |||
| * is less than, equal to, or greater than the specified Resource. | |||
| */ | |||
| public int compareTo(Object another) { | |||
| return this.equals(another) ? 0 : super.compareTo(another); | |||
| } | |||
| /** | |||
| * Compare another Object to this ZipResource for equality. | |||
| * @param another the other Object to compare. | |||
| * @return true if another is a ZipResource representing | |||
| * the same entry in the same zipfile. | |||
| */ | |||
| public boolean equals(Object another) { | |||
| if (this == another) { | |||
| return true; | |||
| } | |||
| if (isReference()) { | |||
| return getCheckedRef().equals(another); | |||
| } | |||
| if (!(another.getClass().equals(getClass()))) { | |||
| return false; | |||
| } | |||
| ZipResource r = (ZipResource) another; | |||
| return getZipfile().equals(r.getZipfile()) | |||
| && getName().equals(r.getName()); | |||
| } | |||
| /** | |||
| * Get the hash code for this Resource. | |||
| * @return hash code as int. | |||
| */ | |||
| public int hashCode() { | |||
| return super.hashCode() | |||
| * (getZipfile() == null ? NULL_ZIPFILE : getZipfile().hashCode()); | |||
| } | |||
| /** | |||
| * Format this ZipResource as a String. | |||
| * @return String representatation of this ZipResource. | |||
| */ | |||
| public String toString() { | |||
| return isReference() ? getCheckedRef().toString() | |||
| : getZipfile().toString() + ':' + getName(); | |||
| } | |||
| private synchronized void checkEntry() throws BuildException { | |||
| if (haveEntry) { | |||
| return; | |||
| } | |||
| String name = getName(); | |||
| if (name == null) { | |||
| throw new BuildException("zip entry name not set"); | |||
| } | |||
| File f = getZipfile(); | |||
| if (f == null) { | |||
| throw new BuildException("zipfile attribute not set"); | |||
| } | |||
| if (!f.exists()) { | |||
| throw new BuildException(f.getAbsolutePath() + " does not exist."); | |||
| } | |||
| if (f.isDirectory()) { | |||
| throw new BuildException(f + " denotes a directory."); | |||
| } | |||
| ZipFile z = null; | |||
| try { | |||
| z = new ZipFile(f, getEncoding()); | |||
| setEntry(z.getEntry(name)); | |||
| } catch (IOException e) { | |||
| log(e.getMessage(), Project.MSG_DEBUG); | |||
| throw new BuildException(e); | |||
| } finally { | |||
| if (z != null) { | |||
| try { | |||
| z.close(); | |||
| } catch (IOException e) { | |||
| //? | |||
| } | |||
| } | |||
| } | |||
| } | |||
| private synchronized void setEntry(ZipEntry e) { | |||
| haveEntry = true; | |||
| if (e == null) { | |||
| super.setExists(false); | |||
| return; | |||
| } | |||
| super.setName(e.getName()); | |||
| super.setExists(true); | |||
| super.setLastModified(e.getTime()); | |||
| super.setDirectory(e.isDirectory()); | |||
| super.setSize(e.getSize()); | |||
| } | |||
| } | |||
| @@ -0,0 +1,69 @@ | |||
| /* | |||
| * Copyright 2005 The Apache Software Foundation | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * | |||
| */ | |||
| package org.apache.tools.ant.types.resources.comparators; | |||
| import java.io.IOException; | |||
| import org.apache.tools.ant.BuildException; | |||
| import org.apache.tools.ant.types.Resource; | |||
| import org.apache.tools.ant.util.FileUtils; | |||
| /** | |||
| * Compares Resources by content. | |||
| * @since Ant 1.7 | |||
| */ | |||
| public class Content extends ResourceComparator { | |||
| private boolean binary = true; | |||
| /** | |||
| * Set binary mode for this Content ResourceComparator. If this | |||
| * attribute is set to false, Resource content will be compared | |||
| * ignoring platform line-ending conventions. | |||
| * Default is <code>true</code>. | |||
| * @param b whether to compare content in binary mode. | |||
| */ | |||
| public void setBinary(boolean b) { | |||
| binary = b; | |||
| } | |||
| /** | |||
| * Learn whether this Content ResourceComparator is operating in binary mode. | |||
| * @return boolean binary flag. | |||
| */ | |||
| public boolean isBinary() { | |||
| return binary; | |||
| } | |||
| /** | |||
| * Compare two Resources by content. | |||
| * @param foo the first Resource. | |||
| * @param bar the second Resource. | |||
| * @return a negative integer, zero, or a positive integer as the first | |||
| * argument is less than, equal to, or greater than the second. | |||
| * @throws BuildException if I/O errors occur. | |||
| * @see org.apache.tools.ant.util.FileUtils#compareContent(Resource, Resource, boolean). | |||
| */ | |||
| protected int resourceCompare(Resource foo, Resource bar) { | |||
| try { | |||
| return FileUtils.getFileUtils().compareContent(foo, bar, !binary); | |||
| } catch (IOException e) { | |||
| throw new BuildException(e); | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,37 @@ | |||
| /* | |||
| * Copyright 2005 The Apache Software Foundation | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * | |||
| */ | |||
| package org.apache.tools.ant.types.resources.comparators; | |||
| import org.apache.tools.ant.types.Resource; | |||
| /** | |||
| * Compares Resources by last modification date. | |||
| * @since Ant 1.7 | |||
| */ | |||
| public class Date extends ResourceComparator { | |||
| /** | |||
| * Compare two Resources. | |||
| * @param foo the first Resource. | |||
| * @param bar the second Resource. | |||
| * @return a negative integer, zero, or a positive integer as the first | |||
| * argument is less than, equal to, or greater than the second. | |||
| */ | |||
| protected int resourceCompare(Resource foo, Resource bar) { | |||
| return (int) (foo.getLastModified() - bar.getLastModified()); | |||
| } | |||
| } | |||
| @@ -0,0 +1,42 @@ | |||
| /* | |||
| * Copyright 2005 The Apache Software Foundation | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * | |||
| */ | |||
| package org.apache.tools.ant.types.resources.comparators; | |||
| import org.apache.tools.ant.types.Resource; | |||
| /** | |||
| * Compares Resources by existence. Not existing is "less than" existing. | |||
| * @since Ant 1.7 | |||
| */ | |||
| public class Exists extends ResourceComparator { | |||
| /** | |||
| * Compare two Resources. | |||
| * @param foo the first Resource. | |||
| * @param bar the second Resource. | |||
| * @return a negative integer, zero, or a positive integer as the first | |||
| * argument is less than, equal to, or greater than the second. | |||
| */ | |||
| protected int resourceCompare(Resource foo, Resource bar) { | |||
| boolean f = foo.isExists(); | |||
| if (f == bar.isExists()) { | |||
| return 0; | |||
| } | |||
| return f ? 1 : -1; | |||
| } | |||
| } | |||
| @@ -0,0 +1,37 @@ | |||
| /* | |||
| * Copyright 2005 The Apache Software Foundation | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * | |||
| */ | |||
| package org.apache.tools.ant.types.resources.comparators; | |||
| import org.apache.tools.ant.types.Resource; | |||
| /** | |||
| * Compares Resources by name. | |||
| * @since Ant 1.7 | |||
| */ | |||
| public class Name extends ResourceComparator { | |||
| /** | |||
| * Compare two Resources. | |||
| * @param foo the first Resource. | |||
| * @param bar the second Resource. | |||
| * @return a negative integer, zero, or a positive integer as the first | |||
| * argument is less than, equal to, or greater than the second. | |||
| */ | |||
| protected int resourceCompare(Resource foo, Resource bar) { | |||
| return foo.getName().compareTo(bar.getName()); | |||
| } | |||
| } | |||
| @@ -0,0 +1,62 @@ | |||
| /* | |||
| * Copyright 2005 The Apache Software Foundation | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * | |||
| */ | |||
| package org.apache.tools.ant.types.resources.comparators; | |||
| import java.util.Comparator; | |||
| import org.apache.tools.ant.types.Resource; | |||
| /** | |||
| * Abstract Resource Comparator. | |||
| * @since Ant 1.7 | |||
| */ | |||
| public abstract class ResourceComparator implements Comparator { | |||
| /** | |||
| * Compare two objects. | |||
| * @param foo the first Object. | |||
| * @param bar the second Object. | |||
| * @return a negative integer, zero, or a positive integer as the first | |||
| * argument is less than, equal to, or greater than the second. | |||
| * @throws ClassCastException if either argument is null. | |||
| */ | |||
| public final int compare(Object foo, Object bar) { | |||
| return resourceCompare((Resource) foo, (Resource) bar); | |||
| } | |||
| /** | |||
| * Test for equality with this ResourceComparator. | |||
| * @param o the Object to compare against. | |||
| * @return true if the specified Object equals this one. | |||
| */ | |||
| public final boolean equals(Object o) { | |||
| if (o == null) { | |||
| return false; | |||
| } | |||
| return o == this || o.getClass().equals(getClass()); | |||
| } | |||
| /** | |||
| * Compare two Resources. | |||
| * @param foo the first Resource. | |||
| * @param bar the second Resource. | |||
| * @return a negative integer, zero, or a positive integer as the first | |||
| * argument is less than, equal to, or greater than the second. | |||
| */ | |||
| protected abstract int resourceCompare(Resource foo, Resource bar); | |||
| } | |||
| @@ -0,0 +1,56 @@ | |||
| /* | |||
| * Copyright 2005 The Apache Software Foundation | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * | |||
| */ | |||
| package org.apache.tools.ant.types.resources.comparators; | |||
| import org.apache.tools.ant.BuildException; | |||
| import org.apache.tools.ant.types.Resource; | |||
| /** | |||
| * Reverses another ResourceComparator. If no nested ResourceComparator | |||
| * is supplied, the compared Resources' natural order will be reversed. | |||
| * @since Ant 1.7 | |||
| */ | |||
| public class Reverse extends ResourceComparator { | |||
| private static final String ONE_NESTED | |||
| = "You must not nest more than one ResourceComparator for reversal."; | |||
| private ResourceComparator nested; | |||
| /** | |||
| * Add the ResourceComparator to reverse. | |||
| * @param nested the ResourceComparator to add. | |||
| */ | |||
| public void add(ResourceComparator c) { | |||
| if (nested != null) { | |||
| throw new BuildException(ONE_NESTED); | |||
| } | |||
| nested = c; | |||
| } | |||
| /** | |||
| * Compare two Resources. | |||
| * @param foo the first Resource. | |||
| * @param bar the second Resource. | |||
| * @return a negative integer, zero, or a positive integer as the first | |||
| * argument is greater than, equal to, or less than the second. | |||
| */ | |||
| protected int resourceCompare(Resource foo, Resource bar) { | |||
| return -1 * (nested == null | |||
| ? foo.compareTo(bar) : nested.compare(foo, bar)); | |||
| } | |||
| } | |||
| @@ -0,0 +1,37 @@ | |||
| /* | |||
| * Copyright 2005 The Apache Software Foundation | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * | |||
| */ | |||
| package org.apache.tools.ant.types.resources.comparators; | |||
| import org.apache.tools.ant.types.Resource; | |||
| /** | |||
| * Compares Resources by size. | |||
| * @since Ant 1.7 | |||
| */ | |||
| public class Size extends ResourceComparator { | |||
| /** | |||
| * Compare two Resources. | |||
| * @param foo the first Resource. | |||
| * @param bar the second Resource. | |||
| * @return a negative integer, zero, or a positive integer as the first | |||
| * argument is less than, equal to, or greater than the second. | |||
| */ | |||
| protected int resourceCompare(Resource foo, Resource bar) { | |||
| return (int) (foo.getSize() - bar.getSize()); | |||
| } | |||
| } | |||
| @@ -0,0 +1,43 @@ | |||
| /* | |||
| * Copyright 2005 The Apache Software Foundation | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * | |||
| */ | |||
| package org.apache.tools.ant.types.resources.comparators; | |||
| import org.apache.tools.ant.types.Resource; | |||
| /** | |||
| * Compares Resources by is-directory status. As a container | |||
| * of files, a directory is deemed "greater" than a file. | |||
| * @since Ant 1.7 | |||
| */ | |||
| public class Type extends ResourceComparator { | |||
| /** | |||
| * Compare two Resources. | |||
| * @param foo the first Resource. | |||
| * @param bar the second Resource. | |||
| * @return a negative integer, zero, or a positive integer as the first | |||
| * argument is less than, equal to, or greater than the second. | |||
| */ | |||
| protected int resourceCompare(Resource foo, Resource bar) { | |||
| boolean f = foo.isDirectory(); | |||
| if (f == bar.isDirectory()) { | |||
| return 0; | |||
| } | |||
| return f ? 1 : -1; | |||
| } | |||
| } | |||
| @@ -0,0 +1,43 @@ | |||
| /* | |||
| * Copyright 2005 The Apache Software Foundation | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * | |||
| */ | |||
| package org.apache.tools.ant.types.resources.selectors; | |||
| import java.util.Iterator; | |||
| import org.apache.tools.ant.types.Resource; | |||
| /** | |||
| * And ResourceSelector. | |||
| * @since Ant 1.7 | |||
| */ | |||
| public class And extends ResourceSelectorContainer implements ResourceSelector { | |||
| /** | |||
| * Return true if this Resource is selected. | |||
| * @param r the Resource to check. | |||
| * @return whether the Resource was selected. | |||
| */ | |||
| public boolean isSelected(Resource r) { | |||
| for (Iterator i = getSelectors(); i.hasNext();) { | |||
| if (!((ResourceSelector) i.next()).isSelected(r)) { | |||
| return false; | |||
| } | |||
| } | |||
| return true; | |||
| } | |||
| } | |||
| @@ -0,0 +1,161 @@ | |||
| /* | |||
| * Copyright 2005 The Apache Software Foundation | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * | |||
| */ | |||
| package org.apache.tools.ant.types.resources.selectors; | |||
| import java.text.DateFormat; | |||
| import java.text.SimpleDateFormat; | |||
| import java.text.ParseException; | |||
| import java.util.Locale; | |||
| import org.apache.tools.ant.BuildException; | |||
| import org.apache.tools.ant.types.Resource; | |||
| import org.apache.tools.ant.types.TimeComparison; | |||
| import org.apache.tools.ant.util.FileUtils; | |||
| /** | |||
| * Date ResourceSelector. Based on the date FileSelector, with the most | |||
| * notable difference being the lack of support for the includedirs attribute. | |||
| * It is recommended that the effect of includeDirs = "false" be achieved for | |||
| * resources by enclosing a "dir" Type ResourceSelector and a Date | |||
| * ResourceSelector in an Or ResourceSelector. | |||
| * @since Ant 1.7 | |||
| */ | |||
| public class Date implements ResourceSelector { | |||
| private static final String MILLIS_OR_DATETIME | |||
| = "Either the millis or the datetime attribute must be set."; | |||
| private static final FileUtils FILE_UTILS = FileUtils.getFileUtils(); | |||
| private Long millis = null; | |||
| private String dateTime = null; | |||
| private String pattern = null; | |||
| private TimeComparison when = TimeComparison.EQUAL; | |||
| private long granularity = FILE_UTILS.getFileTimestampGranularity(); | |||
| /** | |||
| * Set the date/time in milliseconds since 1970. | |||
| * @param m the number of millis. | |||
| */ | |||
| public synchronized void setMillis(long m) { | |||
| millis = new Long(m); | |||
| } | |||
| /** | |||
| * Get the date/time in ms. | |||
| * @return long number of millis since 1970. | |||
| */ | |||
| public synchronized long getMillis() { | |||
| return millis == null ? -1L : millis.longValue(); | |||
| } | |||
| /** | |||
| * Set the date and time as a String. | |||
| * @param s the date & time to use. | |||
| */ | |||
| public synchronized void setDateTime(String s) { | |||
| dateTime = s; | |||
| millis = null; | |||
| } | |||
| /** | |||
| * Get the date & time in String format. | |||
| * @return a String representing a date & time. | |||
| */ | |||
| public synchronized String getDatetime() { | |||
| return dateTime; | |||
| } | |||
| /** | |||
| * Set the granularity to use for this ResourceSelector. | |||
| * @param g the timestamp granularity. | |||
| */ | |||
| public synchronized void setGranularity(long g) { | |||
| granularity = g; | |||
| } | |||
| /** | |||
| * Get the timestamp granularity used by this ResourceSelector. | |||
| * @return the long granularity. | |||
| */ | |||
| public synchronized long getGranularity() { | |||
| return granularity; | |||
| } | |||
| /** | |||
| * Set the optional pattern to use with the datetime attribute. | |||
| * @param p the SimpleDateFormat-compatible pattern string. | |||
| */ | |||
| public synchronized void setPattern(String p) { | |||
| pattern = p; | |||
| } | |||
| /** | |||
| * Get the pattern for use with the datetime attribute. | |||
| * @return a SimpleDateFormat-compatible pattern string. | |||
| */ | |||
| public synchronized String getPattern() { | |||
| return pattern; | |||
| } | |||
| /** | |||
| * Set the comparison mode. | |||
| * @param c a TimeComparison object. | |||
| */ | |||
| public synchronized void setWhen(TimeComparison c) { | |||
| when = c; | |||
| } | |||
| /** | |||
| * Get the comparison mode. | |||
| * @return a TimeComparison object. | |||
| */ | |||
| public synchronized TimeComparison getWhen() { | |||
| return when; | |||
| } | |||
| /** | |||
| * Return true if this Resource is selected. | |||
| * @param r the Resource to check. | |||
| * @return whether the Resource was selected. | |||
| */ | |||
| public synchronized boolean isSelected(Resource r) { | |||
| if (dateTime == null && millis == null) { | |||
| throw new BuildException(MILLIS_OR_DATETIME); | |||
| } | |||
| if (millis == null) { | |||
| DateFormat df = ((pattern == null) | |||
| ? DateFormat.getDateTimeInstance( | |||
| DateFormat.SHORT, DateFormat.SHORT, Locale.US) | |||
| : new SimpleDateFormat(pattern)); | |||
| try { | |||
| long m = df.parse(dateTime).getTime(); | |||
| if (m < 0) { | |||
| throw new BuildException("Date of " + dateTime | |||
| + " results in negative milliseconds value" | |||
| + " relative to epoch (January 1, 1970, 00:00:00 GMT)."); | |||
| } | |||
| setMillis(m); | |||
| } catch (ParseException pe) { | |||
| throw new BuildException("Date of " + dateTime | |||
| + " Cannot be parsed correctly. It should be in" | |||
| + (pattern == null | |||
| ? " MM/DD/YYYY HH:MM AM_PM" : pattern) + " format."); | |||
| } | |||
| } | |||
| return when.evaluate(r.getLastModified(), millis.longValue(), granularity); | |||
| } | |||
| } | |||
| @@ -0,0 +1,36 @@ | |||
| /* | |||
| * Copyright 2005 The Apache Software Foundation | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * | |||
| */ | |||
| package org.apache.tools.ant.types.resources.selectors; | |||
| import org.apache.tools.ant.types.Resource; | |||
| /** | |||
| * Exists ResourceSelector. | |||
| * @since Ant 1.7 | |||
| */ | |||
| public class Exists implements ResourceSelector { | |||
| /** | |||
| * Return true if this Resource is selected. | |||
| * @param r the Resource to check. | |||
| * @return whether the Resource was selected. | |||
| */ | |||
| public boolean isSelected(Resource r) { | |||
| return r.isExists(); | |||
| } | |||
| } | |||
| @@ -0,0 +1,129 @@ | |||
| /* | |||
| * Copyright 2005 The Apache Software Foundation | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * | |||
| */ | |||
| package org.apache.tools.ant.types.resources.selectors; | |||
| import org.apache.tools.ant.Project; | |||
| import org.apache.tools.ant.ProjectHelper; | |||
| import org.apache.tools.ant.BuildException; | |||
| import org.apache.tools.ant.ComponentHelper; | |||
| import org.apache.tools.ant.AntTypeDefinition; | |||
| import org.apache.tools.ant.types.Resource; | |||
| /** | |||
| * InstanceOf ResourceSelector. | |||
| * @since Ant 1.7 | |||
| */ | |||
| public class InstanceOf implements ResourceSelector { | |||
| private static final String ONE_ONLY = "Exactly one of class|type must be set."; | |||
| private Project project; | |||
| private Class clazz; | |||
| private String type; | |||
| private String uri; | |||
| /** | |||
| * Set the Project instance for this InstanceOf selector. | |||
| * @param p the Project instance used for type comparisons. | |||
| */ | |||
| public void setProject(Project p) { | |||
| project = p; | |||
| } | |||
| /** | |||
| * Set the class to compare against. | |||
| * @param c the class. | |||
| */ | |||
| public void setClass(Class c) { | |||
| if (clazz != null) { | |||
| throw new BuildException("The class attribute has already been set."); | |||
| } | |||
| clazz = c; | |||
| } | |||
| /** | |||
| * Set the Ant type to compare against. | |||
| * @param s the type name. | |||
| */ | |||
| public void setType(String s) { | |||
| type = s; | |||
| } | |||
| /** | |||
| * Set the URI in which the Ant type, if specified, should be defined. | |||
| * @param u the URI. | |||
| */ | |||
| public void setURI(String u) { | |||
| uri = u; | |||
| } | |||
| /** | |||
| * Get the comparison class. | |||
| * @return the Class object. | |||
| */ | |||
| public Class getCheckClass() { | |||
| return clazz; | |||
| } | |||
| /** | |||
| * Get the comparison type. | |||
| * @return the String typename. | |||
| */ | |||
| public String getType() { | |||
| return type; | |||
| } | |||
| /** | |||
| * Get the type's URI. | |||
| * @return the String URI. | |||
| */ | |||
| public String getURI() { | |||
| return uri; | |||
| } | |||
| /** | |||
| * Return true if this Resource is selected. | |||
| * @param r the Resource to check. | |||
| * @return whether the Resource was selected. | |||
| * @throws BuildException if an error occurs. | |||
| */ | |||
| public boolean isSelected(Resource r) { | |||
| if ((clazz == null) == (type == null)) { | |||
| throw new BuildException(ONE_ONLY); | |||
| } | |||
| Class c = clazz; | |||
| if (type != null) { | |||
| if (project == null) { | |||
| throw new BuildException( | |||
| "No project set for InstanceOf ResourceSelector; " | |||
| + "the type attribute is invalid."); | |||
| } | |||
| AntTypeDefinition d = ComponentHelper.getComponentHelper( | |||
| project).getDefinition(ProjectHelper.genComponentName(uri, type)); | |||
| if (d == null) { | |||
| throw new BuildException("type " + type + " not found."); | |||
| } | |||
| try { | |||
| c = d.innerGetTypeClass(); | |||
| } catch (ClassNotFoundException e) { | |||
| throw new BuildException(e); | |||
| } | |||
| } | |||
| return c.isAssignableFrom(r.getClass()); | |||
| } | |||
| } | |||
| @@ -0,0 +1,69 @@ | |||
| /* | |||
| * Copyright 2005 The Apache Software Foundation | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * | |||
| */ | |||
| package org.apache.tools.ant.types.resources.selectors; | |||
| import java.util.Iterator; | |||
| import org.apache.tools.ant.types.Resource; | |||
| /** | |||
| * Majority ResourceSelector. | |||
| * @since Ant 1.7 | |||
| */ | |||
| public class Majority | |||
| extends ResourceSelectorContainer implements ResourceSelector { | |||
| private boolean tie = true; | |||
| /** | |||
| * Set whether ties are allowed. | |||
| * @param b whether a tie is a pass. | |||
| */ | |||
| public synchronized void setAllowtie(boolean b) { | |||
| tie = b; | |||
| } | |||
| /** | |||
| * Return true if this Resource is selected. | |||
| * @param r the Resource to check. | |||
| * @return whether the Resource was selected. | |||
| */ | |||
| public synchronized boolean isSelected(Resource r) { | |||
| int passed = 0; | |||
| int failed = 0; | |||
| int count = selectorCount(); | |||
| boolean even = count % 2 == 0; | |||
| int threshold = count / 2; | |||
| for (Iterator i = getSelectors(); i.hasNext();) { | |||
| if (((ResourceSelector) i.next()).isSelected(r)) { | |||
| ++passed; | |||
| if (passed > threshold || (even && tie && passed == threshold)) { | |||
| return true; | |||
| } | |||
| } else { | |||
| ++failed; | |||
| if (failed > threshold || (even && !tie && failed == threshold)) { | |||
| return false; | |||
| } | |||
| } | |||
| } | |||
| //dummy | |||
| return false; | |||
| } | |||
| } | |||
| @@ -0,0 +1,76 @@ | |||
| /* | |||
| * Copyright 2005 The Apache Software Foundation | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * | |||
| */ | |||
| package org.apache.tools.ant.types.resources.selectors; | |||
| import org.apache.tools.ant.types.Resource; | |||
| import org.apache.tools.ant.types.selectors.SelectorUtils; | |||
| /** | |||
| * Name ResourceSelector. | |||
| * @since Ant 1.7 | |||
| */ | |||
| public class Name implements ResourceSelector { | |||
| private String pattern; | |||
| private boolean cs = true; | |||
| /** | |||
| * Set the pattern to compare names against. | |||
| * @param n the pattern String to set. | |||
| */ | |||
| public void setName(String n) { | |||
| pattern = n; | |||
| } | |||
| /** | |||
| * Get the pattern used by this Name ResourceSelector. | |||
| * @return the String selection pattern. | |||
| */ | |||
| public String getName() { | |||
| return pattern; | |||
| } | |||
| /** | |||
| * Set whether the name comparisons are case-sensitive. | |||
| * @param b boolean case-sensitivity flag. | |||
| */ | |||
| public void setCaseSensitive(boolean b) { | |||
| cs = b; | |||
| } | |||
| /** | |||
| * Learn whether this Name ResourceSelector is case-sensitive. | |||
| * @return boolean case-sensitivity flag. | |||
| */ | |||
| public boolean isCaseSensitive() { | |||
| return cs; | |||
| } | |||
| /** | |||
| * Return true if this Resource is selected. | |||
| * @param r the Resource to check. | |||
| * @return whether the Resource was selected. | |||
| */ | |||
| public boolean isSelected(Resource r) { | |||
| String n = r.getName(); | |||
| if (SelectorUtils.match(pattern, n, cs)) { | |||
| return true; | |||
| } | |||
| String s = r.toString(); | |||
| return s.equals(n) ? false : SelectorUtils.match(pattern, s, cs); | |||
| } | |||
| } | |||
| @@ -0,0 +1,43 @@ | |||
| /* | |||
| * Copyright 2005 The Apache Software Foundation | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * | |||
| */ | |||
| package org.apache.tools.ant.types.resources.selectors; | |||
| import java.util.Iterator; | |||
| import org.apache.tools.ant.types.Resource; | |||
| /** | |||
| * None ResourceSelector. | |||
| * @since Ant 1.7 | |||
| */ | |||
| public class None | |||
| extends ResourceSelectorContainer implements ResourceSelector { | |||
| /** | |||
| * Return true if this Resource is selected. | |||
| * @param r the Resource to check. | |||
| * @return whether the Resource was selected. | |||
| */ | |||
| public boolean isSelected(Resource r) { | |||
| boolean none = true; | |||
| for (Iterator i = getSelectors(); none && i.hasNext();) { | |||
| none = !((ResourceSelector) i.next()).isSelected(r); | |||
| } | |||
| return none; | |||
| } | |||
| } | |||
| @@ -0,0 +1,65 @@ | |||
| /* | |||
| * Copyright 2005 The Apache Software Foundation | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * | |||
| */ | |||
| package org.apache.tools.ant.types.resources.selectors; | |||
| import org.apache.tools.ant.types.Resource; | |||
| /** | |||
| * Not ResourceSelector. | |||
| * @since Ant 1.7 | |||
| */ | |||
| public class Not implements ResourceSelector { | |||
| private ResourceSelector sel; | |||
| /** | |||
| * Default constructor. | |||
| */ | |||
| public Not() { | |||
| } | |||
| /** | |||
| * Convenience constructor. | |||
| * @param s the ResourceSelector to negate. | |||
| */ | |||
| public Not(ResourceSelector s) { | |||
| add(s); | |||
| } | |||
| /** | |||
| * Set the ResourceSelector. | |||
| * @param s the ResourceSelector to negate. | |||
| * @throws IllegalStateException if already set. | |||
| */ | |||
| public void add(ResourceSelector s) { | |||
| if (sel != null) { | |||
| throw new IllegalStateException( | |||
| "The Not ResourceSelector accepts a single nested ResourceSelector"); | |||
| } | |||
| sel = s; | |||
| } | |||
| /** | |||
| * Return true if this Resource is selected. | |||
| * @param r the Resource to check. | |||
| * @return whether the Resource was selected. | |||
| */ | |||
| public boolean isSelected(Resource r) { | |||
| return !(sel.isSelected(r)); | |||
| } | |||
| } | |||
| @@ -0,0 +1,43 @@ | |||
| /* | |||
| * Copyright 2005 The Apache Software Foundation | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * | |||
| */ | |||
| package org.apache.tools.ant.types.resources.selectors; | |||
| import java.util.Iterator; | |||
| import org.apache.tools.ant.types.Resource; | |||
| /** | |||
| * Or ResourceSelector. | |||
| * @since Ant 1.7 | |||
| */ | |||
| public class Or extends ResourceSelectorContainer implements ResourceSelector { | |||
| /** | |||
| * Return true if this Resource is selected. | |||
| * @param r the Resource to check. | |||
| * @return whether the Resource was selected. | |||
| */ | |||
| public boolean isSelected(Resource r) { | |||
| for (Iterator i = getSelectors(); i.hasNext();) { | |||
| if (((ResourceSelector) i.next()).isSelected(r)) { | |||
| return true; | |||
| } | |||
| } | |||
| return false; | |||
| } | |||
| } | |||
| @@ -0,0 +1,34 @@ | |||
| /* | |||
| * Copyright 2005 The Apache Software Foundation | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * | |||
| */ | |||
| package org.apache.tools.ant.types.resources.selectors; | |||
| import org.apache.tools.ant.types.Resource; | |||
| /** | |||
| * Interface for a Resource selector. | |||
| * @since Ant 1.7 | |||
| */ | |||
| public interface ResourceSelector { | |||
| /** | |||
| * Return true if this Resource is selected. | |||
| * @param r the Resource to check. | |||
| * @return whether the Resource was selected. | |||
| */ | |||
| public boolean isSelected(Resource r); | |||
| } | |||
| @@ -0,0 +1,111 @@ | |||
| /* | |||
| * Copyright 2005 The Apache Software Foundation | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * | |||
| */ | |||
| package org.apache.tools.ant.types.resources.selectors; | |||
| import java.util.Stack; | |||
| import java.util.Vector; | |||
| import java.util.Iterator; | |||
| import java.util.Collections; | |||
| import org.apache.tools.ant.Project; | |||
| import org.apache.tools.ant.BuildException; | |||
| import org.apache.tools.ant.types.DataType; | |||
| /** | |||
| * ResourceSelector container. | |||
| * @since Ant 1.7 | |||
| */ | |||
| public class ResourceSelectorContainer extends DataType { | |||
| private Vector v = new Vector(); | |||
| /** | |||
| * Add a ResourceSelector to the container. | |||
| * @param s the ResourceSelector to add. | |||
| */ | |||
| public void add(ResourceSelector s) { | |||
| if (isReference()) { | |||
| throw noChildrenAllowed(); | |||
| } | |||
| if (s == null) { | |||
| return; | |||
| } | |||
| v.add(s); | |||
| setChecked(false); | |||
| } | |||
| /** | |||
| * Learn whether this ResourceSelectorContainer has selectors. | |||
| * @return boolean indicating whether selectors have been added to the container. | |||
| */ | |||
| public boolean hasSelectors() { | |||
| if (isReference()) { | |||
| return ((ResourceSelectorContainer) getCheckedRef()).hasSelectors(); | |||
| } | |||
| dieOnCircularReference(); | |||
| return !v.isEmpty(); | |||
| } | |||
| /** | |||
| * Get the count of nested selectors. | |||
| * @return the selector count as int. | |||
| */ | |||
| public int selectorCount() { | |||
| if (isReference()) { | |||
| return ((ResourceSelectorContainer) getCheckedRef()).selectorCount(); | |||
| } | |||
| dieOnCircularReference(); | |||
| return v.size(); | |||
| } | |||
| /** | |||
| * Return an Iterator over the nested selectors. | |||
| * @return Iterator of ResourceSelectors. | |||
| */ | |||
| public Iterator getSelectors() { | |||
| if (isReference()) { | |||
| return ((ResourceSelectorContainer) getCheckedRef()).getSelectors(); | |||
| } | |||
| dieOnCircularReference(); | |||
| return Collections.unmodifiableList(v).iterator(); | |||
| } | |||
| /** | |||
| * Overrides the version from DataType to recurse on nested ResourceSelectors. | |||
| * @param stk the Stack of references. | |||
| * @param p the Project to resolve against. | |||
| * @throws BuildException on error. | |||
| */ | |||
| public void dieOnCircularReference(Stack stk, Project p) { | |||
| if (isChecked()) { | |||
| return; | |||
| } | |||
| if (isReference()) { | |||
| super.dieOnCircularReference(stk, p); | |||
| } else { | |||
| for (Iterator i = v.iterator(); i.hasNext();) { | |||
| Object o = i.next(); | |||
| if (o instanceof DataType) { | |||
| stk.push(o); | |||
| invokeCircularReferenceCheck((DataType) o, stk, p); | |||
| } | |||
| } | |||
| setChecked(true); | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,72 @@ | |||
| /* | |||
| * Copyright 2005 The Apache Software Foundation | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * | |||
| */ | |||
| package org.apache.tools.ant.types.resources.selectors; | |||
| import org.apache.tools.ant.types.Resource; | |||
| import org.apache.tools.ant.types.Comparison; | |||
| /** | |||
| * Size ResourceSelector. | |||
| * @since Ant 1.7 | |||
| */ | |||
| public class Size implements ResourceSelector { | |||
| private long size = -1; | |||
| private Comparison when = Comparison.EQUAL; | |||
| /** | |||
| * Set the size to compare against. | |||
| * @param l the long resource size. | |||
| */ | |||
| public void setSize(long l) { | |||
| size = l; | |||
| } | |||
| /** | |||
| * Get the size compared to by this Size ResourceSelector. | |||
| * @return the long resource size. | |||
| */ | |||
| public long getSize() { | |||
| return size; | |||
| } | |||
| /** | |||
| * Set the comparison mode. | |||
| * @param c a Comparison object. | |||
| */ | |||
| public void setWhen(Comparison c) { | |||
| when = c; | |||
| } | |||
| /** | |||
| * Get the comparison mode. | |||
| * @return a Comparison object. | |||
| */ | |||
| public Comparison getWhen() { | |||
| return when; | |||
| } | |||
| /** | |||
| * Return true if this Resource is selected. | |||
| * @param r the Resource to check. | |||
| * @return whether the Resource was selected. | |||
| */ | |||
| public boolean isSelected(Resource r) { | |||
| long diff = r.getSize() - size; | |||
| return when.evaluate(diff == 0 ? 0 : (int) (diff / Math.abs(diff))); | |||
| } | |||
| } | |||
| @@ -0,0 +1,67 @@ | |||
| /* | |||
| * Copyright 2005 The Apache Software Foundation | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * | |||
| */ | |||
| package org.apache.tools.ant.types.resources.selectors; | |||
| import org.apache.tools.ant.BuildException; | |||
| import org.apache.tools.ant.types.Resource; | |||
| import org.apache.tools.ant.types.EnumeratedAttribute; | |||
| /** | |||
| * Type file/dir ResourceSelector. | |||
| * @since Ant 1.7 | |||
| */ | |||
| public class Type implements ResourceSelector { | |||
| /** | |||
| * Implements the type attribute. | |||
| */ | |||
| public static class FileDir extends EnumeratedAttribute { | |||
| private static final String[] VALUES = new String[] {"file", "dir"}; | |||
| /** | |||
| * Return the possible values. | |||
| * @return a String array. | |||
| */ | |||
| public String[] getValues() { | |||
| return VALUES; | |||
| } | |||
| } | |||
| private FileDir type = null; | |||
| /** | |||
| * Set type; file|dir. | |||
| * @param fd a FileDir object. | |||
| */ | |||
| public void setType(FileDir fd) { | |||
| type = fd; | |||
| } | |||
| /** | |||
| * Return true if this Resource is selected. | |||
| * @param r the Resource to check. | |||
| * @return whether the Resource was selected. | |||
| */ | |||
| public boolean isSelected(Resource r) { | |||
| if (type == null) { | |||
| throw new BuildException("The type attribute is required."); | |||
| } | |||
| int i = type.getIndex(); | |||
| return r.isDirectory() ? i == 1 : i == 0; | |||
| } | |||
| } | |||
| @@ -0,0 +1,143 @@ | |||
| /* | |||
| * Copyright 2005 The Apache Software Foundation | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * | |||
| */ | |||
| package org.apache.tools.ant.util; | |||
| import java.io.InputStream; | |||
| import java.io.BufferedInputStream; | |||
| import java.io.IOException; | |||
| import java.util.Iterator; | |||
| import org.apache.tools.ant.Project; | |||
| import org.apache.tools.ant.ProjectComponent; | |||
| import org.apache.tools.ant.types.Resource; | |||
| import org.apache.tools.ant.types.ResourceCollection; | |||
| /** | |||
| * Special <code>InputStream</code> that will | |||
| * concatenate the contents of Resources from a single ResourceCollection. | |||
| */ | |||
| public class ConcatResourceInputStream extends InputStream { | |||
| private static final int EOF = -1; | |||
| private boolean eof = false; | |||
| private Iterator iter; | |||
| private InputStream currentStream; | |||
| private ProjectComponent managingPc; | |||
| private boolean ignoreErrors = false; | |||
| /** | |||
| * Construct a new ConcatResourceInputStream | |||
| * for the specified ResourceCollection. | |||
| * @param rc the ResourceCollection to combine. | |||
| * @throws IOException if I/O errors occur. | |||
| */ | |||
| public ConcatResourceInputStream(ResourceCollection rc) throws IOException { | |||
| iter = rc.iterator(); | |||
| } | |||
| /** | |||
| * Set whether this ConcatResourceInputStream ignores errors. | |||
| * @param b whether to ignore errors. | |||
| */ | |||
| public void setIgnoreErrors(boolean b) { | |||
| ignoreErrors = b; | |||
| } | |||
| /** | |||
| * Find out whether this ConcatResourceInputStream ignores errors. | |||
| * @return boolean ignore-errors flag. | |||
| */ | |||
| public boolean isIgnoreErrors() { | |||
| return ignoreErrors; | |||
| } | |||
| // inherit doc | |||
| public void close() throws IOException { | |||
| closeCurrent(); | |||
| eof = true; | |||
| } | |||
| // inherit doc | |||
| public int read() throws IOException { | |||
| if (eof) { | |||
| return EOF; | |||
| } | |||
| int result = readCurrent(); | |||
| if (result == EOF) { | |||
| nextResource(); | |||
| result = readCurrent(); | |||
| } | |||
| return result; | |||
| } | |||
| /** | |||
| * Set a managing <code>ProjectComponent</code> for | |||
| * this <code>ConcatResourceInputStream</code>. | |||
| * @param task the managing <code>Task</code>. | |||
| */ | |||
| public void setManagingComponent(ProjectComponent pc) { | |||
| this.managingPc = pc; | |||
| } | |||
| /** | |||
| * Log a message with the specified logging level. | |||
| * @param message the <code>String</code> message. | |||
| * @param loglevel the <code>int</code> logging level. | |||
| */ | |||
| public void log(String message, int loglevel) { | |||
| if (managingPc != null) { | |||
| managingPc.log(message, loglevel); | |||
| } else { | |||
| if (loglevel > Project.MSG_WARN) { | |||
| System.out.println(message); | |||
| } else { | |||
| System.err.println(message); | |||
| } | |||
| } | |||
| } | |||
| private int readCurrent() throws IOException { | |||
| return (eof || currentStream == null) ? EOF : currentStream.read(); | |||
| } | |||
| private void nextResource() throws IOException { | |||
| closeCurrent(); | |||
| while (iter.hasNext()) { | |||
| Resource r = (Resource) iter.next(); | |||
| if (!r.isExists()) { | |||
| continue; | |||
| } | |||
| log("Concating " + r.toLongString(), Project.MSG_VERBOSE); | |||
| try { | |||
| currentStream = new BufferedInputStream(r.getInputStream()); | |||
| return; | |||
| } catch (IOException eyeOhEx) { | |||
| if (!ignoreErrors) { | |||
| log("Failed to get input stream for " + r, Project.MSG_ERR); | |||
| throw eyeOhEx; | |||
| } | |||
| } | |||
| } | |||
| eof = true; | |||
| } | |||
| private void closeCurrent() { | |||
| FileUtils.close(currentStream); | |||
| currentStream = null; | |||
| } | |||
| } | |||
| @@ -45,7 +45,10 @@ import org.apache.tools.ant.BuildException; | |||
| import org.apache.tools.ant.Project; | |||
| import org.apache.tools.ant.filters.util.ChainReaderHelper; | |||
| import org.apache.tools.ant.taskdefs.condition.Os; | |||
| import org.apache.tools.ant.types.Resource; | |||
| import org.apache.tools.ant.types.FilterSetCollection; | |||
| import org.apache.tools.ant.types.resources.Touchable; | |||
| import org.apache.tools.ant.types.resources.FileResource; | |||
| import org.apache.tools.ant.launch.Locator; | |||
| /** | |||
| @@ -521,139 +524,204 @@ public class FileUtils { | |||
| String inputEncoding, String outputEncoding, | |||
| Project project) | |||
| throws IOException { | |||
| copyResource(new FileResource(sourceFile), new FileResource(destFile), | |||
| filters, filterChains, overwrite, preserveLastModified, | |||
| inputEncoding, outputEncoding, project); | |||
| } | |||
| if (overwrite || !destFile.exists() | |||
| || destFile.lastModified() < sourceFile.lastModified()) { | |||
| /** | |||
| * Convenience method to copy content from one Resource to another. | |||
| * No filtering is performed. | |||
| * | |||
| * @param source the Resource to copy from. | |||
| * Must not be <code>null</code>. | |||
| * @param dest the Resource to copy to. | |||
| * Must not be <code>null</code>. | |||
| * | |||
| * @throws IOException if the copying fails. | |||
| * | |||
| * @since Ant 1.7 | |||
| */ | |||
| public void copyResource(Resource source, Resource dest) throws IOException { | |||
| copyResource(source, dest, null); | |||
| } | |||
| if (destFile.exists() && destFile.isFile()) { | |||
| destFile.delete(); | |||
| } | |||
| // ensure that parent dir of dest file exists! | |||
| // not using getParentFile method to stay 1.1 compat | |||
| File parent = destFile.getParentFile(); | |||
| if (parent != null && !parent.exists()) { | |||
| parent.mkdirs(); | |||
| /** | |||
| * Convenience method to copy content from one Resource to another. | |||
| * No filtering is performed. | |||
| * | |||
| * @param source the Resource to copy from. | |||
| * Must not be <code>null</code>. | |||
| * @param dest the Resource to copy to. | |||
| * Must not be <code>null</code>. | |||
| * @param project the project instance. | |||
| * | |||
| * @throws IOException if the copying fails. | |||
| * | |||
| * @since Ant 1.7 | |||
| */ | |||
| public void copyResource(Resource source, Resource dest, Project project) | |||
| throws IOException { | |||
| copyResource(source, dest, null, null, false, | |||
| false, null, null, project); | |||
| } | |||
| /** | |||
| * Convenience method to copy content from one Resource to another | |||
| * specifying whether token filtering must be used, whether filter chains | |||
| * must be used, whether newer destination files may be overwritten and | |||
| * whether the last modified time of <code>dest</code> file should be made | |||
| * equal to the last modified time of <code>source</code>. | |||
| * | |||
| * @param source the Resource to copy from. | |||
| * Must not be <code>null</code>. | |||
| * @param dest the Resource to copy to. | |||
| * Must not be <code>null</code>. | |||
| * @param filters the collection of filters to apply to this copy. | |||
| * @param filterChains filterChains to apply during the copy. | |||
| * @param overwrite Whether or not the destination Resource should be | |||
| * overwritten if it already exists. | |||
| * @param preserveLastModified Whether or not the last modified time of | |||
| * the destination Resource should be set to that | |||
| * of the source. | |||
| * @param inputEncoding the encoding used to read the files. | |||
| * @param outputEncoding the encoding used to write the files. | |||
| * @param project the project instance. | |||
| * | |||
| * @throws IOException if the copying fails. | |||
| * | |||
| * @since Ant 1.7 | |||
| */ | |||
| public void copyResource(Resource source, Resource dest, | |||
| FilterSetCollection filters, Vector filterChains, | |||
| boolean overwrite, boolean preserveLastModified, | |||
| String inputEncoding, String outputEncoding, | |||
| Project project) | |||
| throws IOException { | |||
| if (!overwrite) { | |||
| long slm = source.getLastModified(); | |||
| if (dest.isExists() && slm != 0 | |||
| && dest.getLastModified() > slm) { | |||
| return; | |||
| } | |||
| final boolean filterSetsAvailable = (filters != null | |||
| && filters.hasFilters()); | |||
| final boolean filterChainsAvailable = (filterChains != null | |||
| && filterChains.size() > 0); | |||
| if (filterSetsAvailable) { | |||
| BufferedReader in = null; | |||
| BufferedWriter out = null; | |||
| try { | |||
| if (inputEncoding == null) { | |||
| in = new BufferedReader(new FileReader(sourceFile)); | |||
| } else { | |||
| InputStreamReader isr | |||
| = new InputStreamReader(new FileInputStream(sourceFile), | |||
| inputEncoding); | |||
| in = new BufferedReader(isr); | |||
| } | |||
| if (outputEncoding == null) { | |||
| out = new BufferedWriter(new FileWriter(destFile)); | |||
| } | |||
| final boolean filterSetsAvailable = (filters != null | |||
| && filters.hasFilters()); | |||
| final boolean filterChainsAvailable = (filterChains != null | |||
| && filterChains.size() > 0); | |||
| if (filterSetsAvailable) { | |||
| BufferedReader in = null; | |||
| BufferedWriter out = null; | |||
| try { | |||
| InputStreamReader isr = null; | |||
| if (inputEncoding == null) { | |||
| isr = new InputStreamReader(source.getInputStream()); | |||
| } else { | |||
| isr = new InputStreamReader(source.getInputStream(), | |||
| inputEncoding); | |||
| } | |||
| in = new BufferedReader(isr); | |||
| OutputStreamWriter osw = null; | |||
| if (outputEncoding == null) { | |||
| osw = new OutputStreamWriter(dest.getOutputStream()); | |||
| } else { | |||
| osw = new OutputStreamWriter(dest.getOutputStream(), | |||
| outputEncoding); | |||
| } | |||
| out = new BufferedWriter(osw); | |||
| if (filterChainsAvailable) { | |||
| ChainReaderHelper crh = new ChainReaderHelper(); | |||
| crh.setBufferSize(BUF_SIZE); | |||
| crh.setPrimaryReader(in); | |||
| crh.setFilterChains(filterChains); | |||
| crh.setProject(project); | |||
| Reader rdr = crh.getAssembledReader(); | |||
| in = new BufferedReader(rdr); | |||
| } | |||
| LineTokenizer lineTokenizer = new LineTokenizer(); | |||
| lineTokenizer.setIncludeDelims(true); | |||
| String newline = null; | |||
| String line = lineTokenizer.getToken(in); | |||
| while (line != null) { | |||
| if (line.length() == 0) { | |||
| // this should not happen, because the lines are | |||
| // returned with the end of line delimiter | |||
| out.newLine(); | |||
| } else { | |||
| OutputStreamWriter osw | |||
| = new OutputStreamWriter(new FileOutputStream(destFile), | |||
| outputEncoding); | |||
| out = new BufferedWriter(osw); | |||
| } | |||
| if (filterChainsAvailable) { | |||
| ChainReaderHelper crh = new ChainReaderHelper(); | |||
| crh.setBufferSize(BUF_SIZE); | |||
| crh.setPrimaryReader(in); | |||
| crh.setFilterChains(filterChains); | |||
| crh.setProject(project); | |||
| Reader rdr = crh.getAssembledReader(); | |||
| in = new BufferedReader(rdr); | |||
| } | |||
| LineTokenizer lineTokenizer = new LineTokenizer(); | |||
| lineTokenizer.setIncludeDelims(true); | |||
| String newline = null; | |||
| String line = lineTokenizer.getToken(in); | |||
| while (line != null) { | |||
| if (line.length() == 0) { | |||
| // this should not happen, because the lines are | |||
| // returned with the end of line delimiter | |||
| out.newLine(); | |||
| } else { | |||
| newline = filters.replaceTokens(line); | |||
| out.write(newline); | |||
| } | |||
| line = lineTokenizer.getToken(in); | |||
| newline = filters.replaceTokens(line); | |||
| out.write(newline); | |||
| } | |||
| } finally { | |||
| close(out); | |||
| close(in); | |||
| line = lineTokenizer.getToken(in); | |||
| } | |||
| } else if (filterChainsAvailable | |||
| || (inputEncoding != null | |||
| && !inputEncoding.equals(outputEncoding)) | |||
| || (inputEncoding == null && outputEncoding != null)) { | |||
| BufferedReader in = null; | |||
| BufferedWriter out = null; | |||
| try { | |||
| if (inputEncoding == null) { | |||
| in = new BufferedReader(new FileReader(sourceFile)); | |||
| } else { | |||
| in = | |||
| new BufferedReader( | |||
| new InputStreamReader( | |||
| new FileInputStream(sourceFile), | |||
| inputEncoding)); | |||
| } | |||
| if (outputEncoding == null) { | |||
| out = new BufferedWriter(new FileWriter(destFile)); | |||
| } else { | |||
| out = | |||
| new BufferedWriter( | |||
| new OutputStreamWriter( | |||
| new FileOutputStream(destFile), | |||
| outputEncoding)); | |||
| } | |||
| if (filterChainsAvailable) { | |||
| ChainReaderHelper crh = new ChainReaderHelper(); | |||
| crh.setBufferSize(BUF_SIZE); | |||
| crh.setPrimaryReader(in); | |||
| crh.setFilterChains(filterChains); | |||
| crh.setProject(project); | |||
| Reader rdr = crh.getAssembledReader(); | |||
| in = new BufferedReader(rdr); | |||
| } | |||
| char[] buffer = new char[BUF_SIZE]; | |||
| while (true) { | |||
| int nRead = in.read(buffer, 0, buffer.length); | |||
| if (nRead == -1) { | |||
| break; | |||
| } | |||
| out.write(buffer, 0, nRead); | |||
| } | |||
| } finally { | |||
| close(out); | |||
| close(in); | |||
| } | |||
| } else { | |||
| FileInputStream in = null; | |||
| FileOutputStream out = null; | |||
| try { | |||
| in = new FileInputStream(sourceFile); | |||
| out = new FileOutputStream(destFile); | |||
| byte[] buffer = new byte[BUF_SIZE]; | |||
| int count = 0; | |||
| do { | |||
| out.write(buffer, 0, count); | |||
| count = in.read(buffer, 0, buffer.length); | |||
| } while (count != -1); | |||
| } finally { | |||
| close(out); | |||
| close(in); | |||
| } finally { | |||
| close(out); | |||
| close(in); | |||
| } | |||
| } else if (filterChainsAvailable | |||
| || (inputEncoding != null | |||
| && !inputEncoding.equals(outputEncoding)) | |||
| || (inputEncoding == null && outputEncoding != null)) { | |||
| BufferedReader in = null; | |||
| BufferedWriter out = null; | |||
| try { | |||
| InputStreamReader isr = null; | |||
| if (inputEncoding == null) { | |||
| isr = new InputStreamReader(source.getInputStream()); | |||
| } else { | |||
| isr = new InputStreamReader(source.getInputStream(), | |||
| inputEncoding); | |||
| } | |||
| in = new BufferedReader(isr); | |||
| OutputStreamWriter osw = null; | |||
| if (outputEncoding == null) { | |||
| osw = new OutputStreamWriter(dest.getOutputStream()); | |||
| } else { | |||
| osw = new OutputStreamWriter(dest.getOutputStream(), | |||
| outputEncoding); | |||
| } | |||
| out = new BufferedWriter(osw); | |||
| if (filterChainsAvailable) { | |||
| ChainReaderHelper crh = new ChainReaderHelper(); | |||
| crh.setBufferSize(BUF_SIZE); | |||
| crh.setPrimaryReader(in); | |||
| crh.setFilterChains(filterChains); | |||
| crh.setProject(project); | |||
| Reader rdr = crh.getAssembledReader(); | |||
| in = new BufferedReader(rdr); | |||
| } | |||
| char[] buffer = new char[BUF_SIZE]; | |||
| while (true) { | |||
| int nRead = in.read(buffer, 0, buffer.length); | |||
| if (nRead == -1) { | |||
| break; | |||
| } | |||
| out.write(buffer, 0, nRead); | |||
| } | |||
| } finally { | |||
| close(out); | |||
| close(in); | |||
| } | |||
| if (preserveLastModified) { | |||
| setFileLastModified(destFile, sourceFile.lastModified()); | |||
| } else { | |||
| InputStream in = null; | |||
| OutputStream out = null; | |||
| try { | |||
| in = source.getInputStream(); | |||
| out = dest.getOutputStream(); | |||
| byte[] buffer = new byte[BUF_SIZE]; | |||
| int count = 0; | |||
| do { | |||
| out.write(buffer, 0, count); | |||
| count = in.read(buffer, 0, buffer.length); | |||
| } while (count != -1); | |||
| } finally { | |||
| close(out); | |||
| close(in); | |||
| } | |||
| } | |||
| if (preserveLastModified && dest instanceof Touchable) { | |||
| setLastModified((Touchable) dest, source.getLastModified()); | |||
| } | |||
| } | |||
| /** | |||
| @@ -665,7 +733,19 @@ public class FileUtils { | |||
| * if this is -1, the current time is used. | |||
| */ | |||
| public void setFileLastModified(File file, long time) { | |||
| file.setLastModified((time < 0) ? System.currentTimeMillis() : time); | |||
| setLastModified(new FileResource(file), time); | |||
| } | |||
| /** | |||
| * Set the last modified time of an object implementing | |||
| * org.apache.tools.ant.types.resources.Touchable . | |||
| * | |||
| * @param t the Touchable whose modified time is to be set. | |||
| * @param time the time to which the last modified time is to be set. | |||
| * if this is -1, the current time is used. | |||
| */ | |||
| public void setLastModified(Touchable t, long time) { | |||
| t.touch((time < 0) ? System.currentTimeMillis() : time); | |||
| } | |||
| /** | |||
| @@ -987,62 +1067,108 @@ public class FileUtils { | |||
| * @since Ant 1.6.3 | |||
| */ | |||
| public boolean contentEquals(File f1, File f2, boolean textfile) throws IOException { | |||
| if (f1.exists() != f2.exists()) { | |||
| return contentEquals(new FileResource(f1), new FileResource(f2), textfile); | |||
| } | |||
| /** | |||
| * Compares the contents of two Resources. | |||
| * | |||
| * @param r1 the Resource whose content is to be compared. | |||
| * @param r2 the other Resource whose content is to be compared. | |||
| * @param text true if the content is to be treated as text and | |||
| * differences in kind of line break are to be ignored. | |||
| * | |||
| * @return true if the content of the Resources is the same. | |||
| * | |||
| * @throws IOException if the Resources cannot be read. | |||
| * @since Ant 1.6.3 | |||
| */ | |||
| public boolean contentEquals(Resource r1, Resource r2, boolean text) throws IOException { | |||
| if (r1.isExists() != r2.isExists()) { | |||
| return false; | |||
| } | |||
| if (!f1.exists()) { | |||
| if (!r1.isExists()) { | |||
| // two not existing files are equal | |||
| return true; | |||
| } | |||
| // should the following two be switched? If f1 and f2 refer to the same file, | |||
| // should the following two be switched? If r1 and r2 refer to the same file, | |||
| // isn't their content equal regardless of whether that file is a directory? | |||
| if (f1.isDirectory() || f2.isDirectory()) { | |||
| if (r1.isDirectory() || r2.isDirectory()) { | |||
| // don't want to compare directory contents for now | |||
| return false; | |||
| } | |||
| if (fileNameEquals(f1, f2)) { | |||
| // same filename => true | |||
| if (r1.equals(r2)) { | |||
| return true; | |||
| } | |||
| return textfile ? textEquals(f1, f2) : binaryEquals(f1, f2); | |||
| if (!text && r1.getSize() != r2.getSize()) { | |||
| return false; | |||
| } | |||
| return compareContent(r1, r2, text) == 0; | |||
| } | |||
| /** | |||
| * Binary compares the contents of two files. | |||
| * Compare the content of two Resources. A nonexistent Resource's | |||
| * content is "less than" that of an existing Resource; a directory-type | |||
| * Resource's content is "less than" that of a file-type Resource. | |||
| * @param r1 the Resource whose content is to be compared. | |||
| * @param r2 the other Resource whose content is to be compared. | |||
| * @param text true if the content is to be treated as text and | |||
| * differences in kind of line break are to be ignored. | |||
| * @return a negative integer, zero, or a positive integer as the first | |||
| * argument is less than, equal to, or greater than the second. | |||
| * @throws IOException if the Resources cannot be read. | |||
| */ | |||
| public int compareContent(Resource r1, Resource r2, boolean text) throws IOException { | |||
| if (r1.equals(r2)) { | |||
| return 0; | |||
| } | |||
| boolean e1 = r1.isExists(); | |||
| boolean e2 = r2.isExists(); | |||
| if (!(e1 || e2)) { | |||
| return 0; | |||
| } | |||
| if (e1 != e2) { | |||
| return e1 ? 1 : -1; | |||
| } | |||
| boolean d1 = r1.isDirectory(); | |||
| boolean d2 = r2.isDirectory(); | |||
| if (d1 && d2) { | |||
| return 0; | |||
| } | |||
| if (d1 || d2) { | |||
| return d1 ? -1 : 1; | |||
| } | |||
| return text ? textCompare(r1, r2) : binaryCompare(r1, r2); | |||
| } | |||
| /** | |||
| * Binary compares the contents of two Resources. | |||
| * <p> | |||
| * simple but sub-optimal comparision algorithm. written for working | |||
| * rather than fast. Better would be a block read into buffers followed | |||
| * by long comparisions apart from the final 1-7 bytes. | |||
| * </p> | |||
| * | |||
| * @param f1 the file whose content is to be compared. | |||
| * @param f2 the other file whose content is to be compared. | |||
| * @return true if the content of the files is the same. | |||
| * @throws IOException if the files cannot be read. | |||
| * @param r1 the Resource whose content is to be compared. | |||
| * @param r2 the other Resource whose content is to be compared. | |||
| * @return a negative integer, zero, or a positive integer as the first | |||
| * argument is less than, equal to, or greater than the second. | |||
| * @throws IOException if the Resources cannot be read. | |||
| */ | |||
| private boolean binaryEquals(File f1, File f2) throws IOException { | |||
| if (f1.length() != f2.length()) { | |||
| // different size =>false | |||
| return false; | |||
| } | |||
| private int binaryCompare(Resource r1, Resource r2) throws IOException { | |||
| InputStream in1 = null; | |||
| InputStream in2 = null; | |||
| try { | |||
| in1 = new BufferedInputStream(new FileInputStream(f1)); | |||
| in2 = new BufferedInputStream(new FileInputStream(f2)); | |||
| in1 = new BufferedInputStream(r1.getInputStream()); | |||
| in2 = new BufferedInputStream(r2.getInputStream()); | |||
| int expectedByte = in1.read(); | |||
| while (expectedByte != -1) { | |||
| if (expectedByte != in2.read()) { | |||
| return false; | |||
| for (int b1 = in1.read(); b1 != -1; b1 = in1.read()) { | |||
| int b2 = in2.read(); | |||
| if (b1 != b2) { | |||
| return b1 > b2 ? 1 : -1; | |||
| } | |||
| expectedByte = in1.read(); | |||
| } | |||
| if (in2.read() != -1) { | |||
| return false; | |||
| } | |||
| return true; | |||
| return in2.read() == -1 ? 0 : -1; | |||
| } finally { | |||
| close(in1); | |||
| close(in2); | |||
| @@ -1050,33 +1176,30 @@ public class FileUtils { | |||
| } | |||
| /** | |||
| * Text compares the contents of two files. | |||
| * | |||
| * Text compares the contents of two Resources. | |||
| * Ignores different kinds of line endings. | |||
| * | |||
| * @param f1 the file whose content is to be compared. | |||
| * @param f2 the other file whose content is to be compared. | |||
| * @return true if the content of the files is the same. | |||
| * @throws IOException if the files cannot be read. | |||
| * @param r1 the Resource whose content is to be compared. | |||
| * @param r2 the other Resource whose content is to be compared. | |||
| * @return a negative integer, zero, or a positive integer as the first | |||
| * argument is less than, equal to, or greater than the second. | |||
| * @throws IOException if the Resources cannot be read. | |||
| */ | |||
| private boolean textEquals(File f1, File f2) throws IOException { | |||
| private int textCompare(Resource r1, Resource r2) throws IOException { | |||
| BufferedReader in1 = null; | |||
| BufferedReader in2 = null; | |||
| try { | |||
| in1 = new BufferedReader(new FileReader(f1)); | |||
| in2 = new BufferedReader(new FileReader(f2)); | |||
| in1 = new BufferedReader(new InputStreamReader(r1.getInputStream())); | |||
| in2 = new BufferedReader(new InputStreamReader(r2.getInputStream())); | |||
| String expected = in1.readLine(); | |||
| while (expected != null) { | |||
| if (!expected.equals(in2.readLine())) { | |||
| return false; | |||
| String actual = in2.readLine(); | |||
| if (!expected.equals(actual)) { | |||
| return expected.compareTo(actual); | |||
| } | |||
| expected = in1.readLine(); | |||
| } | |||
| if (in2.readLine() != null) { | |||
| return false; | |||
| } | |||
| return true; | |||
| return in2.readLine() == null ? 0 : -1; | |||
| } finally { | |||
| close(in1); | |||
| close(in2); | |||
| @@ -1384,7 +1507,6 @@ public class FileUtils { | |||
| return isUpToDate(sourceTime, destTime, granularity); | |||
| } | |||
| /** | |||
| * Returns true if the source is older than the dest. | |||
| * @param source source file (should be the older). | |||
| @@ -0,0 +1,69 @@ | |||
| /* | |||
| * Copyright 2005 The Apache Software Foundation | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * | |||
| */ | |||
| package org.apache.tools.ant.util; | |||
| import java.io.IOException; | |||
| import java.io.ByteArrayOutputStream; | |||
| import org.apache.tools.ant.Project; | |||
| /** | |||
| * Exception thrown when an attempt is made to get an OutputStream | |||
| * from an immutable Resource. | |||
| * @since Ant 1.7 | |||
| */ | |||
| public class PropertyOutputStream extends ByteArrayOutputStream { | |||
| private Project project; | |||
| private String property; | |||
| private boolean trim; | |||
| /** | |||
| * Construct a new PropertyOutputStream for the specified Project | |||
| * and property name, trimming the property value. | |||
| * @param p the associated Ant Project. | |||
| * @param s the String property name. | |||
| */ | |||
| public PropertyOutputStream(Project p, String s) { | |||
| this(p, s, true); | |||
| } | |||
| /** | |||
| * Construct a new PropertyOutputStream for | |||
| * the specified Project, property name, and trim mode. | |||
| * @param p the associated Ant Project. | |||
| * @param s the String property name. | |||
| * @param b the boolean trim mode. | |||
| */ | |||
| public PropertyOutputStream(Project p, String s, boolean b) { | |||
| project = p; | |||
| property = s; | |||
| trim = b; | |||
| } | |||
| /** | |||
| * Close the PropertyOutputStream, storing the property. | |||
| */ | |||
| public void close() { | |||
| if (project != null && property != null) { | |||
| String s = new String(toByteArray()); | |||
| project.setNewProperty(property, trim ? s.trim() : s); | |||
| } | |||
| } | |||
| } | |||
| @@ -370,27 +370,29 @@ public class ZipFile { | |||
| */ | |||
| private void positionAtCentralDirectory() | |||
| throws IOException { | |||
| long off = archive.length() - MIN_EOCD_SIZE; | |||
| archive.seek(off); | |||
| byte[] sig = ZipOutputStream.EOCD_SIG; | |||
| int curr = archive.read(); | |||
| boolean found = false; | |||
| while (curr != -1) { | |||
| if (curr == sig[0]) { | |||
| curr = archive.read(); | |||
| if (curr == sig[1]) { | |||
| long off = archive.length() - MIN_EOCD_SIZE; | |||
| if (off >= 0) { | |||
| archive.seek(off); | |||
| byte[] sig = ZipOutputStream.EOCD_SIG; | |||
| int curr = archive.read(); | |||
| while (curr != -1) { | |||
| if (curr == sig[0]) { | |||
| curr = archive.read(); | |||
| if (curr == sig[2]) { | |||
| if (curr == sig[1]) { | |||
| curr = archive.read(); | |||
| if (curr == sig[3]) { | |||
| found = true; | |||
| break; | |||
| if (curr == sig[2]) { | |||
| curr = archive.read(); | |||
| if (curr == sig[3]) { | |||
| found = true; | |||
| break; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| archive.seek(--off); | |||
| curr = archive.read(); | |||
| } | |||
| archive.seek(--off); | |||
| curr = archive.read(); | |||
| } | |||
| if (!found) { | |||
| throw new ZipException("archive is not a ZIP archive"); | |||
| @@ -0,0 +1,16 @@ | |||
| <antlib> | |||
| <typedef name="name" | |||
| classname="org.apache.tools.ant.types.resources.comparators.Name" /> | |||
| <typedef name="size" | |||
| classname="org.apache.tools.ant.types.resources.comparators.Size" /> | |||
| <typedef name="date" | |||
| classname="org.apache.tools.ant.types.resources.comparators.Date" /> | |||
| <typedef name="exists" | |||
| classname="org.apache.tools.ant.types.resources.comparators.Exists" /> | |||
| <typedef name="type" | |||
| classname="org.apache.tools.ant.types.resources.comparators.Type" /> | |||
| <typedef name="content" | |||
| classname="org.apache.tools.ant.types.resources.comparators.Content" /> | |||
| <typedef name="reverse" | |||
| classname="org.apache.tools.ant.types.resources.comparators.Reverse" /> | |||
| </antlib> | |||
| @@ -0,0 +1,24 @@ | |||
| <antlib> | |||
| <typedef name="name" | |||
| classname="org.apache.tools.ant.types.resources.selectors.Name" /> | |||
| <typedef name="not" | |||
| classname="org.apache.tools.ant.types.resources.selectors.Not" /> | |||
| <typedef name="none" | |||
| classname="org.apache.tools.ant.types.resources.selectors.None" /> | |||
| <typedef name="and" | |||
| classname="org.apache.tools.ant.types.resources.selectors.And" /> | |||
| <typedef name="or" | |||
| classname="org.apache.tools.ant.types.resources.selectors.Or" /> | |||
| <typedef name="exists" | |||
| classname="org.apache.tools.ant.types.resources.selectors.Exists" /> | |||
| <typedef name="type" | |||
| classname="org.apache.tools.ant.types.resources.selectors.Type" /> | |||
| <typedef name="majority" | |||
| classname="org.apache.tools.ant.types.resources.selectors.Majority" /> | |||
| <typedef name="instanceof" | |||
| classname="org.apache.tools.ant.types.resources.selectors.InstanceOf" /> | |||
| <typedef name="size" | |||
| classname="org.apache.tools.ant.types.resources.selectors.Size" /> | |||
| <typedef name="date" | |||
| classname="org.apache.tools.ant.types.resources.selectors.Date" /> | |||
| </antlib> | |||
| @@ -275,4 +275,9 @@ public class ConcatTest | |||
| File f2 = getProject().resolveFile("concat.utf8"); | |||
| assertTrue(FILE_UTILS.contentEquals(f1, f2)); | |||
| } | |||
| public void testResources() { | |||
| executeTarget("testResources"); | |||
| } | |||
| } | |||
| @@ -0,0 +1,136 @@ | |||
| /* | |||
| * Copyright 2005 The Apache Software Foundation | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * | |||
| */ | |||
| package org.apache.tools.ant.types; | |||
| import org.apache.tools.ant.BuildFileTest; | |||
| public class ResourceCollectionsTest extends BuildFileTest { | |||
| public ResourceCollectionsTest(String name) { | |||
| super(name); | |||
| } | |||
| public void setUp() { | |||
| configureProject("src/etc/testcases/types/resources/build.xml"); | |||
| } | |||
| public void tearDown() { | |||
| executeTarget("tearDown"); | |||
| } | |||
| public void testdifference() { | |||
| executeTarget("testdifference"); | |||
| } | |||
| public void testdirset() { | |||
| executeTarget("testdirset"); | |||
| } | |||
| public void testfile() { | |||
| executeTarget("testfile"); | |||
| } | |||
| public void testfilelist() { | |||
| executeTarget("testfilelist"); | |||
| } | |||
| public void testfiles1() { | |||
| executeTarget("testfiles1"); | |||
| } | |||
| public void testfiles2() { | |||
| executeTarget("testfiles2"); | |||
| } | |||
| public void testfiles3() { | |||
| executeTarget("testfiles3"); | |||
| } | |||
| public void testfileset() { | |||
| executeTarget("testfileset"); | |||
| } | |||
| public void testfileurl() { | |||
| executeTarget("testfileurl"); | |||
| } | |||
| public void testfileurlref() { | |||
| executeTarget("testfileurlref"); | |||
| } | |||
| public void testhttpurl1() { | |||
| executeTarget("testhttpurl1"); | |||
| } | |||
| public void testhttpurl2() { | |||
| executeTarget("testhttpurl2"); | |||
| } | |||
| public void testintersect() { | |||
| executeTarget("testintersect"); | |||
| } | |||
| public void testjarurl() { | |||
| executeTarget("testjarurl"); | |||
| } | |||
| public void testnestedresources() { | |||
| executeTarget("testnestedresources"); | |||
| } | |||
| public void testpath() { | |||
| executeTarget("testpath"); | |||
| } | |||
| public void testpropertyset() { | |||
| executeTarget("testpropertyset"); | |||
| } | |||
| public void testresource() { | |||
| executeTarget("testresource"); | |||
| } | |||
| public void testresourcesref() { | |||
| executeTarget("testresourcesref"); | |||
| } | |||
| public void testresourceurl() { | |||
| executeTarget("testresourceurl"); | |||
| } | |||
| public void teststring1() { | |||
| executeTarget("teststring1"); | |||
| } | |||
| public void teststring2() { | |||
| executeTarget("teststring2"); | |||
| } | |||
| public void testunion() { | |||
| executeTarget("testunion"); | |||
| } | |||
| public void testzipentry() { | |||
| executeTarget("testzipentry"); | |||
| } | |||
| public void testzipfileset() { | |||
| executeTarget("testzipfileset"); | |||
| } | |||
| } | |||
| @@ -0,0 +1,100 @@ | |||
| /* | |||
| * Copyright 2005 The Apache Software Foundation | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * | |||
| */ | |||
| package org.apache.tools.ant.types; | |||
| import org.apache.tools.ant.BuildFileTest; | |||
| public class ResourceComparatorsTest extends BuildFileTest { | |||
| public ResourceComparatorsTest(String name) { | |||
| super(name); | |||
| } | |||
| public void setUp() { | |||
| configureProject("src/etc/testcases/types/resources/comparators/build.xml"); | |||
| } | |||
| public void tearDown() { | |||
| executeTarget("tearDown"); | |||
| } | |||
| public void testcompoundsort1() { | |||
| executeTarget("testcompoundsort1"); | |||
| } | |||
| public void testcompoundsort2() { | |||
| executeTarget("testcompoundsort2"); | |||
| } | |||
| public void testcontent() { | |||
| executeTarget("testcontent"); | |||
| } | |||
| public void testexists() { | |||
| executeTarget("testexists"); | |||
| } | |||
| public void testdate() { | |||
| executeTarget("testdate"); | |||
| } | |||
| public void testname() { | |||
| executeTarget("testname"); | |||
| } | |||
| public void testrvcontent() { | |||
| executeTarget("testrvcontent"); | |||
| } | |||
| public void testrvdefault() { | |||
| executeTarget("testrvdefault"); | |||
| } | |||
| public void testrvexists() { | |||
| executeTarget("testrvexists"); | |||
| } | |||
| public void testrvdate() { | |||
| executeTarget("testrvdate"); | |||
| } | |||
| public void testrvname() { | |||
| executeTarget("testrvname"); | |||
| } | |||
| public void testrvsize() { | |||
| executeTarget("testrvsize"); | |||
| } | |||
| public void testrvtype() { | |||
| executeTarget("testrvtype"); | |||
| } | |||
| public void testsize() { | |||
| executeTarget("testsize"); | |||
| } | |||
| public void testsortdefault() { | |||
| executeTarget("testsortdefault"); | |||
| } | |||
| public void testtype() { | |||
| executeTarget("testtype"); | |||
| } | |||
| } | |||
| @@ -0,0 +1,153 @@ | |||
| /* | |||
| * Copyright 2005 The Apache Software Foundation | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * | |||
| */ | |||
| package org.apache.tools.ant.types; | |||
| import java.io.File; | |||
| import java.io.IOException; | |||
| import java.io.InputStreamReader; | |||
| import java.net.UnknownServiceException; | |||
| import org.apache.tools.ant.Project; | |||
| import org.apache.tools.ant.BuildFileTest; | |||
| import org.apache.tools.ant.BuildException; | |||
| import org.apache.tools.ant.taskdefs.Zip; | |||
| import org.apache.tools.ant.types.Resource; | |||
| import org.apache.tools.ant.types.resources.URLResource; | |||
| import org.apache.tools.ant.types.resources.ZipResource; | |||
| import org.apache.tools.ant.types.resources.FileResource; | |||
| import org.apache.tools.ant.types.resources.StringResource; | |||
| import org.apache.tools.ant.types.resources.PropertyResource; | |||
| import org.apache.tools.ant.types.resources.ImmutableResourceException; | |||
| import org.apache.tools.ant.util.FileUtils; | |||
| public class ResourceOutputTest extends BuildFileTest { | |||
| private static final FileUtils FILE_UTILS = FileUtils.getFileUtils(); | |||
| private static final File basedir = new File(System.getProperty("root"), | |||
| "src/etc/testcases/types/resources"); | |||
| public ResourceOutputTest(String name) { | |||
| super(name); | |||
| } | |||
| public void setUp() { | |||
| project = new Project(); | |||
| project.init(); | |||
| project.setUserProperty("basedir" , basedir.getAbsolutePath()); | |||
| } | |||
| public void testresourceoutput() { | |||
| try { | |||
| testoutputbe(new Resource("foo")); | |||
| fail("should have caught UnsupportedOperationException"); | |||
| } catch (UnsupportedOperationException e) { | |||
| } | |||
| } | |||
| public void teststringoutput1() { | |||
| StringResource r = new StringResource(); | |||
| testoutputbe(r); | |||
| assertEquals("foo", r.getValue()); | |||
| } | |||
| public void teststringoutput2() { | |||
| StringResource r = new StringResource("bar"); | |||
| try { | |||
| testoutput(r); | |||
| fail("should have caught ImmutableResourceException"); | |||
| } catch (ImmutableResourceException e) { | |||
| } catch (IOException e) { | |||
| fail("caught some other IOException: " + e); | |||
| } | |||
| assertEquals("bar", r.getValue()); | |||
| } | |||
| public void testpropertyoutput1() { | |||
| PropertyResource r = new PropertyResource(getProject(), "bar"); | |||
| testoutputbe(r); | |||
| assertPropertyEquals("bar", "foo"); | |||
| } | |||
| public void testpropertyoutput2() { | |||
| getProject().setNewProperty("bar", "bar"); | |||
| PropertyResource r = new PropertyResource(getProject(), "bar"); | |||
| try { | |||
| testoutput(r); | |||
| fail("should have caught ImmutableResourceException"); | |||
| } catch (ImmutableResourceException e) { | |||
| } catch (IOException e) { | |||
| fail("caught some other IOException: " + e); | |||
| } | |||
| assertPropertyEquals("bar", "bar"); | |||
| } | |||
| public void testurloutput() { | |||
| File f = getProject().resolveFile("testurloutput"); | |||
| try { | |||
| FILE_UTILS.createNewFile(f); | |||
| testoutput(new URLResource(f)); | |||
| fail("should have caught UnknownServiceException"); | |||
| } catch (UnknownServiceException e) { | |||
| } catch (IOException e) { | |||
| e.printStackTrace(System.err); | |||
| fail("caught some other IOException: " + e); | |||
| } finally { | |||
| if (!f.delete()) { | |||
| f.deleteOnExit(); | |||
| } | |||
| } | |||
| } | |||
| public void testzipentryoutput() { | |||
| Zip z = new Zip(); | |||
| z.setProject(getProject()); | |||
| Zip.WhenEmpty create = new Zip.WhenEmpty(); | |||
| create.setValue("create"); | |||
| z.setWhenempty(create); | |||
| z.setBasedir(basedir); | |||
| z.setExcludes("**/*"); | |||
| File f = getProject().resolveFile("foo"); | |||
| z.setDestFile(f); | |||
| z.execute(); | |||
| ZipResource r = new ZipResource(); | |||
| r.setZipfile(f); | |||
| r.setName("foo"); | |||
| try { | |||
| testoutputbe(r); | |||
| fail("should have caught UnsupportedOperationException"); | |||
| } catch (UnsupportedOperationException e) { | |||
| } finally { | |||
| if (!f.delete()) { | |||
| f.deleteOnExit(); | |||
| } | |||
| } | |||
| } | |||
| private void testoutputbe(Resource dest) { | |||
| try { | |||
| testoutput(dest); | |||
| } catch (IOException e) { | |||
| throw new BuildException(e); | |||
| } | |||
| } | |||
| private void testoutput(Resource dest) throws IOException { | |||
| FILE_UTILS.copyResource(new StringResource("foo"), dest, null); | |||
| } | |||
| } | |||
| @@ -0,0 +1,100 @@ | |||
| /* | |||
| * Copyright 2005 The Apache Software Foundation | |||
| * | |||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||
| * you may not use this file except in compliance with the License. | |||
| * You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * | |||
| */ | |||
| package org.apache.tools.ant.types; | |||
| import org.apache.tools.ant.BuildFileTest; | |||
| public class ResourceSelectorsTest extends BuildFileTest { | |||
| public ResourceSelectorsTest(String name) { | |||
| super(name); | |||
| } | |||
| public void setUp() { | |||
| configureProject("src/etc/testcases/types/resources/selectors/build.xml"); | |||
| } | |||
| public void testname1() { | |||
| executeTarget("testname1"); | |||
| } | |||
| public void testname2() { | |||
| executeTarget("testname2"); | |||
| } | |||
| public void testexists() { | |||
| executeTarget("testexists"); | |||
| } | |||
| public void testinstanceoftype1() { | |||
| executeTarget("testinstanceoftype1"); | |||
| } | |||
| public void testinstanceoftype2() { | |||
| executeTarget("testinstanceoftype2"); | |||
| } | |||
| public void testinstanceofclass() { | |||
| executeTarget("testinstanceofclass"); | |||
| } | |||
| public void testtype() { | |||
| executeTarget("testtype"); | |||
| } | |||
| public void testdate() { | |||
| executeTarget("testdate"); | |||
| } | |||
| public void testsize() { | |||
| executeTarget("testsize"); | |||
| } | |||
| public void testand() { | |||
| executeTarget("testand"); | |||
| } | |||
| public void testor() { | |||
| executeTarget("testor"); | |||
| } | |||
| public void testnot() { | |||
| executeTarget("testnot"); | |||
| } | |||
| public void testnone() { | |||
| executeTarget("testnone"); | |||
| } | |||
| public void testmajority1() { | |||
| executeTarget("testmajority1"); | |||
| } | |||
| public void testmajority2() { | |||
| executeTarget("testmajority2"); | |||
| } | |||
| public void testmajority3() { | |||
| executeTarget("testmajority3"); | |||
| } | |||
| public void testmajority4() { | |||
| executeTarget("testmajority4"); | |||
| } | |||
| } | |||
| @@ -172,4 +172,9 @@ public class ClassFileSetTest extends BuildFileTest { | |||
| assertTrue("Result did not contain test" + File.separator + "ContainsOnlyInner.class", | |||
| files.containsKey("test" + File.separator + "MethodParam.class")); | |||
| } | |||
| public void testResourceCollection() { | |||
| executeTarget("testresourcecollection"); | |||
| } | |||
| } | |||