diff options
Diffstat (limited to 'buildscripts/phing/classes/phing/types')
47 files changed, 7188 insertions, 0 deletions
diff --git a/buildscripts/phing/classes/phing/types/AbstractFileSet.php b/buildscripts/phing/classes/phing/types/AbstractFileSet.php new file mode 100755 index 00000000..60ca4d04 --- /dev/null +++ b/buildscripts/phing/classes/phing/types/AbstractFileSet.php @@ -0,0 +1,587 @@ +<?php +/* + * $Id: b7d8ccab6ed556e74626d880dcc09be20ea8bd58 $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +include_once 'phing/system/io/PhingFile.php'; +include_once 'phing/types/DataType.php'; +include_once 'phing/types/PatternSet.php'; +include_once 'phing/types/selectors/BaseSelector.php'; +include_once 'phing/types/selectors/SelectorContainer.php'; +include_once 'phing/types/selectors/BaseSelectorContainer.php'; + +// Load all of the selectors (not really necessary but +// helps reveal parse errors right away) + +include_once 'phing/types/selectors/AndSelector.php'; +include_once 'phing/types/selectors/ContainsSelector.php'; +include_once 'phing/types/selectors/ContainsRegexpSelector.php'; +include_once 'phing/types/selectors/DateSelector.php'; +include_once 'phing/types/selectors/DependSelector.php'; +include_once 'phing/types/selectors/DepthSelector.php'; +include_once 'phing/types/selectors/ExtendSelector.php'; +include_once 'phing/types/selectors/FilenameSelector.php'; +include_once 'phing/types/selectors/MajoritySelector.php'; +include_once 'phing/types/selectors/NoneSelector.php'; +include_once 'phing/types/selectors/NotSelector.php'; +include_once 'phing/types/selectors/OrSelector.php'; +include_once 'phing/types/selectors/PresentSelector.php'; +include_once 'phing/types/selectors/SizeSelector.php'; +include_once 'phing/types/selectors/TypeSelector.php'; + +include_once 'phing/util/DirectoryScanner.php'; + +/** + * The FileSet class provides methods and properties for accessing + * and managing filesets. It extends ProjectComponent and thus inherits + * all methods and properties (not explicitly declared). See ProjectComponent + * for further detail. + * + * TODO: + * - merge this with patternsets: FileSet extends PatternSet !!! + * requires additional mods to the parsing algo + * [HL] .... not sure if that really makes so much sense. I think + * that perhaps they should use common utility class if there really + * is that much shared functionality + * + * @author Andreas Aderhold <andi@binarycloud.com> + * @author Hans Lellelid <hans@xmpl.org> + * @version $Id$ + * @see ProjectComponent + * @package phing.types + */ +class AbstractFileSet extends DataType implements SelectorContainer { + + // These vars are public for cloning purposes + + /** + * @var boolean + */ + public $useDefaultExcludes = true; + + /** + * Whether to expand/dereference symbolic links, default is false + * @var boolean + */ + protected $expandSymbolicLinks = false; + + /** + * @var PatternSet + */ + public $defaultPatterns; + + public $additionalPatterns = array(); + public $dir; + public $isCaseSensitive = true; + public $selectors = array(); + + function __construct($fileset = null) { + if ($fileset !== null && ($fileset instanceof FileSet)) { + $this->dir = $fileset->dir; + $this->defaultPatterns = $fileset->defaultPatterns; + $this->additionalPatterns = $fileset->additionalPatterns; + $this->useDefaultExcludes = $fileset->useDefaultExcludes; + $this->isCaseSensitive = $fileset->isCaseSensitive; + $this->selectors = $fileset->selectors; + } + $this->defaultPatterns = new PatternSet(); + } + + /** + * Sets whether to expand/dereference symbolic links, default is false + * @var boolean + */ + function setExpandSymbolicLinks($expandSymbolicLinks) + { + $this->expandSymbolicLinks = $expandSymbolicLinks; + } + + /** + * Makes this instance in effect a reference to another PatternSet + * instance. + * You must not set another attribute or nest elements inside + * this element if you make it a reference. + */ + function setRefid(Reference $r) { + if ((isset($this->dir) && !is_null($this->dir)) || $this->defaultPatterns->hasPatterns()) { + throw $this->tooManyAttributes(); + } + if (!empty($this->additionalPatterns)) { + throw $this->noChildrenAllowed(); + } + if (!empty($this->selectors)) { + throw $this->noChildrenAllowed(); + } + parent::setRefid($r); + } + + + function setDir($dir) { + if ($this->isReference()) { + throw $this->tooManyAttributes(); + } + if ($dir instanceof PhingFile) { + $dir = $dir->getPath(); + } + $this->dir = new PhingFile((string) $dir); + } + + + function getDir(Project $p) { + if ($this->isReference()) { + return $this->getRef($p)->getDir($p); + } + return $this->dir; + } + + + function createPatternSet() { + if ($this->isReference()) { + throw $this->noChildrenAllowed(); + } + $num = array_push($this->additionalPatterns, new PatternSet()); + return $this->additionalPatterns[$num-1]; + } + + /** + * add a name entry on the include list + */ + function createInclude() { + if ($this->isReference()) { + throw $this->noChildrenAllowed(); + } + return $this->defaultPatterns->createInclude(); + } + + /** + * add a name entry on the include files list + */ + function createIncludesFile() { + if ($this->isReference()) { + throw $this->noChildrenAllowed(); + } + return $this->defaultPatterns->createIncludesFile(); + } + + /** + * add a name entry on the exclude list + */ + function createExclude() { + if ($this->isReference()) { + throw $this->noChildrenAllowed(); + } + return $this->defaultPatterns->createExclude(); + } + + /** + * add a name entry on the include files list + */ + function createExcludesFile() { + if ($this->isReference()) { + throw $this->noChildrenAllowed(); + return; + } + return $this->defaultPatterns->createExcludesFile(); + } + + /** + * Sets the set of include patterns. Patterns may be separated by a comma + * or a space. + */ + function setIncludes($includes) { + if ($this->isReference()) { + throw $this->tooManyAttributes(); + } + $this->defaultPatterns->setIncludes($includes); + } + + /** + * Sets the set of exclude patterns. Patterns may be separated by a comma + * or a space. + */ + function setExcludes($excludes) { + if ($this->isReference()) { + throw $this->tooManyAttributes(); + } + $this->defaultPatterns->setExcludes($excludes); + } + + /** + * Sets the name of the file containing the includes patterns. + * + * @param $incl The file to fetch the include patterns from. + * @throws BE + */ + function setIncludesfile($incl) { + if ($this->isReference()) { + throw $this->tooManyAttributes(); + } + $this->defaultPatterns->setIncludesfile($incl); + } + + /** + * Sets the name of the file containing the includes patterns. + * + * @param $excl The file to fetch the exclude patterns from. + * @throws BE + */ + function setExcludesfile($excl) { + if ($this->isReference()) { + throw $this->tooManyAttributes(); + } + $this->defaultPatterns->setExcludesfile($excl); + } + + /** + * Sets whether default exclusions should be used or not. + * + * @param $useDefaultExcludes "true"|"on"|"yes" when default exclusions + * should be used, "false"|"off"|"no" when they + * shouldn't be used. + */ + function setDefaultexcludes($useDefaultExcludes) { + if ($this->isReference()) { + throw $this->tooManyAttributes(); + } + $this->useDefaultExcludes = $useDefaultExcludes; + } + + /** + * Sets case sensitivity of the file system + */ + function setCaseSensitive($isCaseSensitive) { + $this->isCaseSensitive = $isCaseSensitive; + } + + /** returns a reference to the dirscanner object belonging to this fileset */ + function getDirectoryScanner(Project $p) { + if ($this->isReference()) { + $o = $this->getRef($p); + return $o->getDirectoryScanner($p); + } + + if ($this->dir === null) { + throw new BuildException("No directory specified for fileset."); + } + if (!$this->dir->exists()) { + throw new BuildException("Directory ".$this->dir->getAbsolutePath()." not found."); + } + if (!$this->dir->isLink() || !$this->expandSymbolicLinks) { + if (!$this->dir->isDirectory()) { + throw new BuildException($this->dir->getAbsolutePath()." is not a directory."); + } + } + $ds = new DirectoryScanner(); + $ds->setExpandSymbolicLinks($this->expandSymbolicLinks); + $this->setupDirectoryScanner($ds, $p); + $ds->scan(); + return $ds; + } + + /** feed dirscanner with infos defined by this fileset */ + protected function setupDirectoryScanner(DirectoryScanner $ds, Project $p) { + if ($ds === null) { + throw new Exception("DirectoryScanner cannot be null"); + } + // FIXME - pass dir directly wehn dirscanner supports File + $ds->setBasedir($this->dir->getPath()); + + foreach($this->additionalPatterns as $addPattern) { + $this->defaultPatterns->append($addPattern, $p); + } + + $ds->setIncludes($this->defaultPatterns->getIncludePatterns($p)); + $ds->setExcludes($this->defaultPatterns->getExcludePatterns($p)); + + $p->log("FileSet: Setup file scanner in dir " . $this->dir->__toString() . " with " . $this->defaultPatterns->toString(), Project::MSG_DEBUG); + + if ($ds instanceof SelectorScanner) { + $ds->setSelectors($this->getSelectors($p)); + } + + if ($this->useDefaultExcludes) { + $ds->addDefaultExcludes(); + } + $ds->setCaseSensitive($this->isCaseSensitive); + } + + + /** + * Performs the check for circular references and returns the + * referenced FileSet. + */ + function getRef(Project $p) { + if (!$this->checked) { + $stk = array(); + array_push($stk, $this); + $this->dieOnCircularReference($stk, $p); + } + + $o = $this->ref->getReferencedObject($p); + if (!($o instanceof FileSet)) { + $msg = $this->ref->getRefId()." doesn't denote a fileset"; + throw new BuildException($msg); + } else { + return $o; + } + } + + // SelectorContainer methods + + /** + * Indicates whether there are any selectors here. + * + * @return boolean Whether any selectors are in this container + */ + public function hasSelectors() { + if ($this->isReference() && $this->getProject() !== null) { + return $this->getRef($this->getProject())->hasSelectors(); + } + return !empty($this->selectors); + } + + /** + * Indicates whether there are any patterns here. + * + * @return boolean Whether any patterns are in this container. + */ + public function hasPatterns() { + + if ($this->isReference() && $this->getProject() !== null) { + return $this->getRef($this->getProject())->hasPatterns(); + } + + if ($this->defaultPatterns->hasPatterns($this->getProject())) { + return true; + } + + for($i=0,$size=count($this->additionalPatterns); $i < $size; $i++) { + $ps = $this->additionalPatterns[$i]; + if ($ps->hasPatterns($this->getProject())) { + return true; + } + } + + return false; + } + + /** + * Gives the count of the number of selectors in this container + * + * @return int The number of selectors in this container + */ + public function selectorCount() { + if ($this->isReference() && $this->getProject() !== null) { + try { + return $this->getRef($this->getProject())->selectorCount(); + } catch (Exception $e) { + throw $e; + } + } + return count($this->selectors); + } + + /** + * Returns the set of selectors as an array. + * + * @return an array of selectors in this container + */ + public function getSelectors(Project $p) { + if ($this->isReference()) { + return $this->getRef($p)->getSelectors($p); + } else { + // *copy* selectors + $result = array(); + for($i=0,$size=count($this->selectors); $i < $size; $i++) { + $result[] = clone $this->selectors[$i]; + } + return $result; + } + } + + /** + * Returns an array for accessing the set of selectors. + * + * @return array The array of selectors + */ + public function selectorElements() { + if ($this->isReference() && $this->getProject() !== null) { + return $this->getRef($this->getProject())->selectorElements(); + } + return $this->selectors; + } + + /** + * Add a new selector into this container. + * + * @param selector the new selector to add + */ + public function appendSelector(FileSelector $selector) { + if ($this->isReference()) { + throw $this->noChildrenAllowed(); + } + $this->selectors[] = $selector; + } + + /* Methods below all add specific selectors */ + + /** + * add a "Select" selector entry on the selector list + */ + public function createSelector() { + $o = new SelectSelector(); + $this->appendSelector($o); + return $o; + } + + /** + * add an "And" selector entry on the selector list + */ + public function createAnd() { + $o = new AndSelector(); + $this->appendSelector($o); + return $o; + } + + /** + * add an "Or" selector entry on the selector list + */ + public function createOr() { + $o = new OrSelector(); + $this->appendSelector($o); + return $o; + } + + /** + * add a "Not" selector entry on the selector list + */ + public function createNot() { + $o = new NotSelector(); + $this->appendSelector($o); + return $o; + } + + /** + * add a "None" selector entry on the selector list + */ + public function createNone() { + $o = new NoneSelector(); + $this->appendSelector($o); + return $o; + } + + /** + * add a majority selector entry on the selector list + */ + public function createMajority() { + $o = new MajoritySelector(); + $this->appendSelector($o); + return $o; + } + + /** + * add a selector date entry on the selector list + */ + public function createDate() { + $o = new DateSelector(); + $this->appendSelector($o); + return $o; + } + + /** + * add a selector size entry on the selector list + */ + public function createSize() { + $o = new SizeSelector(); + $this->appendSelector($o); + return $o; + } + + /** + * add a selector filename entry on the selector list + */ + public function createFilename() { + $o = new FilenameSelector(); + $this->appendSelector($o); + return $o; + } + + /** + * add an extended selector entry on the selector list + */ + public function createCustom() { + $o = new ExtendSelector(); + $this->appendSelector($o); + return $o; + } + + /** + * add a contains selector entry on the selector list + */ + public function createContains() { + $o = new ContainsSelector(); + $this->appendSelector($o); + return $o; + } + + /** + * add a contains selector entry on the selector list + */ + public function createContainsRegexp() { + $o = new ContainsRegexpSelector(); + $this->appendSelector($o); + return $o; + } + + /** + * add a present selector entry on the selector list + */ + public function createPresent() { + $o = new PresentSelector(); + $this->appendSelector($o); + return $o; + } + + /** + * add a depth selector entry on the selector list + */ + public function createDepth() { + $o = new DepthSelector(); + $this->appendSelector($o); + return $o; + } + + /** + * add a depends selector entry on the selector list + */ + public function createDepend() { + $o = new DependSelector(); + $this->appendSelector($o); + return $o; + } + + /** + * add a type selector entry on the selector list + */ + public function createType() { + $o = new TypeSelector(); + $this->appendSelector($o); + return $o; + } +} diff --git a/buildscripts/phing/classes/phing/types/Commandline.php b/buildscripts/phing/classes/phing/types/Commandline.php new file mode 100755 index 00000000..d6b36e14 --- /dev/null +++ b/buildscripts/phing/classes/phing/types/Commandline.php @@ -0,0 +1,475 @@ +<?php +/* + * $Id: 891b349dcd88b825ae99edf53ed4c7ac2c1c2467 $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + + +/** + * Commandline objects help handling command lines specifying processes to + * execute. + * + * The class can be used to define a command line as nested elements or as a + * helper to define a command line by an application. + * <p> + * <code> + * <someelement><br> + * <acommandline executable="/executable/to/run"><br> + * <argument value="argument 1" /><br> + * <argument line="argument_1 argument_2 argument_3" /><br> + * <argument value="argument 4" /><br> + * </acommandline><br> + * </someelement><br> + * </code> + * The element <code>someelement</code> must provide a method + * <code>createAcommandline</code> which returns an instance of this class. + * + * @author thomas.haas@softwired-inc.com + * @author <a href="mailto:stefan.bodewig@epost.de">Stefan Bodewig</a> + * @package phing.types + */ +class Commandline { + + /** + * @var array CommandlineArguments[] + */ + public $arguments = array(); // public so "inner" class can access + + /** + * Full path (if not on %PATH% env var) to executable program. + * @var string + */ + public $executable; // public so "inner" class can access + + const DISCLAIMER = "The ' characters around the executable and arguments are not part of the command."; + + public function __construct($to_process = null) { + if ($to_process !== null) { + $tmp = $this->translateCommandline($to_process); + if ($tmp) { + $this->setExecutable(array_shift($tmp)); // removes first el + foreach($tmp as $arg) { // iterate through remaining elements + $this->createArgument()->setValue($arg); + } + } + } + } + + + /** + * Creates an argument object and adds it to our list of args. + * + * <p>Each commandline object has at most one instance of the + * argument class.</p> + * + * @param boolean $insertAtStart if true, the argument is inserted at the + * beginning of the list of args, otherwise it is appended. + * @return CommandlineArgument + */ + public function createArgument($insertAtStart = false) { + $argument = new CommandlineArgument($this); + if ($insertAtStart) { + array_unshift($this->arguments, $argument); + } else { + array_push($this->arguments, $argument); + } + return $argument; + } + + /** + * Sets the executable to run. + */ + public function setExecutable($executable) { + if (!$executable) { + return; + } + $this->executable = $executable; + $this->executable = strtr($this->executable, '/', DIRECTORY_SEPARATOR); + $this->executable = strtr($this->executable, '\\', DIRECTORY_SEPARATOR); + } + + public function getExecutable() { + return $this->executable; + } + + public function addArguments($line) { + foreach($line as $arg) { + $this->createArgument()->setValue($arg); + } + } + + /** + * Returns the executable and all defined arguments. + * @return array + */ + public function getCommandline() { + $args = $this->getArguments(); + if ($this->executable === null) { + return $args; + } + return array_merge(array($this->executable), $args); + } + + + /** + * Returns all arguments defined by <code>addLine</code>, + * <code>addValue</code> or the argument object. + */ + public function getArguments() { + $result = array(); + foreach($this->arguments as $arg) { + $parts = $arg->getParts(); + if ($parts !== null) { + foreach($parts as $part) { + $result[] = $part; + } + } + } + return $result; + } + + public function __toString() { + return self::toString($this->getCommandline()); + } + + /** + * Put quotes around the given String if necessary. + * + * <p>If the argument doesn't include spaces or quotes, return it + * as is. If it contains double quotes, use single quotes - else + * surround the argument by double quotes.</p> + * + * @exception BuildException if the argument contains both, single + * and double quotes. + */ + public static function quoteArgument($argument, $escape = false) { + if ($escape) { + return escapeshellarg($argument); + } elseif (strpos($argument, "\"") !== false) { + if (strpos($argument, "'") !== false) { + throw new BuildException("Can't handle single and double quotes in same argument"); + } else { + return escapeshellarg($argument); + } + } elseif (strpos($argument, "'") !== false || strpos($argument, " ") !== false) { + return escapeshellarg($argument); + //return '\"' . $argument . '\"'; + } else { + return $argument; + } + } + + /** + * Quotes the parts of the given array in way that makes them + * usable as command line arguments. + */ + public static function toString($lines, $escape = false) { + // empty path return empty string + if (!$lines) { + return ""; + } + + // path containing one or more elements + $result = ""; + for ($i = 0, $len=count($lines); $i < $len; $i++) { + if ($i > 0) { + $result .= ' '; + } + $result .= self::quoteArgument($lines[$i], $escape); + } + return $result; + } + + /** + * + * @param string $to_process + * @return array + */ + public static function translateCommandline($to_process) { + + if (!$to_process) { + return array(); + } + + // parse with a simple finite state machine + + $normal = 0; + $inQuote = 1; + $inDoubleQuote = 2; + + $state = $normal; + $args = array(); + $current = ""; + $lastTokenHasBeenQuoted = false; + + $tok = strtok($to_process, ""); + $tokens = preg_split('/(["\' ])/', $to_process, -1, PREG_SPLIT_DELIM_CAPTURE); + while(($nextTok = array_shift($tokens)) !== null) { + switch ($state) { + case $inQuote: + if ("'" == $nextTok) { + $lastTokenHasBeenQuoted = true; + $state = $normal; + } else { + $current .= $nextTok; + } + break; + case $inDoubleQuote: + if ("\"" == $nextTok) { + $lastTokenHasBeenQuoted = true; + $state = $normal; + } else { + $current .= $nextTok; + } + break; + default: + if ("'" == $nextTok) { + $state = $inQuote; + } elseif ("\"" == $nextTok) { + $state = $inDoubleQuote; + } elseif (" " == $nextTok) { + if ($lastTokenHasBeenQuoted || strlen($current) != 0) { + $args[] = $current; + $current = ""; + } + } else { + $current .= $nextTok; + } + $lastTokenHasBeenQuoted = false; + break; + } + } + + if ($lastTokenHasBeenQuoted || strlen($current) != 0) { + $args[] = $current; + } + + if ($state == $inQuote || $state == $inDoubleQuote) { + throw new BuildException("unbalanced quotes in " . $to_process); + } + + return $args; + } + + /** + * @return int Number of components in current commandline. + */ + public function size() { + return count($this->getCommandline()); + } + + public function __copy() { + $c = new Commandline(); + $c->setExecutable($this->executable); + $c->addArguments($this->getArguments()); + return $c; + } + + /** + * Clear out the whole command line. */ + public function clear() { + $this->executable = null; + $this->arguments->removeAllElements(); + } + + /** + * Clear out the arguments but leave the executable in place for + * another operation. + */ + public function clearArgs() { + $this->arguments = array(); + } + + /** + * Return a marker. + * + * <p>This marker can be used to locate a position on the + * commandline - to insert something for example - when all + * parameters have been set.</p> + * @return CommandlineMarker + */ + public function createMarker() { + return new CommandlineMarker($this, count($this->arguments)); + } + + /** + * Returns a String that describes the command and arguments + * suitable for verbose output before a call to + * <code>Runtime.exec(String[])</code>. + * + * <p>This method assumes that the first entry in the array is the + * executable to run.</p> + * @param array $args CommandlineArgument[] to use + * @return string + */ + public function describeCommand($args = null) { + + if ($args === null) { + $args = $this->getCommandline(); + } + + if (!$args) { + return ""; + } + + $buf = "Executing '"; + $buf .= $args[0]; + $buf .= "'"; + if (count($args) > 0) { + $buf .= " with "; + $buf .= $this->describeArguments($args, 1); + } else { + $buf .= self::DISCLAIMER; + } + return $buf; + } + + /** + * Returns a String that describes the arguments suitable for + * verbose output before a call to + * <code>Runtime.exec(String[])</code> + * @param $args arguments to use (default is to use current class args) + * @param $offset ignore entries before this index + * @return string + */ + protected function describeArguments($args = null, $offset = 0) { + if ($args === null) { + $args = $this->getArguments(); + } + + if ($args === null || count($args) <= $offset) { + return ""; + } + + $buf = "argument"; + if (count($args) > $offset) { + $buf .= "s"; + } + $buf .= ":" . PHP_EOL; + for ($i = $offset, $alen=count($args); $i < $alen; $i++) { + $buf .= "'" . $args[$i] . "'" . PHP_EOL; + } + $buf .= self::DISCLAIMER; + return $buf; + } +} + + +/** + * "Inner" class used for nested xml command line definitions. + * + * @package phing.types + */ +class CommandlineArgument { + + private $parts = array(); + private $outer; + + public function __construct(Commandline $outer) { + $this->outer = $outer; + } + + /** + * Sets a single commandline argument. + * + * @param string $value a single commandline argument. + */ + public function setValue($value) { + $this->parts = array($value); + } + + /** + * Line to split into several commandline arguments. + * + * @param line line to split into several commandline arguments + */ + public function setLine($line) { + if ($line === null) { + return; + } + $this->parts = $this->outer->translateCommandline($line); + } + + /** + * Sets a single commandline argument and treats it like a + * PATH - ensures the right separator for the local platform + * is used. + * + * @param value a single commandline argument. + */ + public function setPath($value) { + $this->parts = array( (string) $value ); + } + + /** + * Sets a single commandline argument to the absolute filename + * of the given file. + * + * @param value a single commandline argument. + */ + public function setFile(PhingFile $value) { + $this->parts = array($value->getAbsolutePath()); + } + + /** + * Returns the parts this Argument consists of. + * @return array string[] + */ + public function getParts() { + return $this->parts; + } +} + +/** + * Class to keep track of the position of an Argument. + * + * <p>This class is there to support the srcfile and targetfile + * elements of <execon> and <transform> - don't know + * whether there might be additional use cases.</p> --SB + * + * @package phing.types + */ +class CommandlineMarker { + + private $position; + private $realPos = -1; + private $outer; + + public function __construct(Comandline $outer, $position) { + $this->outer = $outer; + $this->position = $position; + } + + /** + * Return the number of arguments that preceeded this marker. + * + * <p>The name of the executable - if set - is counted as the + * very first argument.</p> + */ + public function getPosition() { + if ($this->realPos == -1) { + $realPos = ($this->outer->executable === null ? 0 : 1); + for ($i = 0; $i < $position; $i++) { + $arg = $this->arguments[$i]; + $realPos += count($arg->getParts()); + } + } + return $this->realPos; + } +} + diff --git a/buildscripts/phing/classes/phing/types/DataType.php b/buildscripts/phing/classes/phing/types/DataType.php new file mode 100644 index 00000000..8aa3b487 --- /dev/null +++ b/buildscripts/phing/classes/phing/types/DataType.php @@ -0,0 +1,182 @@ +<?php +/* + * $Id: 3b15630144c62dda1f447d8eed1e5eda7ac8a466 $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +require_once 'phing/ProjectComponent.php'; +include_once 'phing/BuildException.php'; + +/** + * Base class for those classes that can appear inside the build file + * as stand alone data types. + * + * This class handles the common description attribute and provides + * a default implementation for reference handling and checking for + * circular references that is appropriate for types that can not be + * nested inside elements of the same type (i.e. patternset but not path) + * + * @package phing.types + */ +class DataType extends ProjectComponent { + + /** The descriptin the user has set. */ + public $description = null; + + /** Value to the refid attribute. Type of Reference*/ + public $ref = null; + + /** + * Are we sure we don't hold circular references? + * + * Subclasses are responsible for setting this value to false + * if we'd need to investigate this condition (usually because a + * child element has been added that is a subclass of DataType). + * @var boolean + */ + protected $checked = true; + + /** + * Sets a description of the current data type. It will be useful + * in commenting what we are doing. + */ + function setDescription($desc) { + $this->description = (string) $desc; + } + + /** Return the description for the current data type. */ + function getDescription() { + return $this->description; + } + + /** Has the refid attribute of this element been set? */ + function isReference() { + return ($this->ref !== null); + } + + /** + * Set the value of the refid attribute. + * + * Subclasses may need to check whether any other attributes + * have been set as well or child elements have been created and + * thus override this method. if they do they must call parent::setRefid() + * + * @param Reference $r + * @return void + */ + function setRefid(Reference $r) { + $this->ref = $r; + $this->checked = false; + } + + /** + * Check to see whether any DataType we hold references to is + * included in the Stack (which holds all DataType instances that + * directly or indirectly reference this instance, including this + * instance itself). + * + * If one is included, throw a BuildException created by circularReference + * + * This implementation is appropriate only for a DataType that + * cannot hold other DataTypes as children. + * + * The general contract of this method is that it shouldn't do + * anything if checked is true and set it to true on exit. + */ + function dieOnCircularReference(&$stk, Project $p) { + if ($this->checked || !$this->isReference()) { + return; + } + + $o = $this->ref->getReferencedObject($p); + + if ($o instanceof DataType) { + + // TESTME - make sure that in_array() works just as well here + // + // check if reference is in stack + //$contains = false; + //for ($i=0, $size=count($stk); $i < $size; $i++) { + // if ($stk[$i] === $o) { + // $contains = true; + // break; + // } + //} + + if (in_array($o, $stk, true)) { + // throw build exception + throw $this->circularReference(); + } else { + array_push($stk, $o); + $o->dieOnCircularReference($stk, $p); + array_pop($stk); + } + } + $this->checked = true; + } + + /** Performs the check for circular references and returns the referenced object. */ + function getCheckedRef($requiredClass, $dataTypeName) { + + if (!$this->checked) { + // should be in stack + $stk = array(); + $stk[] = $this; + $this->dieOnCircularReference($stk, $this->getProject()); + } + + $o = $this->ref->getReferencedObject($this->getProject()); + if (!($o instanceof $requiredClass) ) { + throw new BuildException($this->ref->getRefId()." doesn't denote a " . $dataTypeName); + } else { + return $o; + } + } + + /** + * Creates an exception that indicates that refid has to be the + * only attribute if it is set. + */ + function tooManyAttributes() { + return new BuildException( "You must not specify more than one attribute when using refid" ); + } + + /** + * Creates an exception that indicates that this XML element must + * not have child elements if the refid attribute is set. + */ + function noChildrenAllowed() { + return new BuildException("You must not specify nested elements when using refid"); + } + + /** + * Creates an exception that indicates the user has generated a + * loop of data types referencing each other. + */ + function circularReference() { + return new BuildException("This data type contains a circular reference."); + } + + /** + * Template method being called when the data type has been + * parsed completely. + * @return void + */ + function parsingComplete() {} +} + diff --git a/buildscripts/phing/classes/phing/types/Description.php b/buildscripts/phing/classes/phing/types/Description.php new file mode 100644 index 00000000..85b2c529 --- /dev/null +++ b/buildscripts/phing/classes/phing/types/Description.php @@ -0,0 +1,53 @@ +<?php + +/* + * $Id: bb303eb742207be6958c8107e21ec7c964c09dee $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +/** + * Description is used to provide a project-wide description element + * (that is, a description that applies to a buildfile as a whole). + * If present, the <description> element is printed out before the + * target descriptions. + * + * Description has no attributes, only text. There can only be one + * project description per project. A second description element will + * overwrite the first. + * + * @author Hans Lellelid <hans@xmpl.org> (Phing) + * @author Craeg Strong <cstrong@arielpartners.com> (Ant) + * @package phing.types + */ +class Description extends DataType { + + /** + * Adds descriptive text to the project. + * + * @return void + */ + public function addText($text) { + $currentDescription = $this->project->getDescription(); + if ($currentDescription === null) { + $this->project->setDescription($text); + } else { + $this->project->setDescription($currentDescription . $text); + } + } + +} diff --git a/buildscripts/phing/classes/phing/types/DirSet.php b/buildscripts/phing/classes/phing/types/DirSet.php new file mode 100644 index 00000000..527127bb --- /dev/null +++ b/buildscripts/phing/classes/phing/types/DirSet.php @@ -0,0 +1,49 @@ +<?php + +/* + * $Id: 1ab2ec4f1b43daee6cf4c247b4b18b78d87052bc $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +include_once 'phing/types/AbstractFileSet.php'; + +/** + * Subclass as hint for supporting tasks that the included directories + * instead of files should be used. + * + * @package phing.types + */ +class DirSet extends AbstractFileSet { + + public function __construct($dirset = null) { + parent::__construct($dirset); + } + + /** + * Return a DirSet that has the same basedir and same patternsets + * as this one. + */ + public function __clone() { + if ($this->isReference()) { + return new DirSet($this->getRef($this->getProject())); + } else { + return new DirSet($this); + } + } + +} diff --git a/buildscripts/phing/classes/phing/types/Excludes.php b/buildscripts/phing/classes/phing/types/Excludes.php new file mode 100644 index 00000000..2d45b593 --- /dev/null +++ b/buildscripts/phing/classes/phing/types/Excludes.php @@ -0,0 +1,208 @@ +<?php +/* + * $Id: 0c22f261d1984da235c6cf4993d1275c225a33ba $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +include_once 'phing/types/DataType.php'; +include_once 'phing/types/FileSet.php'; +require_once 'phing/types/ExcludesNameEntry.php'; + +/** + * Datatype which handles excluded files, classes and methods. + * + * @package phing.types + * @author Benjamin Schultz <bschultz@proqrent.de> + * @version $Id: 0c22f261d1984da235c6cf4993d1275c225a33ba $ + * @since 2.4.6 + */ +class Excludes extends DataType +{ + /** + * The directory scanner for getting the excluded files + * + * @var DirectoryScanner + */ + private $_directoryScanner = null; + + /** + * Holds the excluded file patterns + * + * @var array + */ + private $_files = array(); + + /** + * Holds the excluded classes + * + * @var array + */ + private $_classes = array(); + + /** + * Holds the excluded methods + * + * @var array + */ + private $_methods = array(); + + /** + * ctor + * + * @param Project $project + */ + public function __construct(Project $project) + { + $this->_directoryScanner = new DirectoryScanner(); + $this->_directoryScanner->setBasedir($project->getBasedir()); + } + + /** + * Add a name entry on the exclude file list + * + * @return ExcludesNameEntry Reference to object + */ + public function createFile() + { + return $this->_addFile($this->_files); + } + + /** + * Add a name entry on the exclude class list + * + * @return ExcludesNameEntry Reference to object + */ + public function createClass() + { + return $this->_addClass($this->_classes); + } + + /** + * Add a name entry on the exclude method list + * + * @return ExcludesNameEntry Reference to object + */ + public function createMethod() + { + return $this->_addMethod($this->_methods); + } + + /** + * Adds a file to the exclusion list + * + * @param FileSet $fileSet The FileSet into which the nameentry should be added + * + * @return ExcludesNameEntry Reference to the created ExcludesNameEntry instance + */ + private function _addFile(&$fileList) + { + $file = new ExcludesNameEntry(); + $fileList[] = $file; + + return $file; + } + + /** + * Adds a class to the exclusion list + * + * @return ExcludesNameEntry Reference to the created ExcludesNameEntry instance + */ + private function _addClass(&$classList) + { + $excludedClass = new ExcludesNameEntry(); + $classList[] = $excludedClass; + + return $excludedClass; + } + + /** + * Adds a method to the exclusion list + * + * @return ExcludesNameEntry Reference to the created ExcludesNameEntry instance + */ + private function _addMethod(&$methodList) + { + $excludedMethod = new ExcludesNameEntry(); + $methodList[] = $excludedMethod; + + return $excludedMethod; + } + + /** + * Returns the excluded files + * + * @return array + */ + public function getExcludedFiles() + { + $includes = array(); + + foreach ($this->_files as $file) { + $includes[] = $file->getName(); + } + + $this->_directoryScanner->setIncludes($includes); + $this->_directoryScanner->scan(); + + $files = $this->_directoryScanner->getIncludedFiles(); + $dir = $this->_directoryScanner->getBasedir(); + $fileList = array(); + + foreach ($files as $file) { + $fileList[] = $dir . DIRECTORY_SEPARATOR . $file; + } + + return $fileList; + } + + /** + * Returns the excluded class names + * + * @return array + */ + public function getExcludedClasses() + { + $excludedClasses = array(); + + foreach ($this->_classes as $excludedClass) { + $excludedClasses[] = $excludedClass->getName(); + } + + return $excludedClasses; + } + + /** + * Returns the excluded method names + * + * @return array + */ + public function getExcludedMethods() + { + $excludedMethods = array(); + + foreach ($this->_methods as $excludedMethod) { + $classAndMethod = explode('::', $excludedMethod->getName()); + $className = $classAndMethod[0]; + $methodName = $classAndMethod[1]; + + $excludedMethods[$className][] = $methodName; + } + + return $excludedMethods; + } +}
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/types/ExcludesNameEntry.php b/buildscripts/phing/classes/phing/types/ExcludesNameEntry.php new file mode 100644 index 00000000..1aa6aae5 --- /dev/null +++ b/buildscripts/phing/classes/phing/types/ExcludesNameEntry.php @@ -0,0 +1,81 @@ +<?php +/* + * $Id: a1098700b4f205baacfd5adf5434e5a4803a6a3f $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +/** + * Class for holding nested excludes elements (file, class, method). + * + * @package phing.types + * @author Benjamin Schultz <bschultz@proqrent.de> + * @version $Id: a1098700b4f205baacfd5adf5434e5a4803a6a3f $ + * @since 2.4.6 + */ +class ExcludesNameEntry +{ + /** + * Holds the name of a file, class or method or a file pattern + * + * @var string + */ + private $_name; + + /** + * An alias for the setName() method. + * Set the name of a file pattern. + * + * @see setName() + * + * @param string $pattern The file pattern + */ + public function addText($pattern) + { + $this->setName($pattern); + } + + /** + * Set the name of a file, class or method + * + * @param string $name + */ + public function setName($name) + { + $this->_name = (string) $name; + } + + /** + * Get the name of a file, class or method or the file pattern + * + * @return string The name of a file, class or method or the file pattern + */ + public function getName() + { + return $this->_name; + } + + /** + * Gets a string representation of this name or pattern. + * + * @return string + */ + public function toString() + { + return $this->_name; + } +}
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/types/FileList.php b/buildscripts/phing/classes/phing/types/FileList.php new file mode 100755 index 00000000..bc7c6b18 --- /dev/null +++ b/buildscripts/phing/classes/phing/types/FileList.php @@ -0,0 +1,224 @@ +<?php +/* + * $Id: aab0ffb8e2266923f6cdaf165741dc38931a2aed $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +require_once 'phing/types/DataType.php'; +include_once 'phing/system/io/PhingFile.php'; + +/** + * FileList represents an explicitly named list of files. FileLists + * are useful when you want to capture a list of files regardless of + * whether they currently exist. + * + * <filelist + * id="docfiles" + * dir="${phing.docs.dir}" + * files="chapters/Installation.html,chapters/Setup.html"/> + * + * OR + * + * <filelist + * dir="${doc.src.dir}" + * listfile="${phing.docs.dir}/PhingGuide.book"/> + * + * (or a mixture of files="" and listfile="" can be used) + * + * @author Hans Lellelid <hans@xmpl.org> + * @version $Id$ + * @package phing.types + */ +class FileList extends DataType { + + // public for "cloning" purposes + + /** Array containing all filenames. */ + public $filenames = array(); + + /** Base directory for this file list. */ + public $dir; + + /** PhingFile that contains a list of files (one per line). */ + public $listfile; + + /** + * Construct a new FileList. + * @param array $filelist; + */ + function __construct($filelist = null) { + if ($filelist !== null) { + $this->dir = $filelist->dir; + $this->filenames = $filelist->filenames; + $this->listfile = $filelist->listfile; + } + } + + /** + * Makes this instance in effect a reference to another FileList + * instance. + */ + function setRefid(Reference $r) { + if ($this->dir !== null || count($this->filenames) !== 0) { + throw $this->tooManyAttributes(); + } + parent::setRefid($r); + } + + /** + * Base directory for files in list. + * @param PhingFile $dir + */ + function setDir(PhingFile $dir) { + if ($this->isReference()) { + throw $this->tooManyAttributes(); + } + if (!($dir instanceof PhingFile)) { + $dir = new PhingFile($dir); + } + $this->dir = $dir; + } + + /** + * Get the basedir for files in list. + * @return PhingFile + */ + function getDir(Project $p) { + if ($this->isReference()) { + $ref = $this->getRef($p); + return $ref->getDir($p); + } + return $this->dir; + } + + /** + * Set the array of files in list. + * @param array $filenames + */ + function setFiles($filenames) { + if ($this->isReference()) { + throw $this->tooManyAttributes(); + } + if (!empty($filenames)) { + $tok = strtok($filenames, ", \t\n\r"); + while ($tok !== false) { + $fname = trim($tok); + if ($fname !== "") { + $this->filenames[] = $tok; + } + $tok = strtok(", \t\n\r"); + } + } + } + + /** + * Sets a source "list" file that contains filenames to add -- one per line. + * @param string $file + */ + function setListFile($file) { + if ($this->isReference()) { + throw $this->tooManyAttributes(); + } + if (!($file instanceof PhingFile)) { + $file = new PhingFile($file); + } + $this->listfile = $file; + } + + /** + * Get the source "list" file that contains file names. + * @param Project $p + * @return PhingFile + */ + function getListFile(Project $p) { + if ($this->isReference()) { + $ref = $this->getRef($p); + return $ref->getListFile($p); + } + return $this->listfile; + } + + /** + * Returns the list of files represented by this FileList. + * @param Project $p + * @return array + */ + function getFiles(Project $p) { + + if ($this->isReference()) { + $ret = $this->getRef($p); + $ret = $ret->getFiles($p); + return $ret; + } + + if ($this->listfile !== null) { + $this->readListFile($p); + } + + return $this->filenames; + } + + + /** + * Performs the check for circular references and returns the + * referenced FileSet. + * @param Project $p + */ + function getRef(Project $p) { + if (!$this->checked) { + $stk = array(); + array_push($stk, $this); + $this->dieOnCircularReference($stk, $p); + } + + $o = $this->ref->getReferencedObject($p); + if (!($o instanceof FileList)) { + throw new BuildException($this->ref->getRefId()." doesn't denote a filelist"); + } else { + return $o; + } + } + + /** + * Reads file names from a file and adds them to the files array. + * @param Project $p + */ + private function readListFile(Project $p) { + $listReader = null; + try { + // Get a FileReader + $listReader = new BufferedReader(new FileReader($this->listfile)); + + $line = $listReader->readLine(); + while ($line !== null) { + if (!empty($line)) { + $line = $p->replaceProperties($line); + $this->filenames[] = trim($line); + } + $line = $listReader->readLine(); + } + } catch (Exception $e) { + if ($listReader) $listReader->close(); + throw new BuildException("An error occured while reading from list file " . $this->listfile->__toString() . ": " . $e->getMessage()); + } + + $listReader->close(); + } + +} + diff --git a/buildscripts/phing/classes/phing/types/FileSet.php b/buildscripts/phing/classes/phing/types/FileSet.php new file mode 100644 index 00000000..229e4419 --- /dev/null +++ b/buildscripts/phing/classes/phing/types/FileSet.php @@ -0,0 +1,56 @@ +<?php + +/* + * $Id: 1fbeb217059bb26788059dd46affde1428d5a52e $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +require_once 'phing/types/AbstractFileSet.php'; + +/** + * Moved out of MatchingTask to make it a standalone object that could + * be referenced (by scripts for example). + * + * @author Hans Lellelid <hans@xmpl.org> (Phing) + * @author Arnout J. Kuiper <ajkuiper@wxs.nl> (Ant) + * @author Stefano Mazzocchi <stefano@apache.org> (Ant) + * @author Sam Ruby <rubys@us.ibm.com> (Ant) + * @author Jon S. Stevens <jon@clearink.com> (Ant) + * @author Stefan Bodewig <stefan.bodewig@epost.de> (Ant) + * @author Magesh Umasankar (Ant) + * @package phing.types + */ +class FileSet extends AbstractFileSet { + + function __construct($fileset = null) { + parent::__construct($fileset); + } + + /** + * Return a FileSet that has the same basedir and same patternsets + * as this one. + */ + public function __clone() { + if ($this->isReference()) { + return new FileSet($this->getRef($this->getProject())); + } else { + return new FileSet($this); + } + } + +} diff --git a/buildscripts/phing/classes/phing/types/FilterChain.php b/buildscripts/phing/classes/phing/types/FilterChain.php new file mode 100755 index 00000000..e6575c33 --- /dev/null +++ b/buildscripts/phing/classes/phing/types/FilterChain.php @@ -0,0 +1,191 @@ +<?php +/* + * $Id: ec2362b430c0a863a77968e9003b09c4b9a78d7e $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +include_once 'phing/types/DataType.php'; +include_once 'phing/filters/HeadFilter.php'; +include_once 'phing/filters/IconvFilter.php'; +include_once 'phing/filters/TailFilter.php'; +include_once 'phing/filters/LineContains.php'; +include_once 'phing/filters/LineContainsRegexp.php'; +include_once 'phing/filters/ExpandProperties.php'; +include_once 'phing/filters/PrefixLines.php'; +include_once 'phing/filters/ReplaceRegexp.php'; +include_once 'phing/filters/ReplaceTokens.php'; +include_once 'phing/filters/ReplaceTokensWithFile.php'; +include_once 'phing/filters/StripPhpComments.php'; +include_once 'phing/filters/StripLineBreaks.php'; +include_once 'phing/filters/StripLineComments.php'; +include_once 'phing/filters/StripWhitespace.php'; +include_once 'phing/filters/TabToSpaces.php'; +include_once 'phing/filters/TidyFilter.php'; +include_once 'phing/filters/TranslateGettext.php'; +include_once 'phing/filters/XincludeFilter.php'; +include_once 'phing/filters/XsltFilter.php'; + +/** + * FilterChain may contain a chained set of filter readers. + * + * @author Yannick Lecaillez <yl@seasonfive.com> + * @version $Id$ + * @package phing.types + */ +class FilterChain extends DataType { + + private $filterReaders = array(); + + function __construct($project = null) { + if ($project) + { + $this->project = $project; + } + } + + function getFilterReaders() { + return $this->filterReaders; + } + + function addExpandProperties(ExpandProperties $o) { + $o->setProject($this->project); + $this->filterReaders[] = $o; + } + + function addGettext(TranslateGettext $o) { + $o->setProject($this->project); + $this->filterReaders[] = $o; + } + + function addHeadFilter(HeadFilter $o) { + $o->setProject($this->project); + $this->filterReaders[] = $o; + } + + function addIconvFilter(IconvFilter $o) { + $o->setProject($this->project); + $this->filterReaders[] = $o; + } + + function addTailFilter(TailFilter $o) { + $o->setProject($this->project); + $this->filterReaders[] = $o; + } + + function addLineContains(LineContains $o) { + $o->setProject($this->project); + $this->filterReaders[] = $o; + } + + function addLineContainsRegExp(LineContainsRegExp $o) { + $o->setProject($this->project); + $this->filterReaders[] = $o; + } + + function addPrefixLines(PrefixLines $o) { + $o->setProject($this->project); + $this->filterReaders[] = $o; + } + + function addReplaceTokens(ReplaceTokens $o) { + $o->setProject($this->project); + $this->filterReaders[] = $o; + } + + function addReplaceTokensWithFile(ReplaceTokensWithFile $o) { + $o->setProject($this->project); + $this->filterReaders[] = $o; + } + + function addReplaceRegexp(ReplaceRegexp $o) { + $o->setProject($this->project); + $this->filterReaders[] = $o; + } + + function addStripPhpComments(StripPhpComments $o) { + $o->setProject($this->project); + $this->filterReaders[] = $o; + } + + function addStripLineBreaks(StripLineBreaks $o) { + $o->setProject($this->project); + $this->filterReaders[] = $o; + } + + function addStripLineComments(StripLineComments $o) { + $o->setProject($this->project); + $this->filterReaders[] = $o; + } + + function addStripWhitespace(StripWhitespace $o) { + $o->setProject($this->project); + $this->filterReaders[] = $o; + } + + function addTidyFilter(TidyFilter $o) { + $o->setProject($this->project); + $this->filterReaders[] = $o; + } + + function addTabToSpaces(TabToSpaces $o) { + $o->setProject($this->project); + $this->filterReaders[] = $o; + } + + function addXincludeFilter(XincludeFilter $o) { + $o->setProject($this->project); + $this->filterReaders[] = $o; + } + + function addXsltFilter(XsltFilter $o) { + $o->setProject($this->project); + $this->filterReaders[] = $o; + } + + function addFilterReader(PhingFilterReader $o) { + $o->setProject($this->project); + $this->filterReaders[] = $o; + } + + /* + * Makes this instance in effect a reference to another FilterChain + * instance. + * + * <p>You must not set another attribute or nest elements inside + * this element if you make it a reference.</p> + * + * @param $r the reference to which this instance is associated + * @throws BuildException if this instance already has been configured. + */ + function setRefid(Reference $r) { + + if ( count($this->filterReaders) !== 0 ) { + throw $this->tooManyAttributes(); + } + + // change this to get the objects from the other reference + $o = $r->getReferencedObject($this->getProject()); + if ( $o instanceof FilterChain ) { + $this->filterReaders = $o->getFilterReaders(); + } else { + throw new BuildException($r->getRefId()." doesn't refer to a FilterChain"); + } + parent::setRefid($r); + } + +} diff --git a/buildscripts/phing/classes/phing/types/IterableFileSet.php b/buildscripts/phing/classes/phing/types/IterableFileSet.php new file mode 100644 index 00000000..bc800bbe --- /dev/null +++ b/buildscripts/phing/classes/phing/types/IterableFileSet.php @@ -0,0 +1,56 @@ +<?php +/* + * $Id: a607a54aa4e434c01a1f36600274fb31041549e2 $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +/** + * FileSet adapter to SPL's Iterator. + * + * @package phing.types + * @author Alexey Shockov <alexey@shockov.com> + * @since 2.4.0 + * @internal + */ +class IterableFileSet + extends FileSet + implements IteratorAggregate +{ + /** + * @return Iterator + */ + public function getIterator() + { + return new ArrayIterator($this->getFiles()); + } + /** + * @return array + */ + private function getFiles() + { + $directoryScanner = $this->getDirectoryScanner($this->getProject()); + $files = $directoryScanner->getIncludedFiles(); + + $baseDirectory = $directoryScanner->getBasedir(); + foreach ($files as $index => $file) { + $files[$index] = realpath($baseDirectory.'/'.$file); + } + + return $files; + } +} diff --git a/buildscripts/phing/classes/phing/types/Mapper.php b/buildscripts/phing/classes/phing/types/Mapper.php new file mode 100644 index 00000000..03042c64 --- /dev/null +++ b/buildscripts/phing/classes/phing/types/Mapper.php @@ -0,0 +1,207 @@ +<?php +/* + * $Id: bab760877500c0bb1ed4d6879c7e31c60c3fd307 $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +include_once 'phing/types/DataType.php'; +include_once 'phing/types/Path.php'; + +/** + * Filename Mapper maps source file name(s) to target file name(s). + * + * Built-in mappers can be accessed by specifying they "type" attribute: + * <code> + * <mapper type="glob" from="*.php" to="*.php.bak"/> + * </code> + * Custom mappers can be specified by providing a dot-path to a include_path-relative + * class: + * <code> + * <mapper classname="myapp.mappers.DevToProdMapper" from="*.php" to="*.php"/> + * <!-- maps all PHP files from development server to production server, for example --> + * </code> + * + * @author Hans Lellelid <hans@xmpl.org> + * @package phing.types + */ +class Mapper extends DataType { + + protected $type; + protected $classname; + protected $from; + protected $to; + protected $classpath; + protected $classpathId; + + + function __construct(Project $project) { + $this->project = $project; + } + + /** + * Set the classpath to be used when searching for component being defined + * + * @param Path $classpath An Path object containing the classpath. + */ + public function setClasspath(Path $classpath) { + if ($this->isReference()) { + throw $this->tooManyAttributes(); + } + if ($this->classpath === null) { + $this->classpath = $classpath; + } else { + $this->classpath->append($classpath); + } + } + + /** + * Create the classpath to be used when searching for component being defined + */ + public function createClasspath() { + if ($this->isReference()) { + throw $this->tooManyAttributes(); + } + if ($this->classpath === null) { + $this->classpath = new Path($this->project); + } + return $this->classpath->createPath(); + } + + /** + * Reference to a classpath to use when loading the files. + */ + public function setClasspathRef(Reference $r) { + if ($this->isReference()) { + throw $this->tooManyAttributes(); + } + $this->classpathId = $r->getRefId(); + $this->createClasspath()->setRefid($r); + } + + /** Set the type of FileNameMapper to use. */ + function setType($type) { + if ($this->isReference()) { + throw $this->tooManyAttributes(); + } + $this->type = $type; + } + + /** Set the class name of the FileNameMapper to use. */ + function setClassname($classname) { + if ($this->isReference()) { + throw $this->tooManyAttributes(); + } + $this->classname = $classname; + } + + /** + * Set the argument to FileNameMapper.setFrom + */ + function setFrom($from) { + if ($this->isReference()) { + throw $this->tooManyAttributes(); + } + $this->from = $from; + } + + /** + * Set the argument to FileNameMapper.setTo + */ + function setTo($to) { + if ($this->isReference()) { + throw $this->tooManyAttributes(); + } + $this->to = $to; + } + + /** + * Make this Mapper instance a reference to another Mapper. + * + * You must not set any other attribute if you make it a reference. + */ + function setRefid(Reference $r) { + if ($this->type !== null || $this->from !== null || $this->to !== null) { + throw DataType::tooManyAttributes(); + } + parent::setRefid($r); + } + + /** Factory, returns inmplementation of file name mapper as new instance */ + function getImplementation() { + if ($this->isReference()) { + $tmp = $this->getRef(); + return $tmp->getImplementation(); + } + + if ($this->type === null && $this->classname === null) { + throw new BuildException("either type or classname attribute must be set for <mapper>"); + } + + if ($this->type !== null) { + switch($this->type) { + case 'identity': + $this->classname = 'phing.mappers.IdentityMapper'; + break; + case 'flatten': + $this->classname = 'phing.mappers.FlattenMapper'; + break; + case 'glob': + $this->classname = 'phing.mappers.GlobMapper'; + break; + case 'regexp': + case 'regex': + $this->classname = 'phing.mappers.RegexpMapper'; + break; + case 'merge': + $this->classname = 'phing.mappers.MergeMapper'; + break; + default: + throw new BuildException("Mapper type {$this->type} not known"); + break; + } + } + + // get the implementing class + $cls = Phing::import($this->classname, $this->classpath); + + $m = new $cls; + $m->setFrom($this->from); + $m->setTo($this->to); + + return $m; + } + + /** Performs the check for circular references and returns the referenced Mapper. */ + private function getRef() { + if (!$this->checked) { + $stk = array(); + $stk[] = $this; + $this->dieOnCircularReference($stk, $this->project); + } + + $o = $this->ref->getReferencedObject($this->project); + if (!($o instanceof Mapper)) { + $msg = $this->ref->getRefId()." doesn't denote a mapper"; + throw new BuildException($msg); + } else { + return $o; + } + } +} + + diff --git a/buildscripts/phing/classes/phing/types/Parameter.php b/buildscripts/phing/classes/phing/types/Parameter.php new file mode 100644 index 00000000..cbba153c --- /dev/null +++ b/buildscripts/phing/classes/phing/types/Parameter.php @@ -0,0 +1,99 @@ +<?php +/* + * $Id: 725ec7b7d585219471bb8793da0210c7ab1452c0 $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. +*/ + +include_once 'phing/types/DataType.php'; + +/** + * A parameter is composed of a name, type and value. Nested + * Parameters are also possible, but the using task/type has + * to support them + * + * @author Manuel Holtgrewe + * @author <a href="mailto:yl@seasonfive.com">Yannick Lecaillez</a> + * @package phing.types + */ +class Parameter extends DataType { + + /** Parameter name */ + protected $name; + + /** Paramter type */ + protected $type; + + /** Parameter value */ + protected $value; + + /** Nested parameters */ + protected $parameters = array(); + + function setName($name) { + $this->name = (string) $name; + } + + function setType($type) { + $this->type = (string) $type; + } + + /** + * Sets value to dynamic register slot. + * @param RegisterSlot $value + */ + public function setListeningValue(RegisterSlot $value) { + $this->value = $value; + } + + function setValue($value) { + $this->value = (string) $value; + } + + function getName() { + return $this->name; + } + + function getType() { + return $this->type; + } + + function getValue() { + if ($this->value instanceof RegisterSlot) { + return $this->value->getValue(); + } else { + return $this->value; + } + } + + /** + * @return Parameter + */ + function createParam() { + $num = array_push($this->parameters, new Parameter()); + return $this->parameters[$num-1]; + } + + /** + * @return array Nested parameters. + */ + function getParams() { + return $this->parameters; + } +} + + diff --git a/buildscripts/phing/classes/phing/types/Parameterizable.php b/buildscripts/phing/classes/phing/types/Parameterizable.php new file mode 100644 index 00000000..7efe790a --- /dev/null +++ b/buildscripts/phing/classes/phing/types/Parameterizable.php @@ -0,0 +1,32 @@ +<?php + +/* + * $Id: e0d41388dad173e2dd61527524d6c3958683171b $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +/** + * Parameterizable objects take genric key value pairs. + * + * @author Hans Lellelid, hans@xmpl.org (Phing) + * @author Magesh Umasankar (Ant) + * @package phing.types + */ +interface Parameterizable { + function setParameters($parameters); +} diff --git a/buildscripts/phing/classes/phing/types/Path.php b/buildscripts/phing/classes/phing/types/Path.php new file mode 100644 index 00000000..b8525628 --- /dev/null +++ b/buildscripts/phing/classes/phing/types/Path.php @@ -0,0 +1,452 @@ +<?php +/* + * $Id: 762715ec83a12704f4ab528e507c28396c159083 $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +require_once 'phing/types/DataType.php'; +include_once 'phing/util/PathTokenizer.php'; +include_once 'phing/types/FileSet.php'; + +/** + * This object represents a path as used by include_path or PATH + * environment variable. + * + * This class has been adopted from the Java Ant equivalent. The ability have + * path structures in Phing is important; however, because of how PHP classes interact + * the ability to specify CLASSPATHs makes less sense than Java.Rather than providing + * CLASSPATH for any tasks that take classes as parameters, perhaps a better + * solution in PHP is to have an IncludePath task, which prepends paths to PHP's include_path + * INI variable. This gets around the problem that simply using a path to load the initial + * PHP class is not enough (in most cases the loaded class may assume that it is on the global + * PHP include_path, and will try to load dependent classes accordingly). The other option is + * to provide a way for this class to add paths to the include path, if desired -- or to create + * an IncludePath subclass. Once added, though, when would a path be removed from the include path? + * + * <p> + * <code> + * <sometask><br> + * <somepath><br> + * <pathelement location="/path/to/file" /><br> + * <pathelement path="/path/to/class2;/path/to/class3" /><br> + * <pathelement location="/path/to/file3" /><br> + * </somepath><br> + * </sometask><br> + * </code> + * <p> + * The object implemention <code>sometask</code> must provide a method called + * <code>createSomepath</code> which returns an instance of <code>Path</code>. + * Nested path definitions are handled by the Path object and must be labeled + * <code>pathelement</code>.<p> + * + * The path element takes a parameter <code>path</code> which will be parsed + * and split into single elements. It will usually be used + * to define a path from an environment variable. + * + * @author Hans Lellelid <hans@xmpl.org> (Phing) + * @author Thomas.Haas@softwired-inc.com (Ant) + * @author Stefan Bodewig <stefan.bodewig@epost.de> (Ant) + * @package phing.types + */ +class Path extends DataType { + + private $elements = array(); + + /** + * Constructor for internally instantiated objects sets project. + * @param Project $project + * @param string $path (for use by IntrospectionHelper) + */ + public function __construct($project = null, $path = null) { + if ($project !== null) { + $this->setProject($project); + } + if ($path !== null) { + $this->createPathElement()->setPath($path); + } + } + + /** + * Adds a element definition to the path. + * @param $location the location of the element to add (must not be + * <code>null</code> nor empty. + * @throws BuildException + */ + public function setDir(PhingFile $location) { + if ($this->isReference()) { + throw $this->tooManyAttributes(); + } + $this->createPathElement()->setDir($location); + } + + /** + * Parses a path definition and creates single PathElements. + * @param path the path definition. + * @throws BuildException + */ + public function setPath($path) { + if ($this->isReference()) { + throw $this->tooManyAttributes(); + } + $this->createPathElement()->setPath($path); + } + + /** + * Makes this instance in effect a reference to another Path instance. + * + * <p>You must not set another attribute or nest elements inside + * this element if you make it a reference.</p> + * @throws BuildException + */ + public function setRefid(Reference $r) { + if (!empty($this->elements)) { + throw $this->tooManyAttributes(); + } + $this->elements[] = $r; + parent::setRefid($r); + } + + /** + * Creates the nested <code><pathelement></code> element. + * @throws BuildException + */ + public function createPathElement() { + if ($this->isReference()) { + throw $this->noChildrenAllowed(); + } + $pe = new PathElement($this); + $this->elements[] = $pe; + return $pe; + } + + /** + * Adds a nested <code><fileset></code> element. + * @throws BuildException + */ + public function addFileset(FileSet $fs) { + if ($this->isReference()) { + throw $this->noChildrenAllowed(); + } + $this->elements[] = $fs; + $this->checked = false; + } + + /** + * Adds a nested <code><dirset></code> element. + * @throws BuildException + */ + public function addDirset(DirSet $dset) { + if ($this->isReference()) { + throw $this->noChildrenAllowed(); + } + $this->elements[] = $dset; + $this->checked = false; + } + + /** + * Creates a nested <code><path></code> element. + * @throws BuildException + */ + public function createPath() { + if ($this->isReference()) { + throw $this->noChildrenAllowed(); + } + $p = new Path($this->project); + $this->elements[] = $p; + $this->checked = false; + return $p; + } + + /** + * Append the contents of the other Path instance to this. + */ + public function append(Path $other) { + if ($other === null) { + return; + } + $l = $other->listPaths(); + foreach($l as $path) { + if (!in_array($path, $this->elements, true)) { + $this->elements[] = $path; + } + } + } + + /** + * Adds the components on the given path which exist to this + * Path. Components that don't exist, aren't added. + * + * @param Path $source - Source path whose components are examined for existence. + */ + public function addExisting(Path $source) { + $list = $source->listPaths(); + foreach($list as $el) { + $f = null; + if ($this->project !== null) { + $f = $this->project->resolveFile($el); + } else { + $f = new PhingFile($el); + } + + if ($f->exists()) { + $this->setDir($f); + } else { + $this->log("dropping " . $f->__toString() . " from path as it doesn't exist", + Project::MSG_VERBOSE); + } + } + } + + /** + * Returns all path elements defined by this and nested path objects. + * @return array List of path elements. + */ + public function listPaths() { + if (!$this->checked) { + // make sure we don't have a circular reference here + $stk = array(); + array_push($stk, $this); + $this->dieOnCircularReference($stk, $this->project); + } + + $result = array(); + for ($i = 0, $elSize=count($this->elements); $i < $elSize; $i++) { + $o = $this->elements[$i]; + if ($o instanceof Reference) { + $o = $o->getReferencedObject($this->project); + // we only support references to paths right now + if (!($o instanceof Path)) { + $msg = $r->getRefId() . " doesn't denote a path"; + throw new BuildException($msg); + } + } + + if (is_string($o)) { + $result[] = $o; + } elseif ($o instanceof PathElement) { + $parts = $o->getParts(); + if ($parts === null) { + throw new BuildException("You must either set location or" + . " path on <pathelement>"); + } + foreach($parts as $part) { + $result[] = $part; + } + } elseif ($o instanceof Path) { + $p = $o; + if ($p->getProject() === null) { + $p->setProject($this->getProject()); + } + $parts = $p->listPaths(); + foreach($parts as $part) { + $result[] = $part; + } + } elseif ($o instanceof DirSet) { + $dset = $o; + $ds = $dset->getDirectoryScanner($this->project); + $dirstrs = $ds->getIncludedDirectories(); + $dir = $dset->getDir($this->project); + foreach($dirstrs as $dstr) { + $d = new PhingFile($dir, $dstr); + $result[] = $d->getAbsolutePath(); + } + } elseif ($o instanceof FileList) { + $fl = $o; + $dirstrs = $fl->getFiles($this->project); + $dir = $fl->getDir($this->project); + foreach($dirstrs as $dstr) { + $d = new PhingFile($dir, $dstr); + $result[] = $d->getAbsolutePath(); + } + } + } + + return array_unique($result); + } + + + /** + * Returns a textual representation of the path, which can be used as + * CLASSPATH or PATH environment variable definition. + * @return string A textual representation of the path. + */ + public function __toString() { + + $list = $this->listPaths(); + + // empty path return empty string + if (empty($list)) { + return ""; + } + + return implode(PATH_SEPARATOR, $list); + } + + /** + * Splits a PATH (with : or ; as separators) into its parts. + * @param Project $project + * @param string $source + */ + public static function translatePath(Project $project, $source) { + $result = array(); + if ($source == null) { + return ""; + } + + $tok = new PathTokenizer($source); + while ($tok->hasMoreTokens()) { + $pathElement = $tok->nextToken(); + try { + $element = self::resolveFile($project, $pathElement); + for ($i = 0, $_i=strlen($element); $i < $_i; $i++) { + self::translateFileSep($element, $i); + } + $result[] = $element; + } catch (BuildException $e) { + $this->project->log("Dropping path element " . $pathElement + . " as it is not valid relative to the project", + Project::MSG_VERBOSE); + } + } + + return $result; + } + + /** + * Returns its argument with all file separator characters + * replaced so that they match the local OS conventions. + */ + public static function translateFile($source) { + if ($source == null) { + return ""; + } + + $result = $source; + for ($i = 0, $_i=strlen($source); $i < $_i; $i++) { + self::translateFileSep($result, $i); + } + + return $result; + } + + /** + * Translates all occurrences of / or \ to correct separator of the + * current platform and returns whether it had to do any + * replacements. + */ + protected static function translateFileSep(&$buffer, $pos) { + if ($buffer{$pos} == '/' || $buffer{$pos} == '\\') { + $buffer{$pos} = DIRECTORY_SEPARATOR; + return true; + } + return false; + } + + /** + * How many parts does this Path instance consist of. + * DEV NOTE: expensive call! list is generated, counted, and then + * discareded. + * @return int + */ + public function size() { + return count($this->listPaths()); + } + + /** + * Return a Path that holds the same elements as this instance. + */ + public function __clone() { + $p = new Path($this->project); + $p->append($this); + return $p; + } + + /** + * Overrides the version of DataType to recurse on all DataType + * child elements that may have been added. + * @throws BuildException + */ + public function dieOnCircularReference(&$stk, Project $p) { + + if ($this->checked) { + return; + } + + // elements can contain strings, FileSets, Reference, etc. + foreach($this->elements as $o) { + + if ($o instanceof Reference) { + $o = $o->getReferencedObject($p); + } + + if ($o instanceof DataType) { + if (in_array($o, $stk, true)) { + throw $this->circularReference(); + } else { + array_push($stk, $o); + $o->dieOnCircularReference($stk, $p); + array_pop($stk); + } + } + } + + $this->checked = true; + } + + /** + * Resolve a filename with Project's help - if we know one that is. + * + * <p>Assume the filename is absolute if project is null.</p> + */ + private static function resolveFile(Project $project, $relativeName) { + if ($project !== null) { + $f = $project->resolveFile($relativeName); + return $f->getAbsolutePath(); + } + return $relativeName; + } + +} + + +/** + * Helper class, holds the nested <code><pathelement></code> values. + * + * @package phing.types + */ +class PathElement { + + private $parts = array(); + private $outer; + + public function __construct(Path $outer) { + $this->outer = $outer; + } + + public function setDir(PhingFile $loc) { + $this->parts = array(Path::translateFile($loc->getAbsolutePath())); + } + + public function setPath($path) { + $this->parts = Path::translatePath($this->outer->getProject(), $path); + } + + public function getParts() { + return $this->parts; + } +} diff --git a/buildscripts/phing/classes/phing/types/PatternSet.php b/buildscripts/phing/classes/phing/types/PatternSet.php new file mode 100755 index 00000000..32967d62 --- /dev/null +++ b/buildscripts/phing/classes/phing/types/PatternSet.php @@ -0,0 +1,493 @@ +<?php +/* + * $Id: af3bd3709d79ad0299bf6ec0130a8a244ee325ab $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +include_once 'phing/system/io/FileReader.php'; +include_once 'phing/types/DataType.php'; + +/** + * The patternset storage component. Carries all necessary data and methods + * for the patternset stuff. + * + * @author Andreas Aderhold, andi@binarycloud.com + * @version $Id: af3bd3709d79ad0299bf6ec0130a8a244ee325ab $ + * @package phing.types + */ +class PatternSet extends DataType { + + private $includeList = array(); + private $excludeList = array(); + private $includesFileList = array(); + private $excludesFileList = array(); + + /** + * Makes this instance in effect a reference to another PatternSet + * instance. + * You must not set another attribute or nest elements inside + * this element if you make it a reference. + */ + function setRefid(Reference $r) { + if (!empty($this->includeList) || !empty($this->excludeList)) { + throw $this->tooManyAttributes(); + } + parent::setRefid($r); + } + + + /** + * Add a name entry on the include list + * + * @return PatternSetNameEntry Reference to object + * @throws BuildException + */ + function createInclude() { + if ($this->isReference()) { + throw $this->noChildrenAllowed(); + } + return $this->addPatternToList($this->includeList); + } + + + /** + * Add a name entry on the include files list + * + * @return PatternSetNameEntry Reference to object + * @throws BuildException + */ + function createIncludesFile() { + if ($this->isReference()) { + throw $this->noChildrenAllowed(); + } + return $this->addPatternToList($this->includesFileList); + } + + /** + * Add a name entry on the exclude list + * + * @return PatternSetNameEntry Reference to object + * @throws BuildException + */ + function createExclude() { + if ($this->isReference()) { + throw $this->noChildrenAllowed(); + } + return $this->addPatternToList($this->excludeList); + } + + /** + * add a name entry on the exclude files list + * + * @return PatternSetNameEntry Reference to object + * @throws BuildException + */ + function createExcludesFile() { + if ($this->isReference()) { + throw $this->noChildrenAllowed(); + return; + } + return $this->addPatternToList($this->excludesFileList); + } + + + /** + * Sets the set of include patterns. Patterns may be separated by a comma + * or a space. + * + * @param string the string containing the include patterns + * @return void + * @throws BuildException + */ + function setIncludes($includes) { + if ($this->isReference()) { + throw $this->tooManyAttributes(); + } + if ($includes !== null && strlen($includes) > 0) { + $tok = strtok($includes, ", "); + while ($tok !== false) { + $o = $this->createInclude(); + $o->setName($tok); + $tok = strtok(", "); + } + } + } + + + /** + * Sets the set of exclude patterns. Patterns may be separated by a comma + * or a space. + * + * @param string the string containing the exclude patterns + * @return void + * @throws BuildException + */ + function setExcludes($excludes) { + if ($this->isReference()) { + throw $this->tooManyAttributes(); + } + if ($excludes !== null && strlen($excludes) > 0) { + $tok = strtok($excludes, ", "); + while ($tok !== false) { + $o = $this->createExclude(); + $o->setName($tok); + $tok = strtok(", "); + } + } + } + + /** + * add a name entry to the given list + * + * @param array List onto which the nameentry should be added + * @return PatternSetNameEntry Reference to the created PsetNameEntry instance + */ + private function addPatternToList(&$list) { + $num = array_push($list, new PatternSetNameEntry()); + return $list[$num-1]; + } + + /** + * Sets the name of the file containing the includes patterns. + * + * @param includesFile The file to fetch the include patterns from. + */ + function setIncludesFile($includesFile) { + if ($this->isReference()) { + throw $this->tooManyAttributes(); + } + if ($includesFile instanceof File) { + $includesFile = $includesFile->getPath(); + } + $o = $this->createIncludesFile(); + $o->setName($includesFile); + } + + /** + * Sets the name of the file containing the excludes patterns. + * + * @param excludesFile The file to fetch the exclude patterns from. + */ + function setExcludesFile($excludesFile) { + if ($this->isReference()) { + throw $this->tooManyAttributes(); + } + if ($excludesFile instanceof File) { + $excludesFile = $excludesFile->getPath(); + } + $o = $this->createExcludesFile(); + $o->setName($excludesFile); + } + + + /** + * Reads path matching patterns from a file and adds them to the + * includes or excludes list + */ + private function readPatterns(PhingFile $patternfile, &$patternlist, Project $p) { + $patternReader = null; + try { + // Get a FileReader + $patternReader = new BufferedReader(new FileReader($patternfile)); + + // Create one NameEntry in the appropriate pattern list for each + // line in the file. + $line = $patternReader->readLine(); + while ($line !== null) { + if (!empty($line)) { + $line = $p->replaceProperties($line); + $this->addPatternToList($patternlist)->setName($line); + } + $line = $patternReader->readLine(); + } + + } catch (IOException $ioe) { + $msg = "An error occured while reading from pattern file: " . $patternfile->__toString(); + if($patternReader) $patternReader->close(); + throw new BuildException($msg, $ioe); + } + + $patternReader->close(); + } + + + /** Adds the patterns of the other instance to this set. */ + function append($other, $p) { + if ($this->isReference()) { + throw new BuildException("Cannot append to a reference"); + } + + $incl = $other->getIncludePatterns($p); + if ($incl !== null) { + foreach($incl as $incl_name) { + $o = $this->createInclude(); + $o->setName($incl_name); + } + } + + $excl = $other->getExcludePatterns($p); + if ($excl !== null) { + foreach($excl as $excl_name) { + $o = $this->createExclude(); + $o->setName($excl_name); + } + } + } + + /** Returns the filtered include patterns. */ + function getIncludePatterns(Project $p) { + if ($this->isReference()) { + $o = $this->getRef($p); + return $o->getIncludePatterns($p); + } else { + $this->readFiles($p); + return $this->makeArray($this->includeList, $p); + } + } + + /** Returns the filtered exclude patterns. */ + function getExcludePatterns(Project $p) { + if ($this->isReference()) { + $o = $this->getRef($p); + return $o->getExcludePatterns($p); + } else { + $this->readFiles($p); + return $this->makeArray($this->excludeList, $p); + } + } + + /** helper for FileSet. */ + function hasPatterns() { + return (boolean) count($this->includesFileList) > 0 || count($this->excludesFileList) > 0 + || count($this->includeList) > 0 || count($this->excludeList) > 0; + } + + /** + * Performs the check for circular references and returns the + * referenced PatternSet. + */ + function getRef(Project $p) { + if (!$this->checked) { + $stk = array(); + array_push($stk, $this); + $this->dieOnCircularReference($stk, $p); + } + $o = $this->ref->getReferencedObject($p); + if (!($o instanceof PatternSet)) { + $msg = $this->ref->getRefId()." doesn't denote a patternset"; + throw new BuildException($msg); + } else { + return $o; + } + } + + /** Convert a array of PatternSetNameEntry elements into an array of Strings. */ + private function makeArray(&$list, Project $p) { + + if (count($list) === 0) { + return null; + } + + $tmpNames = array(); + foreach($list as $ne) { + $pattern = (string) $ne->evalName($p); + if ($pattern !== null && strlen($pattern) > 0) { + array_push($tmpNames, $pattern); + } + } + return $tmpNames; + } + + /** Read includesfile or excludesfile if not already done so. */ + private function readFiles(Project $p) { + if (!empty($this->includesFileList)) { + foreach($this->includesFileList as $ne) { + $fileName = (string) $ne->evalName($p); + if ($fileName !== null) { + $inclFile = $p->resolveFile($fileName); + if (!$inclFile->exists()) { + throw new BuildException("Includesfile ".$inclFile->getAbsolutePath()." not found."); + } + $this->readPatterns($inclFile, $this->includeList, $p); + } + } + $this->includesFileList = array(); + } + + if (!empty($this->excludesFileList)) { + foreach($this->excludesFileList as $ne) { + $fileName = (string) $ne->evalName($p); + if ($fileName !== null) { + $exclFile = $p->resolveFile($fileName); + if (!$exclFile->exists()) { + throw new BuildException("Excludesfile ".$exclFile->getAbsolutePath()." not found."); + return; + } + $this->readPatterns($exclFile, $this->excludeList, $p); + } + } + $this->excludesFileList = array(); + } + } + + + function toString() { + + // We can't compile includeList into array because, toString() does + // not know about project: + // + // $includes = $this->makeArray($this->includeList, $this->project); + // $excludes = $this->makeArray($this->excludeList, $this->project); + + if (empty($this->includeList)) { + $includes = "empty"; + } else { + $includes = ""; + foreach($this->includeList as $ne) { + $includes .= $ne->toString() . ","; + } + $includes = rtrim($includes, ","); + } + + if (empty($this->excludeList)) { + $excludes = "empty"; + } else { + $excludes = ""; + foreach($this->excludeList as $ne) { + $excludes .= $ne->toString() . ","; + } + $excludes = rtrim($excludes, ","); + } + + return "patternSet{ includes: $includes excludes: $excludes }"; + } +} + + +/** + * "Internal" class for holding an include/exclude pattern. + * + * @package phing.types + */ +class PatternSetNameEntry { + + /** + * The pattern. + * @var string + */ + private $name; + + /** + * The if-condition property for this pattern to be applied. + * @var string + */ + private $ifCond; + + /** + * The unless-condition property for this pattern to be applied. + * @var string + */ + private $unlessCond; + + /** + * An alias for the setName() method. + * @see setName() + * @param string $pattern + */ + public function setPattern($pattern) { + $this->setName($pattern); + } + + /** + * Set the pattern text. + * @param string $name The pattern + */ + public function setName($name) { + $this->name = (string) $name; + } + + /** + * Sets an if-condition property for this pattern to match. + * @param string $cond + */ + public function setIf($cond) { + $this->ifCond = (string) $cond; + } + + + /** + * Sets an unless-condition property for this pattern to match. + * @param string $cond + */ + public function setUnless($cond) { + $this->unlessCond = (string) $cond; + } + + /** + * Get the pattern text. + * @return string The pattern. + */ + public function getName() { + return $this->name; + } + + /** + * Evaluates the pattern. + * @return string The pattern or null if it is ruled out by a condition. + */ + public function evalName(Project $project) { + return $this->valid($project) ? $this->name : null; + } + + + /** + * Checks whether pattern should be applied based on whether the if and unless + * properties are set in project. + * @param Project $project + * @return boolean + */ + public function valid(Project $project) { + if ($this->ifCond !== null && $project->getProperty($this->ifCond) === null) { + return false; + } else if ($this->unlessCond !== null && $project->getProperty($this->unlessCond) !== null) { + return false; + } + return true; + } + + /** + * Gets a string representation of this pattern. + * @return string + */ + public function toString() { + $buf = $this->name; + if (($this->ifCond !== null) || ($this->unlessCond !== null)) { + $buf .= ":"; + $connector = ""; + + if ($this->ifCond !== null) { + $buf .= "if->{$this->ifCond}"; + $connector = ";"; + } + if ($this->unlessCond !== null) { + $buf .= "$connector unless->{$this->unlessCond}"; + } + } + return $buf; + } +} diff --git a/buildscripts/phing/classes/phing/types/PearPackageFileSet.php b/buildscripts/phing/classes/phing/types/PearPackageFileSet.php new file mode 100644 index 00000000..8cf99b28 --- /dev/null +++ b/buildscripts/phing/classes/phing/types/PearPackageFileSet.php @@ -0,0 +1,179 @@ +<?php +/** + * Part of phing, the PHP build tool + * + * PHP version 5 + * + * @category Types + * @package phing.types + * @author Christian Weiske <cweiske@cweiske.de> + * @license LGPL v3 or later http://www.gnu.org/licenses/lgpl.html + * @version SVN: $Id: 5ba010b83645d0ea709761a3d8260fc013239458 $ + * @link http://www.phing.info/ + */ +require_once 'phing/types/FileSet.php'; +require_once 'PEAR/Config.php'; +require_once 'phing/util/PearPackageScanner.php'; + +/** + * Fileset that contains files of an installed PEAR package. + * It can be used to package up PEAR package dependencies in own + * release files (zip, tgz, phar). + * + * @internal + * A normal fileset is used that way in CopyTask, rSTTask: + * <code> + * $ds = $fs->getDirectoryScanner($project); + * $fromDir = $fs->getDir($project); + * $srcFiles = $ds->getIncludedFiles(); + * $srcDirs = $ds->getIncludedDirectories(); + * </code> + * The scanner is used as follows: + * <code> + * $ds->getBaseDir() + * $ds->scan() + * </code> + * + * @category Types + * @package phing.types + * @author Christian Weiske <cweiske@cweiske.de> + * @license LGPL v3 or later http://www.gnu.org/licenses/lgpl.html + * @link http://www.phing.info/ + */ +class PearPackageFileSet extends FileSet +{ + /** + * Name of channel the package is from, e.g. "pear.php.net". + * + * @var string + */ + protected $channel; + + /** + * Package name to get files from, e.g. "Console_CommandLine" + * + * @var string + */ + protected $package; + + /** + * Use files of that role only. + * Multiple roles are not supported, and you always have to specify one. + * + * @var string + */ + protected $role = 'php'; + + /** + * Prefix to prepend to the file paths in the zip + */ + protected $prefix; + + /** + * Full path to a PEAR config file. + * If none provided, default one is used. + */ + protected $config; + + /** + * @var PearPackageScanner instance + */ + protected $pps; + + + /** + * Creates and returns the pear package scanner. + * Scanner already has scan() called. + * + * @param Project $project Current phing project + * + * @return PearPackageScanner + */ + public function getDirectoryScanner(Project $project) + { + if ($this->isReference()) { + $obj = $this->getRef($project); + return $obj->getDirectoryScanner($project); + } + + $this->loadPearPackageScanner(); + return $this->pps; + } + + /** + * Returns the base directory all package files are relative to + * + * @return PhingFile Base directory + */ + public function getDir() + { + if ($this->pps === null) { + $this->loadPearPackageScanner(); + } + return new PhingFile((string) $this->pps->getBaseDir()); + } + + /** + * Loads the package scanner instance into $this->pps + * + * @return void + */ + protected function loadPearPackageScanner() + { + $this->pps = new PearPackageScanner(); + $this->pps->setPackage($this->package); + $this->pps->setChannel($this->channel); + $this->pps->setRole($this->role); + $this->pps->setConfig($this->config); + $this->pps->scan(); + } + + /** + * Sets the package name. + * If no channel is given, "pear.php.net" is used. + * + * @param string $package Single package name, or "channel/name" combination + * + * @return void + */ + public function setPackage($package) + { + $parts = explode('/', $package); + if (count($parts) > 2) { + throw new BuildException('Invalid package name: ' . $package); + } + + if (count($parts) == 1) { + $this->channel = 'pear.php.net'; + $this->package = $parts[0]; + } else { + $this->channel = $parts[0]; + $this->package = $parts[1]; + } + } + + /** + * Sets the role of files that should be included. + * Examples are php,doc,script + * + * @param string $role PEAR file role + * + * @return void + */ + public function setRole($role) + { + $this->role = $role; + } + + /** + * Sets the full path to the PEAR configuration file + * + * @param string $config Configuration file + * + * @return void + */ + public function setConfig($config) + { + $this->config = $config; + } +} diff --git a/buildscripts/phing/classes/phing/types/PhingFilterReader.php b/buildscripts/phing/classes/phing/types/PhingFilterReader.php new file mode 100755 index 00000000..2337977a --- /dev/null +++ b/buildscripts/phing/classes/phing/types/PhingFilterReader.php @@ -0,0 +1,136 @@ +<?php +/* + * $Id: fee06c9abce6700d773004bd83a5312d94c5aa29 $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. +*/ + +include_once 'phing/types/DataType.php'; +include_once 'phing/types/Parameter.php'; + +/** + * A PhingFilterReader is a wrapper class that encloses the className + * and configuration of a Configurable FilterReader. + * + * @author Yannick Lecaillez <yl@seasonfive.com> + * @version $Id$ + * @see FilterReader + * @package phing.types + */ +class PhingFilterReader extends DataType { + + private $className; + private $parameters = array(); + private $classPath; + + function setClassName($className) { + $this->className = $className; + } + + function getClassName() { + return $this->className; + } + + /** + * Set the classpath to load the FilterReader through (attribute). + * @param Path $classpath + */ + function setClasspath(Path $classpath) { + if ( $this->isReference() ) { + throw $this->tooManyAttributes(); + } + if ( $this->classPath === null ) { + $this->classPath = $classpath; + } else { + $this->classPath->append($classpath); + } + } + + /* + * Set the classpath to load the FilterReader through (nested element). + */ + function createClasspath() { + if ( $this->isReference() ) { + throw $this->noChildrenAllowed(); + } + if ( $this->classPath === null ) { + $this->classPath = new Path($this->project); + } + return $this->classPath->createPath(); + } + + function getClasspath() { + return $this->classPath; + } + + function setClasspathRef(Reference $r) { + if ( $this->isReference() ) { + throw $this->tooManyAttributes(); + } + $o = $this->createClasspath(); + $o->setRefid($r); + } + + function addParam(Parameter $param) { + $this->parameters[] = $param; + } + + function createParam() { + $num = array_push($this->parameters, new Parameter()); + return $this->parameters[$num-1]; + } + + function getParams() { + // We return a COPY + $ret = array(); + for($i=0,$size=count($this->parameters); $i < $size; $i++) { + $ret[] = clone $this->parameters[$i]; + } + return $ret; + } + + /* + * Makes this instance in effect a reference to another PhingFilterReader + * instance. + * + * <p>You must not set another attribute or nest elements inside + * this element if you make it a reference.</p> + * + * @param Reference $r the reference to which this instance is associated + * @exception BuildException if this instance already has been configured. + */ + function setRefid(Reference $r) { + if ( (count($this->parameters) !== 0) || ($this->className !== null) ) { + throw $this->tooManyAttributes(); + } + $o = $r->getReferencedObject($this->getProject()); + if ( $o instanceof PhingFilterReader ) { + $this->setClassName($o->getClassName()); + $this->setClasspath($o->getClassPath()); + foreach($o->getParams() as $p) { + $this->addParam($p); + } + } else { + $msg = $r->getRefId()." doesn\'t refer to a PhingFilterReader"; + throw new BuildException($msg); + } + + parent::setRefid($r); + } +} + + diff --git a/buildscripts/phing/classes/phing/types/Reference.php b/buildscripts/phing/classes/phing/types/Reference.php new file mode 100644 index 00000000..5f490b3f --- /dev/null +++ b/buildscripts/phing/classes/phing/types/Reference.php @@ -0,0 +1,56 @@ +<?php +/* + * $Id: 48c142f41717a31654d5cbfdb37f339e84adf391 $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +/** Class to hold a reference to another object in the project. + * @package phing.types + */ +class Reference { + + protected $refid; + + function __construct($id = null) { + if ($id !== null) { + $this->setRefId($id); + } + } + + function setRefId($id) { + $this->refid = (string) $id; + } + + function getRefId() { + return $this->refid; + } + + /** returns reference to object in references container of project */ + function getReferencedObject($project) { + if ($this->refid === null) { + throw new BuildException("No reference specified"); + } + $refs = $project->getReferences(); + $o = @$refs[$this->refid]; + if (!is_object($o)) { + throw new BuildException("Reference {$this->refid} not found."); + } + return $o; + } +} + diff --git a/buildscripts/phing/classes/phing/types/RegularExpression.php b/buildscripts/phing/classes/phing/types/RegularExpression.php new file mode 100755 index 00000000..84a25591 --- /dev/null +++ b/buildscripts/phing/classes/phing/types/RegularExpression.php @@ -0,0 +1,128 @@ +<?php +/* + * $Id: 257bd788b6185a3561f10a8de40502473076b6dd $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. +*/ + +include_once 'phing/types/DataType.php'; +include_once 'phing/Project.php'; +include_once 'phing/util/regexp/Regexp.php'; + +/** + * A regular expression datatype. Keeps an instance of the + * compiled expression for speed purposes. This compiled + * expression is lazily evaluated (it is compiled the first + * time it is needed). The syntax is the dependent on which + * regular expression type you are using. + * + * @author <a href="mailto:yl@seasonfive.com">Yannick Lecaillez</a> + * @version $Id$ + * @access public + * @see phing.util.regex.RegexMatcher + * @package phing.types +*/ +class RegularExpression extends DataType { + + private $regexp = null; + /** + * @todo Probably both $ignoreCase and $multiline should be removed + * from attribute list of RegularExpression class: + * actual values are preserved on regexp *engine* level, not expression + * object itself. + */ + private $ignoreCase = false; + private $multiline = false; + + function __construct() { + $this->regexp = new Regexp(); + } + + function setPattern($pattern) { + $this->regexp->setPattern($pattern); + } + + function setReplace($replace) { + $this->regexp->setReplace($replace); + } + + function getPattern($p) { + if ( $this->isReference() ) { + $ref = $this->getRef($p); + return $ref->getPattern($p); + } + return $this->regexp->getPattern(); + } + + function getReplace($p) { + if ( $this->isReference() ) { + $ref = $this->getRef($p); + return $ref->getReplace($p); + } + + return $this->regexp->getReplace(); + } + + function setModifiers($modifiers) { + $this->regexp->setModifiers($modifiers); + } + + function getModifiers() { + return $this->regexp->getModifiers(); + } + + function setIgnoreCase($bit) { + $this->regexp->setIgnoreCase($bit); + } + + function getIgnoreCase() { + return $this->regexp->getIgnoreCase(); + } + + function setMultiline($multiline) { + $this->regexp->setMultiline($multiline); + } + + function getMultiline() { + return $this->regexp->getMultiline(); + } + + function getRegexp(Project $p) { + if ( $this->isReference() ) { + $ref = $this->getRef($p); + return $ref->getRegexp($p); + } + return $this->regexp; + } + + function getRef(Project $p) { + if ( !$this->checked ) { + $stk = array(); + array_push($stk, $this); + $this->dieOnCircularReference($stk, $p); + } + + $o = $this->ref->getReferencedObject($p); + if ( !($o instanceof RegularExpression) ) { + throw new BuildException($this->ref->getRefId()." doesn't denote a RegularExpression"); + } else { + return $o; + } + } +} + + diff --git a/buildscripts/phing/classes/phing/types/TokenReader.php b/buildscripts/phing/classes/phing/types/TokenReader.php new file mode 100755 index 00000000..98ed3083 --- /dev/null +++ b/buildscripts/phing/classes/phing/types/TokenReader.php @@ -0,0 +1,66 @@ +<?php +/* + * $Id: c267e1935c57a372e5b8fc07eef73bd084195e82 $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. +*/ + +// include_once 'phing/system/io/Reader.php'; // really this is unrelated to Reader +include_once 'phing/system/io/IOException.php'; +include_once 'phing/filters/ReplaceTokens.php'; // For class Token + +/** + * Abstract class for TokenReaders. + * + * @author Manuel Holtgewe + * @version $Id$ + * @package phing.filters.util + */ +abstract class TokenReader { + + /** + * Reference to the Project the TokenReader is used in. + * @var Project + */ + protected $project; + + /** + * Constructor + * @param object Reference to the project the TokenReader is used in. + */ + function __construct(Project $project) { + $this->project = $project; + } + + /** + * Utility function for logging + */ + function log($level, $msg) { + $this->project->log($level, $msg); + } + + /** + * Reads the next token from the Reader + * + * @throws IOException - On error + * @return string + */ + abstract public function readToken(); + +} + + diff --git a/buildscripts/phing/classes/phing/types/TokenSource.php b/buildscripts/phing/classes/phing/types/TokenSource.php new file mode 100644 index 00000000..0ca0367a --- /dev/null +++ b/buildscripts/phing/classes/phing/types/TokenSource.php @@ -0,0 +1,157 @@ +<?php +/* + * $Id: 1bc91e925ce194c2e7a615e8f8c950d2057a9cb5 $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. +*/ + +require_once 'phing/types/DataType.php'; +include_once 'phing/util/StringHelper.php'; + +/** + * A parameter is composed of a name, type and value. + * + * Example of usage: + * + * <replacetokens> + * <tokensource classname="phing.filters.util.IniFileTokenReader"> + * <!-- all params for the TokenReader here --> + * <param name="file" value="tokens.ini" /> + * </tokensource> + * </replacetokens> + * + * or: + * + * <filterreader classname="phing.filters.ReplaceTokens"> + * <param type="tokensource> + * <param name="classname" value="phing.filters.util.IniFileTokenReader" /> + * <param name="file" value="tokens.ini" /> + * </param> + * </filterreader> + * + * @author <a href="mailto:yl@seasonfive.com">Yannick Lecaillez</a> + * @package phing.types + */ +class TokenSource extends DataType { + + /** + * String to hold the path to the TokenReader + * @var string + */ + protected $classname = null; + + /** + * Array holding parameters for the wrapped TokenReader. + * @var array + */ + protected $parameters = array(); + + /** + * Reference to the TokenReader used by this TokenSource + * @var TokenReader + */ + protected $reader; + + /** + * Array with key/value pairs of tokens + */ + protected $tokens = array(); + + /** + * This method is called to load the sources from the reader + * into the buffer of the source. + */ + function load() { + // Create new Reader + if ($this->classname === null) { + throw new BuildException("No Classname given to TokenSource."); + } + + $classname = Phing::import($this->classname); + $this->reader = new $classname($this->project); + + // Configure Reader + $this->configureTokenReader($this->reader); + + // Load Tokens + try { + while ($token = $this->reader->readToken()) { + $this->tokens[] = $token; + } + } catch (BuildException $e) { + $this->log("Error reading TokenSource: " . $e->getMessage(), Project::MSG_WARN); + } catch (IOException $e) { + $this->log("Error reading TokenSource: " . $e->getMessage(), Project::MSG_WARN); + } + } + + /** + * This function uses the wrapper to read the tokens and then + * returns them. + * + * @access public + */ + function getTokens() { + if ($this->tokens === null) + $this->Load(); + + return $this->tokens; + } + + /** + * Configures a TokenReader with the parameters passed to the + * TokenSource. + * @param TokenReader $reader + */ + private function configureTokenReader(TokenReader $reader) { + $count = count($this->parameters); + for ($i = 0; $i < $count; $i++) { + $method_name = "Set" . $this->parameters[$i]->getName(); + $value = $this->parameters[$i]->getValue(); + $reader->$method_name($value); + } + } + + /** + * Set the classname (dot-path) to use for handling token replacement. + * @param string $c + */ + function setClassname($c) { + $this->classname = $c; + } + + /** + * Returns the qualified classname (dot-path) to use for handling token replacement. + * @return string + */ + function getClassname() { + return $this->classname; + } + + /** + * Create nested <param> tag. + * Uses standard name/value Parameter class. + * @return Parameter + */ + function createParam() { + $num = array_push($this->parameters, new Parameter()); + return $this->parameters[$num-1]; + } +} + + + diff --git a/buildscripts/phing/classes/phing/types/defaults.properties b/buildscripts/phing/classes/phing/types/defaults.properties new file mode 100644 index 00000000..a2d86350 --- /dev/null +++ b/buildscripts/phing/classes/phing/types/defaults.properties @@ -0,0 +1,13 @@ +# phing default types +commandline=phing.types.Commandline +fileset=phing.types.FileSet +dirset=phing.types.DirSet +filelist=phing.types.FileList +patternset=phing.types.PatternSet +mapper=phing.types.Mapper +filterchain=phing.types.FilterChain +filterreader=phing.types.PhingFilterReader +regexp=phing.types.RegularExpression +param=phing.types.Parameter +path=phing.types.Path +selector=phing.types.selectors.SelectSelector
\ No newline at end of file diff --git a/buildscripts/phing/classes/phing/types/selectors/AndSelector.php b/buildscripts/phing/classes/phing/types/selectors/AndSelector.php new file mode 100644 index 00000000..1a27829d --- /dev/null +++ b/buildscripts/phing/classes/phing/types/selectors/AndSelector.php @@ -0,0 +1,67 @@ +<?php +/* + * $Id: f36556afb9487cce2e56d5c174e3ce4c43ef968f $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +require_once 'phing/types/selectors/BaseSelectorContainer.php'; + +/** + * This selector has a collection of other selectors, all of which have to + * select a file in order for this selector to select it. + * + * @author Hans Lellelid, hans@xmpl.org (Phing) + * @author <a href="mailto:bruce@callenish.com">Bruce Atherton</a> (Ant) + * @package phing.types.selectors + */ +class AndSelector extends BaseSelectorContainer { + + public function toString() { + $buf = ""; + if ($this->hasSelectors()) { + $buf .= "{andselect: "; + $buf .= parent::toString(); + $buf .= "}"; + } + return $buf; + } + + /** + * Returns true (the file is selected) only if all other selectors + * agree that the file should be selected. + * + * @param basedir the base directory the scan is being done from + * @param filename the name of the file to check + * @param file a PhingFile object for the filename that the selector + * can use + * @return whether the file should be selected or not + */ + public function isSelected(PhingFile $basedir, $filename, PhingFile $file) { + $this->validate(); + $selectors = $this->selectorElements(); + for($i=0,$size=count($selectors); $i < $size; $i++) { + $result = $selectors[$i]->isSelected($basedir, $filename, $file); + if (!$result) { + return false; + } + } + return true; + } + +} + diff --git a/buildscripts/phing/classes/phing/types/selectors/BaseExtendSelector.php b/buildscripts/phing/classes/phing/types/selectors/BaseExtendSelector.php new file mode 100644 index 00000000..d8ae0444 --- /dev/null +++ b/buildscripts/phing/classes/phing/types/selectors/BaseExtendSelector.php @@ -0,0 +1,62 @@ +<?php + +/* + * $Id: 0c36c2b00f8ab8d20025b9ad38043c762b6fc7f9 $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +require_once 'phing/types/selectors/ExtendFileSelector.php'; +require_once 'phing/types/selectors/BaseSelector.php'; +include_once 'phing/types/Parameter.php'; + +/** + * Convenience base class for all selectors accessed through ExtendSelector. + * It provides support for gathering the parameters together as well as for + * assigning an error message and throwing a build exception if an error is + * detected. + * + * @author Hans Lellelid, hans@xmpl.org (Phing) + * @author Bruce Atherton, bruce@callenish.com (Ant) + * @package phing.types.selectors + */ +abstract class BaseExtendSelector extends BaseSelector implements ExtendFileSelector { + + /** The passed in parameter array. */ + protected $parameters = null; + + /** + * Set all the Parameters for this custom selector, collected by + * the ExtendSelector class. + * + * @param parameters the complete set of parameters for this selector + */ + public function setParameters($parameters) { + $this->parameters = $parameters; + } + + /** + * Allows access to the parameters gathered and set within the + * <custom> tag. + * + * @return the set of parameters defined for this selector + */ + protected function getParameters() { + return $this->parameters; + } +} + diff --git a/buildscripts/phing/classes/phing/types/selectors/BaseSelector.php b/buildscripts/phing/classes/phing/types/selectors/BaseSelector.php new file mode 100644 index 00000000..c463fa33 --- /dev/null +++ b/buildscripts/phing/classes/phing/types/selectors/BaseSelector.php @@ -0,0 +1,84 @@ +<?php +/* + * $Id: e1f8e20eb87ea465d29ba3add6fada790642bcf8 $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +require_once 'phing/types/selectors/FileSelector.php'; + +/** + * A convenience base class that you can subclass Selectors from. It + * provides some helpful common behaviour. Note that there is no need + * for Selectors to inherit from this class, it is only necessary that + * they implement FileSelector. + * + * @author <a href="mailto:bruce@callenish.com">Bruce Atherton</a> + * @package phing.types.selectors + */ +abstract class BaseSelector extends DataType implements FileSelector { + + private $errmsg = null; + + /** + * Allows all selectors to indicate a setup error. Note that only + * the first error message is recorded. + * + * @param msg The error message any BuildException should throw. + */ + public function setError($msg) { + if ($this->errmsg === null) { + $this->errmsg = $msg; + } + } + + /** + * Returns any error messages that have been set. + * + * @return the error condition + */ + public function getError() { + return $this->errmsg; + } + + + /** + * <p>Subclasses can override this method to provide checking of their + * state. So long as they call validate() from isSelected(), this will + * be called automatically (unless they override validate()).</p> + * <p>Implementations should check for incorrect settings and call + * setError() as necessary.</p> + */ + public function verifySettings() { + } + + /** + * Subclasses can use this to throw the requisite exception + * in isSelected() in the case of an error condition. + */ + public function validate() { + if ($this->getError() === null) { + $this->verifySettings(); + } + if ($this->getError() !== null) { + throw new BuildException($this->errmsg); + } + } + +} + + diff --git a/buildscripts/phing/classes/phing/types/selectors/BaseSelectorContainer.php b/buildscripts/phing/classes/phing/types/selectors/BaseSelectorContainer.php new file mode 100644 index 00000000..3b2a10b1 --- /dev/null +++ b/buildscripts/phing/classes/phing/types/selectors/BaseSelectorContainer.php @@ -0,0 +1,270 @@ +<?php + +/* + * $Id: 9dd90d3e78d751562859bbe5179db148ee5b025c $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +require_once 'phing/types/selectors/SelectorContainer.php'; +require_once 'phing/types/selectors/BaseSelector.php'; + +/** + * This is the base class for selectors that can contain other selectors. + * + * @author <a href="mailto:bruce@callenish.com">Bruce Atherton</a> (Ant) + * @package phing.types.selectors + */ +abstract class BaseSelectorContainer extends BaseSelector implements SelectorContainer { + + private $selectorsList = array(); + + /** + * Indicates whether there are any selectors here. + */ + public function hasSelectors() { + return !(empty($this->selectorsList)); + } + + /** + * Gives the count of the number of selectors in this container + */ + public function selectorCount() { + return count($this->selectorsList); + } + + /** + * Returns a copy of the selectors as an array. + */ + public function getSelectors(Project $p) { + $result = array(); + for($i=0,$size=count($this->selectorsList); $i < $size; $i++) { + $result[] = clone $this->selectorsList[$i]; + } + return $result; + } + + /** + * Returns an array for accessing the set of selectors (not a copy). + */ + public function selectorElements() { + return $this->selectorsList; + } + + /** + * Convert the Selectors within this container to a string. This will + * just be a helper class for the subclasses that put their own name + * around the contents listed here. + * + * @return comma separated list of Selectors contained in this one + */ + public function toString() { + $buf = ""; + $arr = $this->selectorElements(); + for($i=0,$size=count($arr); $i < $size; $i++) { + $buf .= $arr[$i]->toString() . (isset($arr[$i+1]) ? ', ' : ''); + } + return $buf; + } + + /** + * Add a new selector into this container. + * + * @param selector the new selector to add + * @return the selector that was added + */ + public function appendSelector(FileSelector $selector) { + $this->selectorsList[] = $selector; + } + + /** + * <p>This implementation validates the container by calling + * verifySettings() and then validates each contained selector + * provided that the selector implements the validate interface. + * </p> + * <p>Ordinarily, this will validate all the elements of a selector + * container even if the isSelected() method of some elements is + * never called. This has two effects:</p> + * <ul> + * <li>Validation will often occur twice. + * <li>Since it is not required that selectors derive from + * BaseSelector, there could be selectors in the container whose + * error conditions are not detected if their isSelected() call + * is never made. + * </ul> + */ + public function validate() { + $this->verifySettings(); + $errmsg = $this->getError(); + if ($errmsg !== null) { + throw new BuildException($errmsg); + } + foreach($this->selectorsList as $o) { + if ($o instanceof BaseSelector) { + $o->validate(); + } + } + } + + /* Methods below all add specific selectors */ + + /** + * add a "Select" selector entry on the selector list + */ + public function createSelector() { + $o = new SelectSelector(); + $this->appendSelector($o); + return $o; + } + + /** + * add an "And" selector entry on the selector list + */ + public function createAnd() { + $o = new AndSelector(); + $this->appendSelector($o); + return $o; + } + + /** + * add an "Or" selector entry on the selector list + */ + public function createOr() { + $o = new OrSelector(); + $this->appendSelector($o); + return $o; + } + + /** + * add a "Not" selector entry on the selector list + */ + public function createNot() { + $o = new NotSelector(); + $this->appendSelector($o); + return $o; + } + + /** + * add a "None" selector entry on the selector list + */ + public function createNone() { + $o = new NoneSelector(); + $this->appendSelector($o); + return $o; + } + + /** + * add a majority selector entry on the selector list + */ + public function createMajority() { + $o = new MajoritySelector(); + $this->appendSelector($o); + return $o; + } + + /** + * add a selector date entry on the selector list + */ + public function createDate() { + $o = new DateSelector(); + $this->appendSelector($o); + return $o; + } + + /** + * add a selector size entry on the selector list + */ + public function createSize() { + $o = new SizeSelector(); + $this->appendSelector($o); + return $o; + } + + /** + * add a selector filename entry on the selector list + */ + public function createFilename() { + $o = new FilenameSelector(); + $this->appendSelector($o); + return $o; + } + + /** + * add an extended selector entry on the selector list + */ + public function createCustom() { + $o = new ExtendSelector(); + $this->appendSelector($o); + return $o; + } + + /** + * add a contains selector entry on the selector list + */ + public function createContains() { + $o = new ContainsSelector(); + $this->appendSelector($o); + return $o; + } + + /** + * add a contains selector entry on the selector list + */ + public function createContainsRegexp() { + $o = new ContainsRegexpSelector(); + $this->appendSelector($o); + return $o; + } + + /** + * add a present selector entry on the selector list + */ + public function createPresent() { + $o = new PresentSelector(); + $this->appendSelector($o); + return $o; + } + + /** + * add a depth selector entry on the selector list + */ + public function createDepth() { + $o = new DepthSelector(); + $this->appendSelector($o); + return $o; + } + + /** + * add a depends selector entry on the selector list + */ + public function createDepend() { + $o = new DependSelector(); + $this->appendSelector($o); + return $o; + } + + /** + * add a type selector entry on the selector list + */ + public function createType() { + $o = new TypeSelector(); + $this->appendSelector($o); + return $o; + } + +} + diff --git a/buildscripts/phing/classes/phing/types/selectors/ContainsRegexpSelector.php b/buildscripts/phing/classes/phing/types/selectors/ContainsRegexpSelector.php new file mode 100755 index 00000000..5b45bac8 --- /dev/null +++ b/buildscripts/phing/classes/phing/types/selectors/ContainsRegexpSelector.php @@ -0,0 +1,164 @@ +<?php + +/* + * $Id: 2a891d7cc3fb1b710b72d51e6a8cf2d0b553f91a $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +require_once 'phing/types/selectors/BaseExtendSelector.php'; +include_once 'phing/types/RegularExpression.php'; + +/** + * Selector that filters files based on whether they contain a + * particular string using regexp. + * + * @author Hans Lellelid <hans@xmpl.org> (Phing) + * @author Bruce Atherton <bruce@callenish.com> (Ant) + * @version $Id$ + * @package phing.types.selectors + */ +class ContainsRegexpSelector extends BaseExtendSelector { + + /** @var string The expression set from XML. */ + private $userProvidedExpression; + + /** @var Regexp */ + private $myExpression; + + private $casesensitive = true; + + /** @var RegularExpression */ + private $myRegExp; + + const EXPRESSION_KEY = "expression"; + + const CASE_KEY = "casesensitive"; + + public function toString() { + $buf = "{containsregexpselector expression: "; + $buf .= $this->userProvidedExpression; + $buf .= " casesensitive: "; + if ($this->casesensitive) { + $buf .= "true"; + } else { + $buf .= "false"; + } + $buf .= "}"; + return $buf; + } + + /** + * The expression to match on within a file. + * + * @param string $exp the string that a file must contain to be selected. + */ + public function setExpression($exp) { + $this->userProvidedExpression = $exp; + } + + /** + * Whether to ignore case in the regex match. + * + * @param boolean $casesensitive whether to pay attention to case sensitivity + */ + public function setCasesensitive($casesensitive) { + $this->casesensitive = $casesensitive; + } + + /** + * When using this as a custom selector, this method will be called. + * It translates each parameter into the appropriate setXXX() call. + * + * @param array $parameters the complete set of parameters for this selector + */ + public function setParameters($parameters) { + parent::setParameters($parameters); + if ($parameters !== null) { + for ($i=0,$size=count($parameters); $i < $size; $i++) { + $paramname = $parameters[$i]->getName(); + switch(strtolower($paramname)) { + case self::EXPRESSION_KEY: + $this->setExpression($parameters[$i]->getValue()); + break; + case self::CASE_KEY: + $this->setCasesensitive($parameters[$i]->getValue()); + break; + default: + $this->setError("Invalid parameter " . $paramname); + } + } // for each param + } // if params + } + + /** + * Checks to make sure all settings are kosher. In this case, it + * means that the pattern attribute has been set. + * + */ + public function verifySettings() { + if ($this->userProvidedExpression === null) { + $this->setError("The expression attribute is required"); + } + } + + /** + * The heart of the matter. This is where the selector gets to decide + * on the inclusion of a file in a particular fileset. + * + * @param basedir the base directory the scan is being done from + * @param filename is the name of the file to check + * @param file a PhingFile object the selector can use + * @return whether the file should be selected or not + */ + public function isSelected(PhingFile $basedir, $filename, PhingFile $file) { + + $this->validate(); + + if ($file->isDirectory()) { + return true; + } + + if ($this->myRegExp === null) { + $this->myRegExp = new RegularExpression(); + $this->myRegExp->setPattern($this->userProvidedExpression); + if (!$this->casesensitive) { + $this->myRegExp->setIgnoreCase(true); + } + $this->myExpression = $this->myRegExp->getRegexp($this->getProject()); + } + + $in = null; + try { + $in = new BufferedReader(new FileReader($file)); + $teststr = $in->readLine(); + while ($teststr !== null) { + if ($this->myExpression->matches($teststr)) { + return true; + } + $teststr = $in->readLine(); + } + return false; + } catch (IOException $ioe) { + if ($in) $in->close(); + throw new BuildException("Could not read file " . $filename); + } + $in->close(); + } + +} + diff --git a/buildscripts/phing/classes/phing/types/selectors/ContainsSelector.php b/buildscripts/phing/classes/phing/types/selectors/ContainsSelector.php new file mode 100644 index 00000000..5e270583 --- /dev/null +++ b/buildscripts/phing/classes/phing/types/selectors/ContainsSelector.php @@ -0,0 +1,151 @@ +<?php + +/* + * $Id: ab2c641c048573b0a9976b7cb92138b8ceda511f $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +include_once 'phing/types/selectors/BaseExtendSelector.php'; + +/** + * Selector that filters files based on whether they contain a + * particular string. + * + * @author Hans Lellelid <hans@xmpl.org> (Phing) + * @author Bruce Atherton <bruce@callenish.com> (Ant) + * @package phing.types.selectors + */ +class ContainsSelector extends BaseExtendSelector { + + private $contains = null; + private $casesensitive = true; + const CONTAINS_KEY = "text"; + const CASE_KEY = "casesensitive"; + + public function toString() { + $buf = "{containsselector text: "; + $buf .= $this->contains; + $buf .= " casesensitive: "; + if ($this->casesensitive) { + $buf .= "true"; + } else { + $buf .= "false"; + } + $buf .= "}"; + return $buf; + } + + /** + * The string to search for within a file. + * + * @param string $contains the string that a file must contain to be selected. + */ + public function setText($contains) { + $this->contains = $contains; + } + + /** + * Whether to ignore case in the string being searched. + * + * @param boolean $casesensitive whether to pay attention to case sensitivity + */ + public function setCasesensitive($casesensitive) { + $this->casesensitive = $casesensitive; + } + + /** + * When using this as a custom selector, this method will be called. + * It translates each parameter into the appropriate setXXX() call. + * + * @param array $parameters the complete set of parameters for this selector + */ + public function setParameters($parameters) { + parent::setParameters($parameters); + if ($parameters !== null) { + for ($i=0,$size=count($parameters); $i < $size; $i++) { + $paramname = $parameters[$i]->getName(); + switch(strtolower($paramname)) { + case self::CONTAINS_KEY: + $this->setText($parameters[$i]->getValue()); + break; + case self::CASE_KEY: + $this->setCasesensitive($parameters[$i]->getValue()); + break; + default: + $this->setError("Invalid parameter " . $paramname); + } + } // for each param + } // if params + } + + /** + * Checks to make sure all settings are kosher. In this case, it + * means that the pattern attribute has been set. + * + */ + public function verifySettings() { + if ($this->contains === null) { + $this->setError("The text attribute is required"); + } + } + + /** + * The heart of the matter. This is where the selector gets to decide + * on the inclusion of a file in a particular fileset. + * + * @param basedir the base directory the scan is being done from + * @param filename is the name of the file to check + * @param file a PhingFile object the selector can use + * @return whether the file should be selected or not + */ + public function isSelected(PhingFile $basedir, $filename, PhingFile $file) { + + $this->validate(); + + if ($file->isDirectory()) { + return true; + } + + $userstr = $this->contains; + if (!$this->casesensitive) { + $userstr = strtolower($this->contains); + } + + $in = null; + try { + $in = new BufferedReader(new FileReader($file)); + $teststr = $in->readLine(); + while ($teststr !== null) { + if (!$this->casesensitive) { + $teststr = strtolower($teststr); + } + if (strpos($teststr, $userstr) !== false) { + return true; + } + $teststr = $in->readLine(); + } + return false; + } catch (IOException $ioe) { + if ($in) $in->close(); + throw new BuildException("Could not read file " . $filename); + } + $in->close(); + } + +} + diff --git a/buildscripts/phing/classes/phing/types/selectors/DateSelector.php b/buildscripts/phing/classes/phing/types/selectors/DateSelector.php new file mode 100755 index 00000000..0f8c28a8 --- /dev/null +++ b/buildscripts/phing/classes/phing/types/selectors/DateSelector.php @@ -0,0 +1,214 @@ +<?php + +/* + * $Id: f05cee91082616c66b2e109157b1d2f2298a66f8 $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +require_once 'phing/types/selectors/BaseExtendSelector.php'; + +/** + * Selector that chooses files based on their last modified date. Ant uses + * millisecond precision (thanks to Java); PHP is forced to use only seconds + * precision. + * + * @author Hans Lellelid <hans@xmpl.org> (Phing) + * @author Bruce Atherton <bruce@callenish.com> (Ant) + * @version $Id: f05cee91082616c66b2e109157b1d2f2298a66f8 $ + * @package phing.types.selectors + */ +class DateSelector extends BaseExtendSelector { + + private $seconds = -1; // millis in Ant, but PHP doesn't support that level of precision + private $dateTime = null; + private $includeDirs = false; + private $granularity = 0; + private $cmp = 2; + const MILLIS_KEY = "millis"; + const DATETIME_KEY = "datetime"; + const CHECKDIRS_KEY = "checkdirs"; + const GRANULARITY_KEY = "granularity"; + const WHEN_KEY = "when"; + private static $timeComparisons = array("before", "after", "equal"); + + public function __construct() { + //if (Os.isFamily("dos")) { + // granularity = 2000; + //} + } + + public function toString() { + $buf = "{dateselector date: "; + $buf .= $this->dateTime; + $buf .= " compare: "; + if ($this->cmp === 0) { + $buf .= "before"; + } elseif ($this->cmp === 1) { + $buf .= "after"; + } else { + $buf .= "equal"; + } + $buf .= " granularity: "; + $buf .= $this->granularity; + $buf .= "}"; + return $buf; + } + + /** + * For users that prefer to express time in seconds since 1970 + * + * @param int $seconds the time to compare file's last modified date to, + * expressed in milliseconds + */ + public function setSeconds($seconds) { + $this->seconds = (int) $seconds; + } + + /** + * Returns the seconds value the selector is set for. + */ + public function getSeconds() { + return $this->seconds; + } + + /** + * Sets the date. The user must supply it in MM/DD/YYYY HH:MM AM_PM + * format + * + * @param string $dateTime a string in MM/DD/YYYY HH:MM AM_PM format + */ + public function setDatetime($dateTime) { + $dt = strtotime($dateTime); + if ($dt == -1) { + $this->setError("Date of " . $dateTime + . " Cannot be parsed correctly. It should be in" + . " a format parsable by PHP's strtotime() function."); + } else { + $this->dateTime = $dateTime; + $this->setSeconds($dt); + } + } + + /** + * Should we be checking dates on directories? + * + * @param boolean $includeDirs whether to check the timestamp on directories + */ + public function setCheckdirs($includeDirs) { + $this->includeDirs = (boolean) $includeDirs; + } + + /** + * Sets the number of milliseconds leeway we will give before we consider + * a file not to have matched a date. + * @param int $granularity + */ + public function setGranularity($granularity) { + $this->granularity = (int) $granularity; + } + + /** + * Sets the type of comparison to be done on the file's last modified + * date. + * + * @param string $cmp The comparison to perform + */ + public function setWhen($cmp) { + $idx = array_search($cmp, self::$timeComparisons, true); + if ($idx === null) { + $this->setError("Invalid value for ".WHEN_KEY.": ".$cmp); + } else { + $this->cmp = $idx; + } + } + + /** + * When using this as a custom selector, this method will be called. + * It translates each parameter into the appropriate setXXX() call. + * + * @param array $parameters the complete set of parameters for this selector + */ + public function setParameters($parameters) { + parent::setParameters($parameters); + if ($parameters !== null) { + for ($i=0,$size=count($parameters); $i < $size; $i++) { + $paramname = $parameters[$i]->getName(); + switch(strtolower($paramname)) { + case self::MILLIS_KEY: + $this->setMillis($parameters[$i]->getValue()); + break; + case self::DATETIME_KEY: + $this->setDatetime($parameters[$i]->getValue()); + break; + case self::CHECKDIRS_KEY: + $this->setCheckdirs($parameters[$i]->getValue()); + break; + case self::GRANULARITY_KEY: + $this->setGranularity($parameters[$i]->getValue()); + break; + case self::WHEN_KEY: + $this->setWhen($parameters[$i]->getValue()); + break; + default: + $this->setError("Invalid parameter " . $paramname); + } // switch + } + } + } + + /** + * This is a consistency check to ensure the selector's required + * values have been set. + */ + public function verifySettings() { + if ($this->dateTime === null && $this->seconds < 0) { + $this->setError("You must provide a datetime or the number of " + . "seconds."); + } elseif ($this->seconds < 0) { + $this->setError("Date of " . $this->dateTime + . " results in negative seconds" + . " value relative to epoch (January 1, 1970, 00:00:00 GMT)."); + } + } + + /** + * The heart of the matter. This is where the selector gets to decide + * on the inclusion of a file in a particular fileset. + * + * @param PhingFile $basedir the base directory the scan is being done from + * @param string $filename is the name of the file to check + * @param PhingFile $file is a PhingFile object the selector can use + * @return boolean Whether the file should be selected or not + */ + public function isSelected(PhingFile $basedir, $filename, PhingFile $file) { + $this->validate(); + if ($file->isDirectory() && ($this->includeDirs === false)) { + return true; + } + if ($this->cmp === 0) { + return (($file->lastModified() - $this->granularity) < $this->seconds); + } elseif ($this->cmp === 1) { + return (($file->lastModified() - $this->granularity) > $this->seconds); + } else { + return (abs($file->lastModified() - $this->seconds) <= $this->granularity); + } + } + +} + + diff --git a/buildscripts/phing/classes/phing/types/selectors/DependSelector.php b/buildscripts/phing/classes/phing/types/selectors/DependSelector.php new file mode 100755 index 00000000..3b869199 --- /dev/null +++ b/buildscripts/phing/classes/phing/types/selectors/DependSelector.php @@ -0,0 +1,151 @@ +<?php + +/* + * $Id: eac9e808c89c2a8f414f86afc589eda4f218dd6e $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +require_once 'phing/types/selectors/BaseSelector.php'; + +/** + * Selector that filters files based on whether they are newer than + * a matching file in another directory tree. It can contain a mapper + * element, so isn't available as an ExtendSelector (since those + * parameters can't hold other elements). + * + * @author Hans Lellelid <hans@xmpl.org> (Phing) + * @author Bruce Atherton <bruce@callenish.com> (Ant) + * @version $Id$ + * @package phing.types.selectors + */ +class DependSelector extends BaseSelector { + + private $targetdir = null; + private $mapperElement = null; + private $map = null; + private $granularity = 0; + + public function __construct() { + // not yet supported: + //if (Os.isFamily("dos")) { + // $this->granularity = 2000; + //} + } + + public function toString() { + $buf = "{dependselector targetdir: "; + if ($this->targetdir === null) { + $buf .= "NOT YET SET"; + } else { + $buf .= $this->targetdir->getName(); + } + $buf .= " granularity: "; + $buf .= $this->granularity; + if ($this->map !== null) { + $buf .= " mapper: "; + $buf .= $this->map->toString(); + } elseif ($this->mapperElement !== null) { + $buf .= " mapper: "; + $buf .= $this->mapperElement->toString(); + } + $buf .= "}"; + return $buf; + } + + /** + * The name of the file or directory which is checked for out-of-date + * files. + * + * @param targetdir the directory to scan looking for files. + */ + public function setTargetdir(PhingFile $targetdir) { + $this->targetdir = $targetdir; + } + + /** + * Sets the number of milliseconds leeway we will give before we consider + * a file out of date. + */ + public function setGranularity($granularity) { + $this->granularity = (int) granularity; + } + + /** + * Defines the FileNameMapper to use (nested mapper element). + * @throws BuildException + */ + public function createMapper() { + if ($this->mapperElement !== null) { + throw new BuildException("Cannot define more than one mapper"); + } + $this->mapperElement = new Mapper($this->project); + return $this->mapperElement; + } + + + /** + * Checks to make sure all settings are kosher. In this case, it + * means that the dest attribute has been set and we have a mapper. + */ + public function verifySettings() { + if ($this->targetdir === null) { + $this->setError("The targetdir attribute is required."); + } + if ($this->mapperElement === null) { + $this->map = new IdentityMapper(); + } else { + $this->map = $this->mapperElement->getImplementation(); + } + if ($this->map === null) { + $this->setError("Could not set <mapper> element."); + } + } + + /** + * The heart of the matter. This is where the selector gets to decide + * on the inclusion of a file in a particular fileset. + * + * @param basedir the base directory the scan is being done from + * @param filename is the name of the file to check + * @param file is a PhingFile object the selector can use + * @return whether the file should be selected or not + */ + public function isSelected(PhingFile $basedir, $filename, PhingFile $file) { + + $this->validate(); + + // Determine file whose out-of-dateness is to be checked + $destfiles = $this->map->main($filename); + + // If filename does not match the To attribute of the mapper + // then filter it out of the files we are considering + if ($destfiles === null) { + return false; + } + // Sanity check + if (count($destfiles) !== 1 || $destfiles[0] === null) { + throw new BuildException("Invalid destination file results for " . $this->targetdir . " with filename " . $filename); + } + $destname = $destfiles[0]; + $destfile = new PhingFile($this->targetdir, $destname); + + return SelectorUtils::isOutOfDate($file, $destfile, $this->granularity); + } + +} + diff --git a/buildscripts/phing/classes/phing/types/selectors/DepthSelector.php b/buildscripts/phing/classes/phing/types/selectors/DepthSelector.php new file mode 100755 index 00000000..0ad6c8eb --- /dev/null +++ b/buildscripts/phing/classes/phing/types/selectors/DepthSelector.php @@ -0,0 +1,158 @@ +<?php +/* + * $Id: 9c244177a7f95995cd30c67c9fee47c1e977e4e2 $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +require_once 'phing/types/selectors/BaseExtendSelector.php'; + +/** + * Selector that filters files based on the how deep in the directory + * tree they are. + * + * @author Hans Lellelid <hans@xmpl.org> (Phing) + * @author Bruce Atherton <bruce@callenish.com> (Ant) + * @version $Id$ + * @package phing.types.selectors + */ +class DepthSelector extends BaseExtendSelector { + + public $min = -1; + public $max = -1; + const MIN_KEY = "min"; + const MAX_KEY = "max"; + + public function toString() { + $buf = "{depthselector min: "; + $buf .= $this->min; + $buf .= " max: "; + $buf .= $this->max; + $buf .= "}"; + return $buf; + } + + /** + * The minimum depth below the basedir before a file is selected. + * + * @param min minimum directory levels below basedir to go + */ + public function setMin($min) { + $this->min = (int) $min; + } + + /** + * The minimum depth below the basedir before a file is selected. + * + * @param min maximum directory levels below basedir to go + */ + public function setMax($max) { + $this->max = (int) $max; + } + + /** + * When using this as a custom selector, this method will be called. + * It translates each parameter into the appropriate setXXX() call. + * + * @param parameters the complete set of parameters for this selector + */ + public function setParameters($parameters) { + parent::setParameters($parameters); + if ($parameters !== null) { + for ($i = 0, $size=count($parameters); $i < $size; $i++) { + $paramname = $parameters[$i]->getName(); + switch(strtolower($paramname)) { + case self::MIN_KEY: + $this->setMin($parameters[$i]->getValue()); + break; + case self::MAX_KEY: + $this->setMax($parameters[$i]->getValue()); + break; + + default: + $this->setError("Invalud parameter " . $paramname); + } // switch + } + } + } + + /** + * Checks to make sure all settings are kosher. In this case, it + * means that the max depth is not lower than the min depth. + */ + public function verifySettings() { + if ($this->min < 0 && $this->max < 0) { + $this->setError("You must set at least one of the min or the " . + "max levels."); + } + if ($this->max < $this->min && $this->max > -1) { + $this->setError("The maximum depth is lower than the minimum."); + } + } + + /** + * The heart of the matter. This is where the selector gets to decide + * on the inclusion of a file in a particular fileset. Most of the work + * for this selector is offloaded into SelectorUtils, a static class + * that provides the same services for both FilenameSelector and + * DirectoryScanner. + * + * @param basedir the base directory the scan is being done from + * @param filename is the name of the file to check + * @param file is a PhingFile object the selector can use + * @return whether the file should be selected or not + */ + public function isSelected(PhingFile $basedir, $filename, PhingFile $file) { + + $this->validate(); + + $depth = -1; + // If you felt daring, you could cache the basedir absolute path + $abs_base = $basedir->getAbsolutePath(); + $abs_file = $file->getAbsolutePath(); + + $tok_base = explode(DIRECTORY_SEPARATOR, $abs_base); + $tok_file = explode(DIRECTORY_SEPARATOR, $abs_file); + + for($i=0,$size=count($tok_file); $i < $size; $i++) { + $filetoken = $tok_file[$i]; + if (isset($tok_base[$i])) { + $basetoken = $tok_base[$i]; + // Sanity check. Ditch it if you want faster performance + if ($basetoken !== $filetoken) { + throw new BuildException("File " . $filename . + " does not appear within " . $abs_base . "directory"); + } + } else { // no more basepath tokens + $depth++; + if ($this->max > -1 && $depth > $this->max) { + return false; + } + } + } + if (isset($tok_base[$i + 1])) { + throw new BuildException("File " . $filename . + " is outside of " . $abs_base . "directory tree"); + } + if ($this->min > -1 && $depth < $this->min) { + return false; + } + return true; + } + +} + diff --git a/buildscripts/phing/classes/phing/types/selectors/ExtendFileSelector.php b/buildscripts/phing/classes/phing/types/selectors/ExtendFileSelector.php new file mode 100644 index 00000000..8394387c --- /dev/null +++ b/buildscripts/phing/classes/phing/types/selectors/ExtendFileSelector.php @@ -0,0 +1,43 @@ +<?php + +/* + * $Id: dc3c5cb2a3043b7a3f7600591ce825b6563ec0ce $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +require_once 'phing/types/Parameterizable.php'; +require_once 'phing/types/selectors/FileSelector.php'; + +/** + * This is the interface to be used by all custom selectors, those that are + * called through the <custom> tag. It is the amalgamation of two + * interfaces, the FileSelector and the Paramterizable interface. Note that + * you will almost certainly want the default behaviour for handling + * Parameters, so you probably want to use the BaseExtendSelector class + * as the base class for your custom selector rather than implementing + * this interface from scratch. + * + * @author Hans Lellelid <hans@xmpl.org> (Phing) + * @author Bruce Atherton <bruce@callenish.com> (Ant) + * @package phing.types.selectors + */ +interface ExtendFileSelector extends Parameterizable, FileSelector { + // No further methods necessary. This is just an amalgamation of two other + // interfaces. +} + diff --git a/buildscripts/phing/classes/phing/types/selectors/ExtendSelector.php b/buildscripts/phing/classes/phing/types/selectors/ExtendSelector.php new file mode 100644 index 00000000..1204ef12 --- /dev/null +++ b/buildscripts/phing/classes/phing/types/selectors/ExtendSelector.php @@ -0,0 +1,124 @@ +<?php + +/* + * $Id: 1683a0a93b4bb5486f3cffbe40e8260f886c6258 $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +include_once 'phing/util/StringHelper.php'; + +/** + * Selector that selects files by forwarding the request on to other classes. + * + * TODO - Consider adding Path (phing.types.Path) support to this class + * and to the Mappers class. See Ant versions for implimentation details. + * + * @author Hans Lellelid <hans@xmpl.org> (Phing) + * @author Bruce Atherton <bruce@callenish.com> (Ant) + * @package phing.types.selectors + */ +class ExtendSelector extends BaseSelector { + + private $classname; + private $dynselector; + private $parameters = array(); + + /** + * Sets the classname of the custom selector. + * + * @param classname is the class which implements this selector + */ + public function setClassname($classname) { + $this->classname = $classname; + } + + /** + * Instantiates the identified custom selector class. + */ + public function selectorCreate() { + if ($this->classname !== null && $this->classname !== "") { + try { + // assume it's fully qualified, import it + $cls = Phing::import($this->classname); + + // make sure class exists + if (class_exists($cls)) { + $this->dynselector = new $cls(); + } else { + $this->setError("Selector " . $this->classname . " not initialized, no such class"); + } + } catch (Exception $e) { + $this->setError("Selector " . $this->classname . " not initialized, could not create class: " . $e->getMessage()); + } + } else { + $this->setError("There is no classname specified"); + } + } + + /** + * Create new parameters to pass to custom selector. + * + * @param p The new Parameter object + */ + public function addParam(Parameter $p) { + $this->parameters[] = $p; + } + + /** + * These are errors specific to ExtendSelector only. If there are + * errors in the custom selector, it should throw a BuildException + * when isSelected() is called. + */ + public function verifySettings() { + // Creation is done here rather than in isSelected() because some + // containers may do a validation pass before running isSelected(), + // but we need to check for the existence of the created class. + if ($this->dynselector === null) { + $this->selectorCreate(); + } + + if (empty($this->classname)) { + $this->setError("The classname attribute is required"); + } elseif ($this->dynselector === null) { + $this->setError("Internal Error: The custom selector was not created"); + } elseif ( !($this->dynselector instanceof ExtendFileSelector) && (count($this->parameters) > 0)) { + $this->setError("Cannot set parameters on custom selector that does not " + . "implement ExtendFileSelector."); + } + } + + + /** + * Allows the custom selector to choose whether to select a file. This + * is also where the Parameters are passed to the custom selector. + * + * @throws BuildException + */ + public function isSelected(PhingFile $basedir, $filename, PhingFile $file) { + + $this->validate(); + + if (count($this->parameters) > 0 && $this->dynselector instanceof ExtendFileSelector) { + // We know that dynselector must be non-null if no error message + $this->dynselector->setParameters($this->parameters); + } + return $this->dynselector->isSelected($basedir, $filename, $file); + } + +} + diff --git a/buildscripts/phing/classes/phing/types/selectors/FileSelector.php b/buildscripts/phing/classes/phing/types/selectors/FileSelector.php new file mode 100644 index 00000000..3c014d61 --- /dev/null +++ b/buildscripts/phing/classes/phing/types/selectors/FileSelector.php @@ -0,0 +1,47 @@ +<?php + +/* + * $Id: 26b8712469a798faf79d1c877aad89d64880f061 $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +/** + * This is the interface to be used by all selectors. + * + * @author Hans Lellelid, hans@xmpl.org (Phing) + * @author Bruce Atherton, bruce@callenish.com (Ant) + * @package phing.types.selectors + */ +interface FileSelector { + + /** + * Method that each selector will implement to create their + * selection behaviour. If there is a problem with the setup + * of a selector, it can throw a BuildException to indicate + * the problem. + * + * @param basedir A PhingFile object for the base directory + * @param filename The name of the file to check + * @param file A PhingFile object for this filename + * @return whether the file should be selected or not + * @throws BuildException if the selector was not configured correctly + */ + public function isSelected(PhingFile $basedir, $filename, PhingFile $file); + +} + diff --git a/buildscripts/phing/classes/phing/types/selectors/FilenameSelector.php b/buildscripts/phing/classes/phing/types/selectors/FilenameSelector.php new file mode 100644 index 00000000..04abbe2e --- /dev/null +++ b/buildscripts/phing/classes/phing/types/selectors/FilenameSelector.php @@ -0,0 +1,157 @@ +<?php + +/* + * $Id: d0a6af11eeda50b911bad3717528a9ea72291185 $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + + +include_once 'phing/types/selectors/BaseExtendSelector.php'; + +/** + * Selector that filters files based on the filename. + * + * @author Hans Lellelid, hans@xmpl.org (Phing) + * @author Bruce Atherton, bruce@callenish.com (Ant) + * @package phing.types.selectors + */ +class FilenameSelector extends BaseExtendSelector { + + private $pattern = null; + private $casesensitive = true; + private $negated = false; + const NAME_KEY = "name"; + const CASE_KEY = "casesensitive"; + const NEGATE_KEY = "negate"; + + public function toString() { + $buf = "{filenameselector name: "; + $buf .= $this->pattern; + $buf .= " negate: "; + if ($this->negated) { + $buf .= "true"; + } else { + $buf .= "false"; + } + $buf .= " casesensitive: "; + if ($this->casesensitive) { + $buf .= "true"; + } else { + $buf .= "false"; + } + $buf .= "}"; + return $buf; + } + + /** + * The name of the file, or the pattern for the name, that + * should be used for selection. + * + * @param pattern the file pattern that any filename must match + * against in order to be selected. + */ + public function setName($pattern) { + $pattern = str_replace('\\', DIRECTORY_SEPARATOR, $pattern); + $pattern = str_replace('/', DIRECTORY_SEPARATOR, $pattern); + + if (StringHelper::endsWith(DIRECTORY_SEPARATOR, $pattern)) { + $pattern .= "**"; + } + $this->pattern = $pattern; + } + + /** + * Whether to ignore case when checking filenames. + * + * @param casesensitive whether to pay attention to case sensitivity + */ + public function setCasesensitive($casesensitive) { + $this->casesensitive = $casesensitive; + } + + /** + * You can optionally reverse the selection of this selector, + * thereby emulating an <exclude> tag, by setting the attribute + * negate to true. This is identical to surrounding the selector + * with <not></not>. + * + * @param negated whether to negate this selection + */ + public function setNegate($negated) { + $this->negated = $negated; + } + + /** + * When using this as a custom selector, this method will be called. + * It translates each parameter into the appropriate setXXX() call. + * + * @param array $parameters the complete set of parameters for this selector + */ + public function setParameters($parameters) { + parent::setParameters($parameters); + if ($parameters !== null) { + for ($i=0, $len=count($parameters); $i < $len; $i++) { + $paramname = $parameters[$i]->getName(); + switch(strtolower($paramname)) { + case self::NAME_KEY: + $this->setName($parameters[$i]->getValue()); + break; + case self::CASE_KEY: + $this->setCasesensitive($parameters[$i]->getValue()); + break; + case self::NEGATE_KEY: + $this->setNegate($parameters[$i]->getValue()); + break; + default: + $this->setError("Invalid parameter " . $paramname); + } + } // for each param + } // if params + } + + /** + * Checks to make sure all settings are kosher. In this case, it + * means that the name attribute has been set. + * + */ + public function verifySettings() { + if ($this->pattern === null) { + $this->setError("The name attribute is required"); + } + } + + /** + * The heart of the matter. This is where the selector gets to decide + * on the inclusion of a file in a particular fileset. Most of the work + * for this selector is offloaded into SelectorUtils, a static class + * that provides the same services for both FilenameSelector and + * DirectoryScanner. + * + * @param basedir the base directory the scan is being done from + * @param filename is the name of the file to check + * @param file is a PhingFile object the selector can use + * @return whether the file should be selected or not + */ + public function isSelected(PhingFile $basedir, $filename, PhingFile $file) { + $this->validate(); + return (SelectorUtils::matchPath($this->pattern, $filename, $this->casesensitive) + === !($this->negated)); + } + +} + diff --git a/buildscripts/phing/classes/phing/types/selectors/MajoritySelector.php b/buildscripts/phing/classes/phing/types/selectors/MajoritySelector.php new file mode 100644 index 00000000..5ad2629e --- /dev/null +++ b/buildscripts/phing/classes/phing/types/selectors/MajoritySelector.php @@ -0,0 +1,92 @@ +<?php + +/* + * $Id: 9071d88eb880abe5a299f7c5db707d4439ccaa6c $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + + +/** + * This selector is here just to shake up your thinking a bit. Don't get + * too caught up in boolean, there are other ways you can evaluate a + * collection of selectors. This one takes a vote of the selectors it + * contains, and majority wins. You could also have an "all-but-one" + * selector, a "weighted-average" selector, and so on. These are left + * as exercises for the reader (as are the usecases where this would + * be necessary). + * + * @author Hans Lellelid <hans@xmpl.org> (Phing) + * @author Bruce Atherton <bruce@callenish.com> (Ant) + * @package phing.types.selectors + */ +class MajoritySelector extends BaseSelectorContainer { + + private $allowtie = true; + + public function toString() { + $buf = ""; + if ($this->hasSelectors()) { + $buf .= "{majorityselect: "; + $buf .= parent::toString(); + $buf .= "}"; + } + return $buf; + } + + public function setAllowtie($tiebreaker) { + $this->allowtie = $tiebreaker; + } + + /** + * Returns true (the file is selected) if most of the other selectors + * agree. In case of a tie, go by the allowtie setting. That defaults + * to true, meaning in case of a tie, the file is selected. + * + * @param basedir the base directory the scan is being done from + * @param filename is the name of the file to check + * @param file is a PhingFile object for the filename that the selector + * can use + * @return whether the file should be selected or not + */ + public function isSelected(PhingFile $basedir, $filename, PhingFile $file) { + + $this->validate(); + + $yesvotes = 0; + $novotes = 0; + + $selectors = $this->selectorElements(); + for($i=0,$size=count($selectors); $i < $size; $i++) { + $result = $selectors[$i]->isSelected($basedir,$filename,$file); + if ($result) { + $yesvotes = $yesvotes + 1; + } else { + $novotes = $novotes + 1; + } + } + if ($yesvotes > $novotes) { + return true; + } + else if ($novotes > $yesvotes) { + return false; + } + // At this point, we know we have a tie. + return $this->allowtie; + } +} + diff --git a/buildscripts/phing/classes/phing/types/selectors/NoneSelector.php b/buildscripts/phing/classes/phing/types/selectors/NoneSelector.php new file mode 100644 index 00000000..f8941208 --- /dev/null +++ b/buildscripts/phing/classes/phing/types/selectors/NoneSelector.php @@ -0,0 +1,71 @@ +<?php +/* + * $Id: a085187a008c4d8e8ba25fd6f1315b3dee92ec27 $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +require_once 'phing/types/selectors/BaseSelectorContainer.php'; + +/** + * This selector has a collection of other selectors. All of those selectors + * must refuse to select a file before the file is considered selected by + * this selector. + * + * @author Hans Lellelid <hans@xmpl.org> + * @author Bruce Atherton <bruce@callenish.com> (Ant) + * @package phing.types.selectors + */ +class NoneSelector extends BaseSelectorContainer { + + public function toString() { + $buf = ""; + if ($this->hasSelectors()) { + $buf .= "{noneselect: "; + $buf .= parent::toString(); + $buf .= "}"; + } + return $buf; + } + + /** + * Returns true (the file is selected) only if all other selectors + * agree that the file should not be selected. + * + * @param basedir the base directory the scan is being done from + * @param filename is the name of the file to check + * @param file is a java.io.File object for the filename that the selector + * can use + * @return whether the file should be selected or not + */ + public function isSelected(PhingFile $basedir, $filename, PhingFile $file) { + + $this->validate(); + + $selectors = $this->selectorElements(); + + for($i=0,$size=count($selectors); $i < $size; $i++) { + $result = $selectors[$i]->isSelected($basedir, $filename, $file); + if ($result) { + return false; + } + } + return true; + } + +} + diff --git a/buildscripts/phing/classes/phing/types/selectors/NotSelector.php b/buildscripts/phing/classes/phing/types/selectors/NotSelector.php new file mode 100644 index 00000000..08e70a5a --- /dev/null +++ b/buildscripts/phing/classes/phing/types/selectors/NotSelector.php @@ -0,0 +1,59 @@ +<?php + +/* + * $Id: 8dcce9d2d304b7a8d4be0ef5b5111b582846840d $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +require_once 'phing/types/selectors/NoneSelector.php'; + +/** + * This selector has one other selectors whose meaning it inverts. It + * actually relies on NoneSelector for its implementation of the + * isSelected() method, but it adds a check to ensure there is only one + * other selector contained within. + * + * @author Hans Lellelid <hans@xmpl.org> (Phing) + * @author Bruce Atherton <bruce@callenish.com> (Ant) + * @package phing.types.selectors + */ +class NotSelector extends NoneSelector { + + public function toString() { + $buf = ""; + if ($this->hasSelectors()) { + $buf .= "{notselect: "; + $buf .= parent::toString(); + $buf .= "}"; + } + return $buf; + } + + /** + * Makes sure that there is only one entry, sets an error message if + * not. + */ + public function verifySettings() { + if ($this->selectorCount() != 1) { + $this->setError("One and only one selector is allowed within the " . + "<not> tag"); + } + } + +} + diff --git a/buildscripts/phing/classes/phing/types/selectors/OrSelector.php b/buildscripts/phing/classes/phing/types/selectors/OrSelector.php new file mode 100644 index 00000000..56e6df1e --- /dev/null +++ b/buildscripts/phing/classes/phing/types/selectors/OrSelector.php @@ -0,0 +1,72 @@ +<?php +/* + * $Id: bfed3cc534a3e1ab8789f0ed4a6e64419979e21a $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +require_once 'phing/types/selectors/BaseSelectorContainer.php'; + +/** + * This selector has a collection of other selectors, any of which have to + * select a file in order for this selector to select it. + * + * @author Hans Lellelid <hans@xmpl.org> (Phing) + * @author Bruce Atherton <bruce@callenish.com> (Ant) + * @package phing.types.selectors + */ +class OrSelector extends BaseSelectorContainer { + + public function toString() { + $buf = ""; + if ($this->hasSelectors()) { + $buf .= "{orselect: "; + $buf .= parent::toString(); + $buf .= "}"; + } + return $buf; + } + + /** + * Returns true (the file is selected) if any of the other selectors + * agree that the file should be selected. + * + * @param basedir the base directory the scan is being done from + * @param filename the name of the file to check + * @param file a PhingFile object for the filename that the selector + * can use + * @return boolean Whether the file should be selected or not + */ + public function isSelected(PhingFile $basedir, $filename, PhingFile $file) { + + $this->validate(); + + $selectors = $this->selectorElements(); + + // First, check that all elements are correctly configured + + for($i=0,$size=count($selectors); $i < $size; $i++) { + $result = $selectors[$i]->isSelected($basedir, $filename, $file); + if ($result) { + return true; + } + } + return false; + } + +} + diff --git a/buildscripts/phing/classes/phing/types/selectors/PresentSelector.php b/buildscripts/phing/classes/phing/types/selectors/PresentSelector.php new file mode 100644 index 00000000..462d3927 --- /dev/null +++ b/buildscripts/phing/classes/phing/types/selectors/PresentSelector.php @@ -0,0 +1,154 @@ +<?php + +/* + * $Id: db4c8bc8217483d4150b2d9e62d2ef5129038b4e $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +/** + * Selector that filters files based on whether they appear in another + * directory tree. It can contain a mapper element, so isn't available + * as an ExtendSelector (since those parameters can't hold other + * elements). + * + * @author Hans Lellelid <hans@xmpl.org> (Phing) + * @author Bruce Atherton <bruce@callenish.com> (Ant) + * @package phing.types.selectors + */ +class PresentSelector extends BaseSelector { + + private $targetdir = null; + private $mapperElement = null; + private $map = null; + private $destmustexist = true; + private static $filePresence = array("srconly", "both"); + + public function toString() { + $buf = "{presentselector targetdir: "; + if ($this->targetdir === null) { + $buf .= "NOT YET SET"; + } else { + $buf .= $this->targetdir->getName(); + } + $buf .= " present: "; + if ($this->destmustexist) { + $buf .= "both"; + } else { + $buf .= "srconly"; + } + if ($this->map !== null) { + $buf .= $this->map->toString(); + } elseif ($this->mapperElement !== null) { + $buf .= $this->mapperElement->toString(); + } + $buf .= "}"; + return $buf; + } + + /** + * The name of the file or directory which is checked for matching + * files. + * + * @param targetdir the directory to scan looking for matching files. + */ + public function setTargetdir(PhingFile $targetdir) { + $this->targetdir = $targetdir; + } + + /** + * Defines the FileNameMapper to use (nested mapper element). + * @throws BuildException + */ + public function createMapper() { + if ($this->mapperElement !== null) { + throw new BuildException("Cannot define more than one mapper"); + } + $this->mapperElement = new Mapper($this->getProject()); + return $this->mapperElement; + } + + + /** + * This sets whether to select a file if its dest file is present. + * It could be a <code>negate</code> boolean, but by doing things + * this way, we get some documentation on how the system works. + * A user looking at the documentation should clearly understand + * that the ONLY files whose presence is being tested are those + * that already exist in the source directory, hence the lack of + * a <code>destonly</code> option. + * + * @param string $fp An attribute set to either <code>srconly</code> or + * <code>both</code>. + */ + public function setPresent($fp) { + $idx = array_search($fp, self::$filePresence, true); + if ( $idx === 0 ) { + $this->destmustexist = false; + } + } + + /** + * Checks to make sure all settings are kosher. In this case, it + * means that the targetdir attribute has been set and we have a mapper. + */ + public function verifySettings() { + if ($this->targetdir === null) { + $this->setError("The targetdir attribute is required."); + } + if ($this->mapperElement === null) { + $this->map = new IdentityMapper(); + } else { + $this->map = $this->mapperElement->getImplementation(); + } + if ($this->map === null) { + $this->setError("Could not set <mapper> element."); + } + } + + /** + * The heart of the matter. This is where the selector gets to decide + * on the inclusion of a file in a particular fileset. + * + * @param basedir the base directory the scan is being done from + * @param filename is the name of the file to check + * @param file is a PhingFile object the selector can use + * @return whether the file should be selected or not + */ + public function isSelected(PhingFile $basedir, $filename, PhingFile $file) { + + $this->validate(); + + // Determine file whose existence is to be checked + $destfiles = $this->map->main($filename); + // If filename does not match the To attribute of the mapper + // then filter it out of the files we are considering + if ($destfiles === null) { + return false; + } + // Sanity check + if (count($destfiles) !== 1 || $destfiles[0] === null) { + throw new BuildException("Invalid destination file results for " + . $this->targetdir . " with filename " . $filename); + } + $destname = $destfiles[0]; + $destfile = new PhingFile($this->targetdir, $destname); + return $destfile->exists() === $this->destmustexist; + } + +} + diff --git a/buildscripts/phing/classes/phing/types/selectors/SelectSelector.php b/buildscripts/phing/classes/phing/types/selectors/SelectSelector.php new file mode 100755 index 00000000..0db73e5d --- /dev/null +++ b/buildscripts/phing/classes/phing/types/selectors/SelectSelector.php @@ -0,0 +1,124 @@ +<?php + +/* + * $Id: aa3a5cceea362713959333bda113e0ca5428a530 $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +require_once 'phing/types/selectors/AndSelector.php'; + +/** + * This selector just holds one other selector and forwards all + * requests to it. It exists so that there is a single selector + * type that can exist outside of any targets, as an element of + * project. It overrides all of the reference stuff so that it + * works as expected. Note that this is the only selector you + * can reference. + * + * @author Hans Lellelid <hans@xmpl.org> (Phing) + * @author Bruce Atherton <bruce@callenish.com> (Ant) + * @version $Id$ + * @package phing.types.selectors + */ +class SelectSelector extends AndSelector { + + public function toString() { + $buf = ""; + if ($this->hasSelectors()) { + $buf .= "{select: "; + $buf .= parent::toString(); + $buf .= "}"; + } + return $buf; + } + + /** + * Performs the check for circular references and returns the + * referenced Selector. + */ + private function getRef() { + $o = $this->getCheckedRef(get_class($this), "SelectSelector"); + return $o; + } + + /** + * Indicates whether there are any selectors here. + */ + public function hasSelectors() { + if ($this->isReference()) { + return $this->getRef()->hasSelectors(); + } + return parent::hasSelectors(); + } + + /** + * Gives the count of the number of selectors in this container + */ + public function selectorCount() { + if ($this->isReference()) { + return $this->getRef()->selectorCount(); + } + return parent::selectorCount(); + } + + /** + * Returns the set of selectors as an array. + */ + public function getSelectors(Project $p) { + if ($this->isReference()) { + return $this->getRef()->getSelectors($p); + } + return parent::getSelectors($p); + } + + /** + * Returns an enumerator for accessing the set of selectors. + */ + public function selectorElements() { + if ($this->isReference()) { + return $this->getRef()->selectorElements(); + } + return parent::selectorElements(); + } + + /** + * Add a new selector into this container. + * + * @param selector the new selector to add + * @return the selector that was added + */ + public function appendSelector(FileSelector $selector) { + if ($this->isReference()) { + throw $this->noChildrenAllowed(); + } + parent::appendSelector($selector); + } + + /** + * Makes sure that there is only one entry, sets an error message if + * not. + */ + public function verifySettings() { + if ($this->selectorCount() != 1) { + $this->setError("One and only one selector is allowed within the " + . "<selector> tag"); + } + } + +} + diff --git a/buildscripts/phing/classes/phing/types/selectors/SelectorContainer.php b/buildscripts/phing/classes/phing/types/selectors/SelectorContainer.php new file mode 100644 index 00000000..0ee42237 --- /dev/null +++ b/buildscripts/phing/classes/phing/types/selectors/SelectorContainer.php @@ -0,0 +1,141 @@ +<?php + +/* + * $Id: 6fedde4695e4838f435f336b7936190b16429706 $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + + +/** + * This is the interface for selectors that can contain other selectors. + * + * @author <a href="mailto:bruce@callenish.com">Bruce Atherton</a> + * @package phing.types.selectors + */ +interface SelectorContainer { + + /** + * Indicates whether there are any selectors here. + * + * @return whether any selectors are in this container + */ + public function hasSelectors(); + + /** + * Gives the count of the number of selectors in this container + * + * @return the number of selectors in this container + */ + public function selectorCount(); + + /** + * Returns a *copy* of the set of selectors as an array. + * + * @return an array of selectors in this container + */ + public function getSelectors(Project $p); + + /** + * Returns an array for accessing the set of selectors. + * + * @return an enumerator that goes through each of the selectors + */ + public function selectorElements(); + + /** + * Add a new selector into this container. + * + * @param selector the new selector to add + * @return the selector that was added + */ + public function appendSelector(FileSelector $selector); + + /* Methods below all add specific selectors */ + + /** + * add a "Select" selector entry on the selector list + */ + public function createSelector(); + + /** + * add an "And" selector entry on the selector list + */ + public function createAnd(); + + /** + * add an "Or" selector entry on the selector list + */ + public function createOr(); + + /** + * add a "Not" selector entry on the selector list + */ + public function createNot(); + + /** + * add a "None" selector entry on the selector list + */ + public function createNone(); + + /** + * add a majority selector entry on the selector list + */ + public function createMajority(); + + /** + * add a selector date entry on the selector list + */ + public function createDate(); + + /** + * add a selector size entry on the selector list + */ + public function createSize(); + + /** + * add a selector filename entry on the selector list + */ + public function createFilename(); + + /** + * add an extended selector entry on the selector list + */ + public function createCustom(); + + /** + * add a contains selector entry on the selector list + */ + public function createContains(); + + /** + * add a present selector entry on the selector list + */ + public function createPresent(); + + /** + * add a depth selector entry on the selector list + */ + public function createDepth(); + + /** + * add a depends selector entry on the selector list + */ + public function createDepend(); + +} + diff --git a/buildscripts/phing/classes/phing/types/selectors/SelectorScanner.php b/buildscripts/phing/classes/phing/types/selectors/SelectorScanner.php new file mode 100644 index 00000000..91fc3f4c --- /dev/null +++ b/buildscripts/phing/classes/phing/types/selectors/SelectorScanner.php @@ -0,0 +1,55 @@ +<?php + +/* + * $Id: 3c28c4c2e4c41cf4507870e472ed9f278e2d9c9f $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + + +/** + * An interface used to describe the actions required by any type of + * directory scanner that supports Selecters. + * + * @author Hans Lellelid <hans@xmpl.org> (Phing) + * @author Bruce Atherton <bruce@callenish.com> (Ant) + * @package phing.types.selectors + */ +interface SelectorScanner { + + /** + * Sets the selectors the scanner should use. + * + * @param selectors the list of selectors + */ + public function setSelectors($selectors); + + /** + * Directories which were selected out of a scan. + * + * @param selectors list selector objects + */ + public function getDeselectedDirectories(); + + /** + * Files which were selected out of a scan. + * + * @param selectors list selector objects + */ + public function getDeselectedFiles(); + +} diff --git a/buildscripts/phing/classes/phing/types/selectors/SelectorUtils.php b/buildscripts/phing/classes/phing/types/selectors/SelectorUtils.php new file mode 100644 index 00000000..2d7e5068 --- /dev/null +++ b/buildscripts/phing/classes/phing/types/selectors/SelectorUtils.php @@ -0,0 +1,200 @@ +<?php + +/* + * $Id: 4a682bbe8751f6e09a725af7cfdf2bd17ab00645 $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +include_once 'phing/util/StringHelper.php'; + +/** + * <p>This is a utility class used by selectors and DirectoryScanner. The + * functionality more properly belongs just to selectors, but unfortunately + * DirectoryScanner exposed these as protected methods. Thus we have to + * support any subclasses of DirectoryScanner that may access these methods. + * </p> + * <p>This is a Singleton.</p> + * + * @author Hans Lellelid, hans@xmpl.org (Phing) + * @author Arnout J. Kuiper, ajkuiper@wxs.nl (Ant) + * @author Magesh Umasankar + * @author Bruce Atherton, bruce@callenish.com (Ant) + * @package phing.types.selectors + */ +class SelectorUtils { + + private static $instance; + + /** + * Retrieves the instance of the Singleton. + */ + public static function getInstance() { + if (!isset(self::$instance)) { + self::$instance = new SelectorUtils(); + } + return self::$instance; + } + + /** + * Tests whether or not a given path matches the start of a given + * pattern up to the first "**". + * <p> + * This is not a general purpose test and should only be used if you + * can live with false positives. For example, <code>pattern=**\a</code> + * and <code>str=b</code> will yield <code>true</code>. + * + * @param pattern The pattern to match against. Must not be + * <code>null</code>. + * @param str The path to match, as a String. Must not be + * <code>null</code>. + * @param isCaseSensitive Whether or not matching should be performed + * case sensitively. + * + * @return whether or not a given path matches the start of a given + * pattern up to the first "**". + */ + public static function matchPatternStart($pattern, $str, $isCaseSensitive = true) { + + // When str starts with a DIRECTORY_SEPARATOR, pattern has to start with a + // DIRECTORY_SEPARATOR. + // When pattern starts with a DIRECTORY_SEPARATOR, str has to start with a + // DIRECTORY_SEPARATOR. + if (StringHelper::startsWith(DIRECTORY_SEPARATOR, $str) !== + StringHelper::startsWith(DIRECTORY_SEPARATOR, $pattern)) { + return false; + } + + $patDirs = explode(DIRECTORY_SEPARATOR, $pattern); + $strDirs = explode(DIRECTORY_SEPARATOR, $str); + + $patIdxStart = 0; + $patIdxEnd = count($patDirs)-1; + $strIdxStart = 0; + $strIdxEnd = count($strDirs)-1; + + // up to first '**' + while ($patIdxStart <= $patIdxEnd && $strIdxStart <= $strIdxEnd) { + $patDir = $patDirs[$patIdxStart]; + if ($patDir == "**") { + break; + } + if (!self::match($patDir, $strDirs[$strIdxStart], $isCaseSensitive)) { + return false; + } + $patIdxStart++; + $strIdxStart++; + } + + if ($strIdxStart > $strIdxEnd) { + // String is exhausted + return true; + } elseif ($patIdxStart > $patIdxEnd) { + // String not exhausted, but pattern is. Failure. + return false; + } else { + // pattern now holds ** while string is not exhausted + // this will generate false positives but we can live with that. + return true; + } + } + + /** + * Tests whether or not a given path matches a given pattern. + * + * @param pattern The pattern to match against. Must not be + * <code>null</code>. + * @param str The path to match, as a String. Must not be + * <code>null</code>. + * @param isCaseSensitive Whether or not matching should be performed + * case sensitively. + * + * @return <code>true</code> if the pattern matches against the string, + * or <code>false</code> otherwise. + */ + public static function matchPath($pattern, $str, $isCaseSensitive = true) { + + $rePattern = preg_quote($pattern, '/'); + $dirSep = preg_quote(DIRECTORY_SEPARATOR, '/'); + $trailingDirSep = '(('.$dirSep.')?|('.$dirSep.').+)'; + $patternReplacements = array( + $dirSep.'\*\*'.$dirSep => $dirSep.'.*'.$trailingDirSep, + $dirSep.'\*\*' => $trailingDirSep, + '\*\*'.$dirSep => '.*'.$trailingDirSep, + '\*\*' => '.*', + '\*' => '[^'.$dirSep.']*', + '\?' => '[^'.$dirSep.']' + ); + $rePattern = str_replace(array_keys($patternReplacements), array_values($patternReplacements), $rePattern); + $rePattern = '/^'.$rePattern.'$/'.($isCaseSensitive ? '' : 'i'); + return (bool) preg_match($rePattern, $str); + } + + /** + * Tests whether or not a string matches against a pattern. + * The pattern may contain two special characters:<br> + * '*' means zero or more characters<br> + * '?' means one and only one character + * + * @param pattern The pattern to match against. + * Must not be <code>null</code>. + * @param str The string which must be matched against the pattern. + * Must not be <code>null</code>. + * @param isCaseSensitive Whether or not matching should be performed + * case sensitively. + * + * + * @return <code>true</code> if the string matches against the pattern, + * or <code>false</code> otherwise. + */ + public static function match($pattern, $str, $isCaseSensitive = true) { + + $rePattern = preg_quote($pattern, '/'); + $rePattern = str_replace(array("\*", "\?"), array('.*', '.'), $rePattern); + $rePattern = '/^'.$rePattern.'$/'.($isCaseSensitive ? '' : 'i'); + return (bool) preg_match($rePattern, $str); + } + + /** + * Returns dependency information on these two files. If src has been + * modified later than target, it returns true. If target doesn't exist, + * it likewise returns true. Otherwise, target is newer than src and + * is not out of date, thus the method returns false. It also returns + * false if the src file doesn't even exist, since how could the + * target then be out of date. + * + * @param PhingFile $src the original file + * @param PhingFile $target the file being compared against + * @param int $granularity the amount in seconds of slack we will give in + * determining out of dateness + * @return whether the target is out of date + */ + public static function isOutOfDate(PhingFile $src, PhingFile $target, $granularity) { + if (!$src->exists()) { + return false; + } + if (!$target->exists()) { + return true; + } + if (($src->lastModified() - $granularity) > $target->lastModified()) { + return true; + } + return false; + } + +} + diff --git a/buildscripts/phing/classes/phing/types/selectors/SizeSelector.php b/buildscripts/phing/classes/phing/types/selectors/SizeSelector.php new file mode 100644 index 00000000..3aaf8a92 --- /dev/null +++ b/buildscripts/phing/classes/phing/types/selectors/SizeSelector.php @@ -0,0 +1,228 @@ +<?php + +/* + * $Id: 4969c98a4e03305a23770e2afd5da641999f6174 $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + + +/** + * Selector that filters files based on their size. + * + * @author Hans Lellelid <hans@xmpl.org> (Phing) + * @author Bruce Atherton <bruce@callenish.com> (Ant) + * @package phing.types.selectors + */ +class SizeSelector extends BaseExtendSelector { + + private $size = -1; + private $multiplier = 1; + private $sizelimit = -1; + private $cmp = 2; + const SIZE_KEY = "value"; + const UNITS_KEY = "units"; + const WHEN_KEY = "when"; + + private static $sizeComparisons = array("less", "more", "equal"); + private static $byteUnits = array("K", "k", "kilo", "KILO", + "Ki", "KI", "ki", "kibi", "KIBI", + "M", "m", "mega", "MEGA", + "Mi", "MI", "mi", "mebi", "MEBI", + "G", "g", "giga", "GIGA", + "Gi", "GI", "gi", "gibi", "GIBI", + "T", "t", "tera", "TERA", + /* You wish! */ "Ti", "TI", "ti", "tebi", "TEBI" + ); + + public function toString() { + $buf = "{sizeselector value: "; + $buf .= $this->sizelimit; + $buf .= "compare: "; + if ($this->cmp === 0) { + $buf .= "less"; + } elseif ($this->cmp === 1) { + $buf .= "more"; + } else { + $buf .= "equal"; + } + $buf .= "}"; + return $buf; + } + + /** + * A size selector needs to know what size to base its selecting on. + * This will be further modified by the multiplier to get an + * actual size limit. + * + * @param size the size to select against expressed in units + */ + public function setValue($size) { + $this->size = $size; + if (($this->multiplier !== 0) && ($this->size > -1)) { + $this->sizelimit = $size * $this->multiplier; + } + } + + /** + * Sets the units to use for the comparison. This is a little + * complicated because common usage has created standards that + * play havoc with capitalization rules. Thus, some people will + * use "K" for indicating 1000's, when the SI standard calls for + * "k". Others have tried to introduce "K" as a multiple of 1024, + * but that falls down when you reach "M", since "m" is already + * defined as 0.001. + * <p> + * To get around this complexity, a number of standards bodies + * have proposed the 2^10 standard, and at least one has adopted + * it. But we are still left with a populace that isn't clear on + * how capitalization should work. + * <p> + * We therefore ignore capitalization as much as possible. + * Completely mixed case is not possible, but all upper and lower + * forms are accepted for all long and short forms. Since we have + * no need to work with the 0.001 case, this practice works here. + * <p> + * This function translates all the long and short forms that a + * unit prefix can occur in and translates them into a single + * multiplier. + * + * @param $units The units to compare the size to. + * @return void + */ + public function setUnits($units) { + $i = array_search($units, self::$byteUnits, true); + if ($i === false) $i = -1; // make it java-like + + $this->multiplier = 0; + if (($i > -1) && ($i < 4)) { + $this->multiplier = 1000; + } elseif (($i > 3) && ($i < 9)) { + $this->multiplier = 1024; + } elseif (($i > 8) && ($i < 13)) { + $this->multiplier = 1000000; + } elseif (($i > 12) && ($i < 18)) { + $this->multiplier = 1048576; + } elseif (($i > 17) && ($i < 22)) { + $this->multiplier = 1000000000; + } elseif (($i > 21) && ($i < 27)) { + $this->multiplier = 1073741824; + } elseif (($i > 26) && ($i < 31)) { + $this->multiplier = 1000000000000; + } elseif (($i > 30) && ($i < 36)) { + $this->multiplier = 1099511627776; + } + if (($this->multiplier > 0) && ($this->size > -1)) { + $this->sizelimit = $this->size * $this->multiplier; + } + } + + /** + * This specifies when the file should be selected, whether it be + * when the file matches a particular size, when it is smaller, + * or whether it is larger. + * + * @param cmp The comparison to perform, an EnumeratedAttribute + */ + public function setWhen($cmp) { + $c = array_search($cmp, self::$sizeComparisons, true); + if ($c !== false) { + $this->cmp = $c; + } + } + + /** + * When using this as a custom selector, this method will be called. + * It translates each parameter into the appropriate setXXX() call. + * + * @param parameters the complete set of parameters for this selector + */ + public function setParameters($parameters) { + parent::setParameters($parameters); + if ($parameters !== null) { + for ($i = 0, $size=count($parameters); $i < $size; $i++) { + $paramname = $parameters[$i]->getName(); + switch(strtolower($paramname)) { + case self::SIZE_KEY: + try { + $this->setValue($parameters[$i]->getValue()); + } catch (Exception $nfe) { + $this->setError("Invalid size setting " + . $parameters[$i]->getValue()); + } + break; + case self::UNITS_KEY: + $this->setUnits($parameters[$i]->getValue()); + break; + case self::WHEN_KEY: + $this->setWhen($parameters[$i]->getValue()); + break; + default: + $this->setError("Invalid parameter " . $paramname); + } + } + } + } + + /** + * <p>Checks to make sure all settings are kosher. In this case, it + * means that the size attribute has been set (to a positive value), + * that the multiplier has a valid setting, and that the size limit + * is valid. Since the latter is a calculated value, this can only + * fail due to a programming error. + * </p> + * <p>If a problem is detected, the setError() method is called. + * </p> + */ + public function verifySettings() { + if ($this->size < 0) { + $this->setError("The value attribute is required, and must be positive"); + } elseif ($this->multiplier < 1) { + $this->setError("Invalid Units supplied, must be K,Ki,M,Mi,G,Gi,T,or Ti"); + } elseif ($this->sizelimit < 0) { + $this->setError("Internal error: Code is not setting sizelimit correctly"); + } + } + + /** + * The heart of the matter. This is where the selector gets to decide + * on the inclusion of a file in a particular fileset. + * + * @param basedir A PhingFile object for the base directory + * @param filename The name of the file to check + * @param file A PhingFile object for this filename + * @return whether the file should be selected or not + */ + public function isSelected(PhingFile $basedir, $filename, PhingFile $file) { + + $this->validate(); + + // Directory size never selected for + if ($file->isDirectory()) { + return true; + } + if ($this->cmp === 0) { + return ($file->length() < $this->sizelimit); + } elseif ($this->cmp === 1) { + return ($file->length() > $this->sizelimit); + } else { + return ($file->length() === $this->sizelimit); + } + } + +} + diff --git a/buildscripts/phing/classes/phing/types/selectors/TypeSelector.php b/buildscripts/phing/classes/phing/types/selectors/TypeSelector.php new file mode 100755 index 00000000..6ff024e8 --- /dev/null +++ b/buildscripts/phing/classes/phing/types/selectors/TypeSelector.php @@ -0,0 +1,120 @@ +<?php + +/* + * $Id: 95c34bb6a364dc0131e9e9c5c124d5074b4a2a21 $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +require_once 'phing/types/selectors/BaseExtendSelector.php'; + +/** + * Selector that selects a certain kind of file: directory or regular file. + * + * @author Hans Lellelid <hans@xmpl.org> (Phing) + * @author Jeff Turner <jefft@apache.org> (Ant) + * @version $Id: 95c34bb6a364dc0131e9e9c5c124d5074b4a2a21 $ + * @package phing.types.selectors + */ +class TypeSelector extends BaseExtendSelector { + + private $type; + + /** Key to used for parameterized custom selector */ + const TYPE_KEY = "type"; + + /** Valid types */ + private static $types = array('file', 'dir', 'link'); + + /** + * @return string A string describing this object + */ + public function toString() { + $buf = "{typeselector type: " . $this->type . "}"; + return $buf; + } + + /** + * Set the type of file to require. + * @param string $type The type of file - 'file' or 'dir' + */ + public function setType($type) { + $this->type = $type; + } + + /** + * When using this as a custom selector, this method will be called. + * It translates each parameter into the appropriate setXXX() call. + * + * @param array $parameters the complete set of parameters for this selector + */ + public function setParameters($parameters) { + parent::setParameters($parameters); + if ($parameters !== null) { + for ($i = 0, $size=count($parameters); $i < $size; $i++) { + $paramname = $parameters[$i]->getName(); + if (self::TYPE_KEY == strtolower($paramname)) { + $this->setType($parameters[$i]->getValue()); + } else { + $this->setError("Invalid parameter " . $paramname); + } + } + } + } + + /** + * Checks to make sure all settings are kosher. In this case, it + * means that the pattern attribute has been set. + * + */ + public function verifySettings() { + if ($this->type === null) { + $this->setError("The type attribute is required"); + } elseif (!in_array($this->type, self::$types, true)) { + $this->setError("Invalid type specified; must be one of (" . implode(self::$types) . ")"); + } + } + + /** + * The heart of the matter. This is where the selector gets to decide + * on the inclusion of a file in a particular fileset. + * + * @param PhingFile $basedir the base directory the scan is being done from + * @param string $filename is the name of the file to check + * @param PhingFile $file is a PhingFile object the selector can use + * @return boolean Whether the file should be selected or not + */ + public function isSelected(PhingFile $basedir, $filename, PhingFile $file) { + // throw BuildException on error + $this->validate(); + + if ($file->isLink()) { + if ($this->type == 'link') + return true; + + $this->log($file->getAbsolutePath() . " is a link, proceeding with " . $file->getCanonicalPath() . " instead.", Project::MSG_DEBUG); + $file = new PhingFile($file->getCanonicalPath()); + } + + if ($file->isDirectory()) { + return $this->type === 'dir'; + } else { + return $this->type === 'file'; + } + } + +} |