summaryrefslogtreecommitdiff
path: root/buildscripts/phing/classes/phing/Project.php
diff options
context:
space:
mode:
Diffstat (limited to 'buildscripts/phing/classes/phing/Project.php')
-rw-r--r--buildscripts/phing/classes/phing/Project.php966
1 files changed, 0 insertions, 966 deletions
diff --git a/buildscripts/phing/classes/phing/Project.php b/buildscripts/phing/classes/phing/Project.php
deleted file mode 100644
index 8123d91e..00000000
--- a/buildscripts/phing/classes/phing/Project.php
+++ /dev/null
@@ -1,966 +0,0 @@
-<?php
-/*
- * $Id: Project.php,v 1.29 2006/02/02 20:27:10 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>.
- */
-
-define('PROJECT_MSG_DEBUG', 4);
-define('PROJECT_MSG_VERBOSE', 3);
-define('PROJECT_MSG_INFO', 2);
-define('PROJECT_MSG_WARN', 1);
-define('PROJECT_MSG_ERR', 0);
-
-include_once 'phing/system/io/PhingFile.php';
-include_once 'phing/util/FileUtils.php';
-include_once 'phing/TaskAdapter.php';
-include_once 'phing/util/StringHelper.php';
-include_once 'phing/BuildEvent.php';
-include_once 'phing/input/DefaultInputHandler.php';
-
-/**
- * The Phing project class. Represents a completely configured Phing project.
- * The class defines the project and all tasks/targets. It also contains
- * methods to start a build as well as some properties and FileSystem
- * abstraction.
- *
- * @author Andreas Aderhold <andi@binarycloud.com>
- * @author Hans Lellelid <hans@xmpl.org>
- * @version $Revision: 1.29 $
- * @package phing
- */
-class Project {
-
- /** contains the targets */
- private $targets = array();
- /** global filterset (future use) */
- private $globalFilterSet = array();
- /** all globals filters (future use) */
- private $globalFilters = array();
-
- /** Project properties map (usually String to String). */
- private $properties = array();
-
- /**
- * Map of "user" properties (as created in the Ant task, for example).
- * Note that these key/value pairs are also always put into the
- * project properties, so only the project properties need to be queried.
- * Mapping is String to String.
- */
- private $userProperties = array();
-
- /**
- * Map of inherited "user" properties - that are those "user"
- * properties that have been created by tasks and not been set
- * from the command line or a GUI tool.
- * Mapping is String to String.
- */
- private $inheritedProperties = array();
-
- /** task definitions for this project*/
- private $taskdefs = array();
-
- /** type definitions for this project */
- private $typedefs = array();
-
- /** holds ref names and a reference to the referred object*/
- private $references = array();
-
- /** The InputHandler being used by this project. */
- private $inputHandler;
-
- /* -- properties that come in via xml attributes -- */
-
- /** basedir (PhingFile object) */
- private $basedir;
-
- /** the default target name */
- private $defaultTarget = 'all';
-
- /** project name (required) */
- private $name;
-
- /** project description */
- private $description;
-
- /** a FileUtils object */
- private $fileUtils;
-
- /** Build listeneers */
- private $listeners = array();
-
- /**
- * Constructor, sets any default vars.
- */
- function __construct() {
- $this->fileUtils = new FileUtils();
- $this->inputHandler = new DefaultInputHandler();
- }
-
- /**
- * Sets the input handler
- */
- public function setInputHandler(InputHandler $handler) {
- $this->inputHandler = $handler;
- }
-
- /**
- * Retrieves the current input handler.
- */
- public function getInputHandler() {
- return $this->inputHandler;
- }
-
- /** inits the project, called from main app */
- function init() {
- // set builtin properties
- $this->setSystemProperties();
-
- // load default tasks
- $taskdefs = Phing::getResourcePath("phing/tasks/defaults.properties");
-
- try { // try to load taskdefs
- $props = new Properties();
- $in = new PhingFile((string)$taskdefs);
-
- if ($in === null) {
- throw new BuildException("Can't load default task list");
- }
- $props->load($in);
-
- $enum = $props->propertyNames();
- foreach($enum as $key) {
- $value = $props->getProperty($key);
- $this->addTaskDefinition($key, $value);
- }
- } catch (IOException $ioe) {
- throw new BuildException("Can't load default task list");
- }
-
- // load default tasks
- $typedefs = Phing::getResourcePath("phing/types/defaults.properties");
-
- try { // try to load typedefs
- $props = new Properties();
- $in = new PhingFile((string)$typedefs);
- if ($in === null) {
- throw new BuildException("Can't load default datatype list");
- }
- $props->load($in);
-
- $enum = $props->propertyNames();
- foreach($enum as $key) {
- $value = $props->getProperty($key);
- $this->addDataTypeDefinition($key, $value);
- }
- } catch(IOException $ioe) {
- throw new BuildException("Can't load default datatype list");
- }
- }
-
- /** returns the global filterset (future use) */
- function getGlobalFilterSet() {
- return $this->globalFilterSet;
- }
-
- // ---------------------------------------------------------
- // Property methods
- // ---------------------------------------------------------
-
- /**
- * Sets a property. Any existing property of the same name
- * is overwritten, unless it is a user property.
- * @param string $name The name of property to set.
- * Must not be <code>null</code>.
- * @param string $value The new value of the property.
- * Must not be <code>null</code>.
- * @return void
- */
- public function setProperty($name, $value) {
-
- // command line properties take precedence
- if (isset($this->userProperties[$name])) {
- $this->log("Override ignored for user property " . $name, PROJECT_MSG_VERBOSE);
- return;
- }
-
- if (isset($this->properties[$name])) {
- $this->log("Overriding previous definition of property " . $name, PROJECT_MSG_VERBOSE);
- }
-
- $this->log("Setting project property: " . $name . " -> " . $value, PROJECT_MSG_DEBUG);
- $this->properties[$name] = $value;
- }
-
- /**
- * Sets a property if no value currently exists. If the property
- * exists already, a message is logged and the method returns with
- * no other effect.
- *
- * @param string $name The name of property to set.
- * Must not be <code>null</code>.
- * @param string $value The new value of the property.
- * Must not be <code>null</code>.
- * @since 2.0
- */
- public function setNewProperty($name, $value) {
- if (isset($this->properties[$name])) {
- $this->log("Override ignored for property " . $name, PROJECT_MSG_DEBUG);
- return;
- }
- $this->log("Setting project property: " . $name . " -> " . $value, PROJECT_MSG_DEBUG);
- $this->properties[$name] = $value;
- }
-
- /**
- * Sets a user property, which cannot be overwritten by
- * set/unset property calls. Any previous value is overwritten.
- * @param string $name The name of property to set.
- * Must not be <code>null</code>.
- * @param string $value The new value of the property.
- * Must not be <code>null</code>.
- * @see #setProperty()
- */
- public function setUserProperty($name, $value) {
- $this->log("Setting ro project property: " . $name . " -> " . $value, PROJECT_MSG_DEBUG);
- $this->userProperties[$name] = $value;
- $this->properties[$name] = $value;
- }
-
- /**
- * Sets a user property, which cannot be overwritten by set/unset
- * property calls. Any previous value is overwritten. Also marks
- * these properties as properties that have not come from the
- * command line.
- *
- * @param string $name The name of property to set.
- * Must not be <code>null</code>.
- * @param string $value The new value of the property.
- * Must not be <code>null</code>.
- * @see #setProperty()
- */
- public function setInheritedProperty($name, $value) {
- $this->inheritedProperties[$name] = $value;
- $this->setUserProperty($name, $value);
- }
-
- /**
- * Sets a property unless it is already defined as a user property
- * (in which case the method returns silently).
- *
- * @param name The name of the property.
- * Must not be <code>null</code>.
- * @param value The property value. Must not be <code>null</code>.
- */
- private function setPropertyInternal($name, $value) {
- if (isset($this->userProperties[$name])) {
- $this->log("Override ignored for user property " . $name, PROJECT_MSG_VERBOSE);
- return;
- }
- $this->properties[$name] = $value;
- }
-
- /**
- * Returns the value of a property, if it is set.
- *
- * @param string $name The name of the property.
- * May be <code>null</code>, in which case
- * the return value is also <code>null</code>.
- * @return string The property value, or <code>null</code> for no match
- * or if a <code>null</code> name is provided.
- */
- public function getProperty($name) {
- if (!isset($this->properties[$name])) {
- return null;
- }
- return $this->properties[$name];
- }
-
- /**
- * Replaces ${} style constructions in the given value with the
- * string value of the corresponding data types.
- *
- * @param value The string to be scanned for property references.
- * May be <code>null</code>.
- *
- * @return the given string with embedded property names replaced
- * by values, or <code>null</code> if the given string is
- * <code>null</code>.
- *
- * @exception BuildException if the given value has an unclosed
- * property name, e.g. <code>${xxx</code>
- */
- public function replaceProperties($value) {
- return ProjectConfigurator::replaceProperties($this, $value, $this->properties);
- }
-
- /**
- * Returns the value of a user property, if it is set.
- *
- * @param string $name The name of the property.
- * May be <code>null</code>, in which case
- * the return value is also <code>null</code>.
- * @return string The property value, or <code>null</code> for no match
- * or if a <code>null</code> name is provided.
- */
- public function getUserProperty($name) {
- if (!isset($this->userProperties[$name])) {
- return null;
- }
- return $this->userProperties[$name];
- }
-
- /**
- * Returns a copy of the properties table.
- * @return array A hashtable containing all properties
- * (including user properties).
- */
- public function getProperties() {
- return $this->properties;
- }
-
- /**
- * Returns a copy of the user property hashtable
- * @return a hashtable containing just the user properties
- */
- public function getUserProperties() {
- return $this->userProperties;
- }
-
- /**
- * Copies all user properties that have been set on the command
- * line or a GUI tool from this instance to the Project instance
- * given as the argument.
- *
- * <p>To copy all "user" properties, you will also have to call
- * {@link #copyInheritedProperties copyInheritedProperties}.</p>
- *
- * @param Project $other the project to copy the properties to. Must not be null.
- * @return void
- * @since phing 2.0
- */
- public function copyUserProperties(Project $other) {
- foreach($this->userProperties as $arg => $value) {
- if (isset($this->inheritedProperties[$arg])) {
- continue;
- }
- $other->setUserProperty($arg, $value);
- }
- }
-
- /**
- * Copies all user properties that have not been set on the
- * command line or a GUI tool from this instance to the Project
- * instance given as the argument.
- *
- * <p>To copy all "user" properties, you will also have to call
- * {@link #copyUserProperties copyUserProperties}.</p>
- *
- * @param other the project to copy the properties to. Must not be null.
- *
- * @since phing 2.0
- */
- public function copyInheritedProperties(Project $other) {
- foreach($this->userProperties as $arg => $value) {
- if ($other->getUserProperty($arg) !== null) {
- continue;
- }
- $other->setInheritedProperty($arg, $value);
- }
- }
-
- // ---------------------------------------------------------
- // END Properties methods
- // ---------------------------------------------------------
-
-
- function setDefaultTarget($targetName) {
- $this->defaultTarget = (string) trim($targetName);
- }
-
- function getDefaultTarget() {
- return (string) $this->defaultTarget;
- }
-
- /**
- * Sets the name of the current project
- *
- * @param string name of project
- * @return void
- * @access public
- * @author Andreas Aderhold, andi@binarycloud.com
- */
-
- function setName($name) {
- $this->name = (string) trim($name);
- $this->setProperty("phing.project.name", $this->name);
- }
-
- /**
- * Returns the name of this project
- *
- * @returns string projectname
- * @access public
- * @author Andreas Aderhold, andi@binarycloud.com
- */
- function getName() {
- return (string) $this->name;
- }
-
- /** Set the projects description */
- function setDescription($description) {
- $this->description = (string) trim($description);
- }
-
- /** return the description, null otherwise */
- function getDescription() {
- return $this->description;
- }
-
- /** Set basedir object from xml*/
- function setBasedir($dir) {
- if ($dir instanceof PhingFile) {
- $dir = $dir->getAbsolutePath();
- }
-
- $dir = $this->fileUtils->normalize($dir);
-
- $dir = new PhingFile((string) $dir);
- if (!$dir->exists()) {
- throw new BuildException("Basedir ".$dir->getAbsolutePath()." does not exist");
- }
- if (!$dir->isDirectory()) {
- throw new BuildException("Basedir ".$dir->getAbsolutePath()." is not a directory");
- }
- $this->basedir = $dir;
- $this->setPropertyInternal("project.basedir", $this->basedir->getAbsolutePath());
- $this->log("Project base dir set to: " . $this->basedir->getPath(), PROJECT_MSG_VERBOSE);
-
- // [HL] added this so that ./ files resolve correctly. This may be a mistake ... or may be in wrong place.
- chdir($dir->getAbsolutePath());
- }
-
- /**
- * Returns the basedir of this project
- *
- * @returns PhingFile Basedir PhingFile object
- * @access public
- * @throws BuildException
- * @author Andreas Aderhold, andi@binarycloud.com
- */
- function getBasedir() {
- if ($this->basedir === null) {
- try { // try to set it
- $this->setBasedir(".");
- } catch (BuildException $exc) {
- throw new BuildException("Can not set default basedir. ".$exc->getMessage());
- }
- }
- return $this->basedir;
- }
-
- /**
- * Sets system properties and the environment variables for this project.
- *
- * @return void
- */
- function setSystemProperties() {
-
- // first get system properties
- $systemP = array_merge( self::getProperties(), Phing::getProperties() );
- foreach($systemP as $name => $value) {
- $this->setPropertyInternal($name, $value);
- }
-
- // and now the env vars
- foreach($_SERVER as $name => $value) {
- // skip arrays
- if (is_array($value)) {
- continue;
- }
- $this->setPropertyInternal('env.' . $name, $value);
- }
- return true;
- }
-
-
- /**
- * Adds a task definition.
- * @param string $name Name of tag.
- * @param string $class The class path to use.
- * @param string $classpath The classpat to use.
- */
- function addTaskDefinition($name, $class, $classpath = null) {
- $name = $name;
- $class = $class;
- if ($class === "") {
- $this->log("Task $name has no class defined.", PROJECT_MSG_ERR);
- } elseif (!isset($this->taskdefs[$name])) {
- Phing::import($class, $classpath);
- $this->taskdefs[$name] = $class;
- $this->log(" +Task definiton: $name ($class)", PROJECT_MSG_DEBUG);
- } else {
- $this->log("Task $name ($class) already registerd, skipping", PROJECT_MSG_VERBOSE);
- }
- }
-
- function &getTaskDefinitions() {
- return $this->taskdefs;
- }
-
- /**
- * Adds a data type definition.
- * @param string $name Name of tag.
- * @param string $class The class path to use.
- * @param string $classpath The classpat to use.
- */
- function addDataTypeDefinition($typeName, $typeClass, $classpath = null) {
- if (!isset($this->typedefs[$typeName])) {
- Phing::import($typeClass, $classpath);
- $this->typedefs[$typeName] = $typeClass;
- $this->log(" +User datatype: $typeName ($typeClass)", PROJECT_MSG_DEBUG);
- } else {
- $this->log("Type $name ($class) already registerd, skipping", PROJECT_MSG_VERBOSE);
- }
- }
-
- function getDataTypeDefinitions() {
- return $this->typedefs;
- }
-
- /** add a new target to the project */
- function addTarget($targetName, &$target) {
- if (isset($this->targets[$targetName])) {
- throw new BuildException("Duplicate target: $targetName");
- }
- $this->addOrReplaceTarget($targetName, $target);
- }
-
- function addOrReplaceTarget($targetName, &$target) {
- $this->log(" +Target: $targetName", PROJECT_MSG_DEBUG);
- $target->setProject($this);
- $this->targets[$targetName] = $target;
- }
-
- function getTargets() {
- return $this->targets;
- }
-
- /**
- * Create a new task instance and return reference to it. This method is
- * sorta factory like. A _local_ instance is created and a reference returned to
- * that instance. Usually PHP destroys local variables when the function call
- * ends. But not if you return a reference to that variable.
- * This is kinda error prone, because if no reference exists to the variable
- * it is destroyed just like leaving the local scope with primitive vars. There's no
- * central place where the instance is stored as in other OOP like languages.
- *
- * [HL] Well, ZE2 is here now, and this is still working. We'll leave this alone
- * unless there's any good reason not to.
- *
- * @param string $taskType Task name
- * @returns Task A task object
- * @throws BuildException
- * Exception
- */
- function createTask($taskType) {
- try {
- $cls = "";
- $tasklwr = strtolower($taskType);
- foreach ($this->taskdefs as $name => $class) {
- if (strtolower($name) === $tasklwr) {
- $cls = StringHelper::unqualify($class);
- break;
- }
- }
-
- if ($cls === "") {
- return null;
- }
-
- if (!class_exists($cls)) {
- throw new BuildException("Could not instantiate class $cls, even though a class was specified. (Make sure that the specified class file contains a class with the correct name.)");
- }
-
- $o = new $cls();
-
- if ($o instanceof Task) {
- $task = $o;
- } else {
- $this->log (" (Using TaskAdapter for: $taskType)", PROJECT_MSG_DEBUG);
- // not a real task, try adapter
- $taskA = new TaskAdapter();
- $taskA->setProxy($o);
- $task = $taskA;
- }
- $task->setProject($this);
- $task->setTaskType($taskType);
- // set default value, can be changed by the user
- $task->setTaskName($taskType);
- $this->log (" +Task: " . $taskType, PROJECT_MSG_DEBUG);
- } catch (Exception $t) {
- throw new BuildException("Could not create task of type: " . $taskType, $t);
- }
- // everything fine return reference
- return $task;
- }
-
- /**
- * Create a task instance and return reference to it
- * See createTask() for explanation how this works
- *
- * @param string Type name
- * @returns object A datatype object
- * @throws BuildException
- * Exception
- */
- function createDataType($typeName) {
- try {
- $cls = "";
- $typelwr = strtolower($typeName);
- foreach ($this->typedefs as $name => $class) {
- if (strtolower($name) === $typelwr) {
- $cls = StringHelper::unqualify($class);
- break;
- }
- }
-
- if ($cls === "") {
- return null;
- }
-
- if (!class_exists($cls)) {
- throw new BuildException("Could not instantiate class $cls, even though a class was specified. (Make sure that the specified class file contains a class with the correct name.)");
- }
-
- $type = new $cls();
- $this->log(" +Type: $typeName", PROJECT_MSG_DEBUG);
- if (!($type instanceof DataType)) {
- throw new Exception("$class is not an instance of phing.types.DataType");
- }
- if ($type instanceof ProjectComponent) {
- $type->setProject($this);
- }
- } catch (Exception $t) {
- throw new BuildException("Could not create type: $typeName", $t);
- }
- // everything fine return reference
- return $type;
- }
-
- /**
- * Executes a list of targets
- *
- * @param array List of target names to execute
- * @returns void
- * @throws BuildException
- */
- function executeTargets($targetNames) {
- foreach($targetNames as $tname) {
- $this->executeTarget($tname);
- }
- }
-
- /**
- * Executes a target
- *
- * @param string Name of Target to execute
- * @returns void
- * @throws BuildException
- */
- function executeTarget($targetName) {
-
- // complain about executing void
- if ($targetName === null) {
- throw new BuildException("No target specified");
- }
-
- // invoke topological sort of the target tree and run all targets
- // until targetName occurs.
- $sortedTargets = $this->_topoSort($targetName, $this->targets);
-
- $curIndex = (int) 0;
- $curTarget = null;
- do {
- try {
- $curTarget = $sortedTargets[$curIndex++];
- $curTarget->performTasks();
- } catch (BuildException $exc) {
- $this->log("Execution of target \"".$curTarget->getName()."\" failed for the following reason: ".$exc->getMessage(), PROJECT_MSG_ERR);
- throw $exc;
- }
- } while ($curTarget->getName() !== $targetName);
- }
-
-
- function resolveFile($fileName, $rootDir = null) {
- if ($rootDir === null) {
- return $this->fileUtils->resolveFile($this->basedir, $fileName);
- } else {
- return $this->fileUtils->resolveFile($rootDir, $fileName);
- }
- }
-
- /**
- * Topologically sort a set of Targets.
- * @param $root is the (String) name of the root Target. The sort is
- * created in such a way that the sequence of Targets until the root
- * target is the minimum possible such sequence.
- * @param $targets is a array representing a "name to Target" mapping
- * @return An array of Strings with the names of the targets in
- * sorted order.
- */
- function _topoSort($root, &$targets) {
-
- $root = (string) $root;
- $ret = array();
- $state = array();
- $visiting = array();
-
- // We first run a DFS based sort using the root as the starting node.
- // This creates the minimum sequence of Targets to the root node.
- // We then do a sort on any remaining unVISITED targets.
- // This is unnecessary for doing our build, but it catches
- // circular dependencies or missing Targets on the entire
- // dependency tree, not just on the Targets that depend on the
- // build Target.
-
- $this->_tsort($root, $targets, $state, $visiting, $ret);
-
- $retHuman = "";
- for ($i=0, $_i=count($ret); $i < $_i; $i++) {
- $retHuman .= $ret[$i]->toString()." ";
- }
- $this->log("Build sequence for target '$root' is: $retHuman", PROJECT_MSG_VERBOSE);
-
- $keys = array_keys($targets);
- while($keys) {
- $curTargetName = (string) array_shift($keys);
- if (!isset($state[$curTargetName])) {
- $st = null;
- } else {
- $st = (string) $state[$curTargetName];
- }
-
- if ($st === null) {
- $this->_tsort($curTargetName, $targets, $state, $visiting, $ret);
- } elseif ($st === "VISITING") {
- throw new Exception("Unexpected node in visiting state: $curTargetName");
- }
- }
-
- $retHuman = "";
- for ($i=0,$_i=count($ret); $i < $_i; $i++) {
- $retHuman .= $ret[$i]->toString()." ";
- }
- $this->log("Complete build sequence is: $retHuman", PROJECT_MSG_VERBOSE);
-
- return $ret;
- }
-
- // one step in a recursive DFS traversal of the target dependency tree.
- // - The array "state" contains the state (VISITED or VISITING or null)
- // of all the target names.
- // - The stack "visiting" contains a stack of target names that are
- // currently on the DFS stack. (NB: the target names in "visiting" are
- // exactly the target names in "state" that are in the VISITING state.)
- // 1. Set the current target to the VISITING state, and push it onto
- // the "visiting" stack.
- // 2. Throw a BuildException if any child of the current node is
- // in the VISITING state (implies there is a cycle.) It uses the
- // "visiting" Stack to construct the cycle.
- // 3. If any children have not been VISITED, tsort() the child.
- // 4. Add the current target to the Vector "ret" after the children
- // have been visited. Move the current target to the VISITED state.
- // "ret" now contains the sorted sequence of Targets upto the current
- // Target.
-
- function _tsort($root, &$targets, &$state, &$visiting, &$ret) {
- $state[$root] = "VISITING";
- $visiting[] = $root;
-
- if (!isset($targets[$root]) || !($targets[$root] instanceof Target)) {
- $target = null;
- } else {
- $target = $targets[$root];
- }
-
- // make sure we exist
- if ($target === null) {
- $sb = "Target '$root' does not exist in this project.";
- array_pop($visiting);
- if (!empty($visiting)) {
- $parent = (string) $visiting[count($visiting)-1];
- $sb .= "It is used from target '$parent'.";
- }
- throw new BuildException($sb);
- }
-
- $deps = $target->getDependencies();
-
- while($deps) {
- $cur = (string) array_shift($deps);
- if (!isset($state[$cur])) {
- $m = null;
- } else {
- $m = (string) $state[$cur];
- }
- if ($m === null) {
- // not been visited
- $this->_tsort($cur, $targets, $state, $visiting, $ret);
- } elseif ($m == "VISITING") {
- // currently visiting this node, so have a cycle
- throw $this->_makeCircularException($cur, $visiting);
- }
- }
-
- $p = (string) array_pop($visiting);
- if ($root !== $p) {
- throw new Exception("Unexpected internal error: expected to pop $root but got $p");
- }
-
- $state[$root] = "VISITED";
- $ret[] = $target;
- }
-
- function _makeCircularException($end, $stk) {
- $sb = "Circular dependency: $end";
- do {
- $sb .= " <- ".(string) array_pop($stk);
- } while($c != $end);
- return new BuildException($sb);
- }
-
- /**
- * Adds a reference to an object. This method is called when the parser
- * detects a id="foo" attribute. It passes the id as $name and a reference
- * to the object assigned to this id as $value
- */
- function addReference($name, $object) {
- if (isset($this->references[$name])) {
- $this->log("Overriding previous definition of reference to $name", PROJECT_MSG_WARN);
- }
- $this->log("Adding reference: $name -> ".get_class($object), PROJECT_MSG_DEBUG);
- $this->references[$name] = $object;
- }
-
- /**
- * Returns the references array.
- * @return array
- */
- function getReferences() {
- return $this->references;
- }
-
- /**
- * Returns a specific reference.
- * @param string $key The reference id/key.
- * @return object or null if not defined
- */
- function getReference($key)
- {
- if (isset($this->references[$key])) {
- return $this->references[$key];
- }
- return null; // just to be explicit
- }
-
- /**
- * Abstracting and simplifyling Logger calls for project messages
- */
- function log($msg, $level = PROJECT_MSG_INFO) {
- $this->logObject($this, $msg, $level);
- }
-
- function logObject($obj, $msg, $level) {
- $this->fireMessageLogged($obj, $msg, $level);
- }
-
- function addBuildListener(BuildListener $listener) {
- $this->listeners[] = $listener;
- }
-
- function removeBuildListener(BuildListener $listener) {
- $newarray = array();
- for ($i=0, $size=count($this->listeners); $i < $size; $i++) {
- if ($this->listeners[$i] !== $listener) {
- $newarray[] = $this->listeners[$i];
- }
- }
- $this->listeners = $newarray;
- }
-
- function getBuildListeners() {
- return $this->listeners;
- }
-
- function fireBuildStarted() {
- $event = new BuildEvent($this);
- foreach($this->listeners as $listener) {
- $listener->buildStarted($event);
- }
- }
-
- function fireBuildFinished($exception) {
- $event = new BuildEvent($this);
- $event->setException($exception);
- foreach($this->listeners as $listener) {
- $listener->buildFinished($event);
- }
- }
-
- function fireTargetStarted($target) {
- $event = new BuildEvent($target);
- foreach($this->listeners as $listener) {
- $listener->targetStarted($event);
- }
- }
-
- function fireTargetFinished($target, $exception) {
- $event = new BuildEvent($target);
- $event->setException($exception);
- foreach($this->listeners as $listener) {
- $listener->targetFinished($event);
- }
- }
-
- function fireTaskStarted($task) {
- $event = new BuildEvent($task);
- foreach($this->listeners as $listener) {
- $listener->taskStarted($event);
- }
- }
-
- function fireTaskFinished($task, $exception) {
- $event = new BuildEvent($task);
- $event->setException($exception);
- foreach($this->listeners as $listener) {
- $listener->taskFinished($event);
- }
- }
-
- function fireMessageLoggedEvent($event, $message, $priority) {
- $event->setMessage($message, $priority);
- foreach($this->listeners as $listener) {
- $listener->messageLogged($event);
- }
- }
-
- function fireMessageLogged($object, $message, $priority) {
- $this->fireMessageLoggedEvent(new BuildEvent($object), $message, $priority);
- }
-}