diff options
author | xue <> | 2006-06-19 18:38:29 +0000 |
---|---|---|
committer | xue <> | 2006-06-19 18:38:29 +0000 |
commit | 588727c7e2b8954ec3dbde293cf4c4d68b119f9b (patch) | |
tree | fdcc16181a20335547953ccf1550e0006c11bf28 /buildscripts/phing/classes/phing/parser/ProjectConfigurator.php | |
parent | 127f78a4db3cc0fbbbb92f5b1abcfdce4a9af93b (diff) |
Merge from 3.0 branch till 1185.
Diffstat (limited to 'buildscripts/phing/classes/phing/parser/ProjectConfigurator.php')
-rw-r--r-- | buildscripts/phing/classes/phing/parser/ProjectConfigurator.php | 246 |
1 files changed, 246 insertions, 0 deletions
diff --git a/buildscripts/phing/classes/phing/parser/ProjectConfigurator.php b/buildscripts/phing/classes/phing/parser/ProjectConfigurator.php new file mode 100644 index 00000000..6b69e955 --- /dev/null +++ b/buildscripts/phing/classes/phing/parser/ProjectConfigurator.php @@ -0,0 +1,246 @@ +<?php +/* + * $Id: ProjectConfigurator.php,v 1.17 2006/01/06 14:57:18 hlellelid Exp $ + * + * 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/BufferedReader.php'; +include_once 'phing/system/io/FileReader.php'; +include_once 'phing/BuildException.php'; +include_once 'phing/system/lang/FileNotFoundException.php'; +include_once 'phing/system/io/PhingFile.php'; + +/** + * The datatype handler class. + * + * This class handles the occurance of registered datatype tags like + * FileSet + * + * @author Andreas Aderhold <andi@binarycloud.com> + * @copyright © 2001,2002 THYRELL. All rights reserved + * @version $Revision: 1.17 $ $Date: 2006/01/06 14:57:18 $ + * @access public + * @package phing.parser + */ +class ProjectConfigurator { + + public $project; + public $locator; + + public $buildFile; + public $buildFileParent; + + /** + * Static call to ProjectConfigurator. Use this to configure a + * project. Do not use the new operator. + * + * @param object the Project instance this configurator should use + * @param object the buildfile object the parser should use + * @access public + */ + public static function configureProject(Project $project, PhingFile $buildFile) { + $pc = new ProjectConfigurator($project, $buildFile); + $pc->parse(); + } + + /** + * Constructs a new ProjectConfigurator object + * This constructor is private. Use a static call to + * <code>configureProject</code> to configure a project. + * + * @param object the Project instance this configurator should use + * @param object the buildfile object the parser should use + * @access private + */ + function __construct(Project $project, PhingFile $buildFile) { + $this->project = $project; + $this->buildFile = new PhingFile($buildFile->getAbsolutePath()); + $this->buildFileParent = new PhingFile($this->buildFile->getParent()); + } + + /** + * Creates the ExpatParser, sets root handler and kick off parsing + * process. + * + * @throws BuildException if there is any kind of execption during + * the parsing process + * @access private + */ + protected function parse() { + try { + $reader = new BufferedReader(new FileReader($this->buildFile)); + $reader->open(); + $parser = new ExpatParser($reader); + $parser->parserSetOption(XML_OPTION_CASE_FOLDING,0); + $parser->setHandler(new RootHandler($parser, $this)); + $this->project->log("parsing buildfile ".$this->buildFile->getName(), PROJECT_MSG_VERBOSE); + $parser->parse(); + $reader->close(); + } catch (Exception $exc) { + throw new BuildException("Error reading project file", $exc); + } + } + + /** + * Configures an element and resolves eventually given properties. + * + * @param object the element to configure + * @param array the element's attributes + * @param object the project this element belongs to + * @throws Exception if arguments are not valid + * @throws BuildException if attributes can not be configured + * @access public + */ + function configure($target, $attrs, Project $project) { + + if ($target instanceof TaskAdapter) { + $target = $target->getProxy(); + } + + // if the target is an UnknownElement, this means that the tag had not been registered + // when the enclosing element (task, target, etc.) was configured. It is possible, however, + // that the tag was registered (e.g. using <taskdef>) after the original configuration. + // ... so, try to load it again: + if ($target instanceof UnknownElement) { + $tryTarget = $project->createTask($target->getTaskType()); + if ($tryTarget) { + $target = $tryTarget; + } + } + + $bean = get_class($target); + $ih = IntrospectionHelper::getHelper($bean); + + foreach ($attrs as $key => $value) { + if ($key == 'id') { + continue; + // throw new BuildException("Id must be set Extermnally"); + } + $value = self::replaceProperties($project, $value, $project->getProperties()); + try { // try to set the attribute + $ih->setAttribute($project, $target, strtolower($key), $value); + } catch (BuildException $be) { + // id attribute must be set externally + if ($key !== "id") { + throw $be; + } + } + } + } + + /** + * Configures the #CDATA of an element. + * + * @param object the project this element belongs to + * @param object the element to configure + * @param string the element's #CDATA + * @access public + */ + function addText($project, $target, $text = null) { + if ($text === null || strlen(trim($text)) === 0) { + return; + } + $ih = IntrospectionHelper::getHelper(get_class($target)); + $text = self::replaceProperties($project, $text, $project->getProperties()); + $ih->addText($project, $target, $text); + } + + /** + * Stores a configured child element into its parent object + * + * @param object the project this element belongs to + * @param object the parent element + * @param object the child element + * @param string the XML tagname + * @access public + */ + function storeChild($project, $parent, $child, $tag) { + $ih = IntrospectionHelper::getHelper(get_class($parent)); + $ih->storeElement($project, $parent, $child, $tag); + } + + // The following two properties are a sort of hack + // to enable a static function to serve as the callback + // for preg_replace_callback(). Clearly we cannot use object + // variables, since the replaceProperties() is called statically. + // This is IMO better than using global variables in the callback. + + private static $propReplaceProject; + private static $propReplaceProperties; + + /** + * Replace ${} style constructions in the given value with the + * string value of the corresponding data types. This method is + * static. + * + * @param object the project that should be used for property look-ups + * @param string the string to be scanned for property references + * @param array proeprty keys + * @return string the replaced string or <code>null</code> if the string + * itself was null + */ + public static function replaceProperties(Project $project, $value, $keys) { + + if ($value === null) { + return null; + } + + // These are a "hack" to support static callback for preg_replace_callback() + + // make sure these get initialized every time + self::$propReplaceProperties = $keys; + self::$propReplaceProject = $project; + + // Because we're not doing anything special (like multiple passes), + // regex is the simplest / fastest. PropertyTask, though, uses + // the old parsePropertyString() method, since it has more stringent + // requirements. + + $sb = preg_replace_callback('/\$\{([^}]+)\}/', array('ProjectConfigurator', 'replacePropertyCallback'), $value); + return $sb; + } + + /** + * Private [static] function for use by preg_replace_callback to replace a single param. + * This method makes use of a static variable to hold the + */ + private static function replacePropertyCallback($matches) + { + $propertyName = $matches[1]; + if (!isset(self::$propReplaceProperties[$propertyName])) { + self::$propReplaceProject->log('Property ${'.$propertyName.'} has not been set.', PROJECT_MSG_VERBOSE); + return $matches[0]; + } else { + self::$propReplaceProject->log('Property ${'.$propertyName.'} => ' . self::$propReplaceProperties[$propertyName], PROJECT_MSG_DEBUG); + } + return self::$propReplaceProperties[$propertyName]; + } + + /** + * Scan Attributes for the id attribute and maybe add a reference to + * project. + * + * @param object the element's object + * @param array the element's attributes + */ + function configureId(&$target, $attr) { + if (isset($attr['id']) && $attr['id'] !== null) { + $this->project->addReference($attr['id'], $target); + } + } +} |