CC-2166: Packaging Improvements. Moved the Zend app into airtime_mvc. It is now installed to /var/www/airtime. Storage is now set to /srv/airtime/stor. Utils are now installed to /usr/lib/airtime/utils/. Added install/airtime-dircheck.php as a simple test to see if everything is install/uninstalled correctly.
This commit is contained in:
parent
514777e8d2
commit
b11cbd8159
4546 changed files with 138 additions and 51 deletions
999
airtime_mvc/library/phing/Project.php
Normal file
999
airtime_mvc/library/phing/Project.php
Normal file
|
@ -0,0 +1,999 @@
|
|||
<?php
|
||||
/*
|
||||
* $Id: Project.php 905 2010-10-05 16:28:03Z mrook $
|
||||
*
|
||||
* 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/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: 905 $
|
||||
* @package phing
|
||||
*/
|
||||
class Project {
|
||||
|
||||
// Logging level constants.
|
||||
const MSG_DEBUG = 4;
|
||||
const MSG_VERBOSE = 3;
|
||||
const MSG_INFO = 2;
|
||||
const MSG_WARN = 1;
|
||||
const MSG_ERR = 0;
|
||||
|
||||
/** 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;
|
||||
|
||||
/** require phing version */
|
||||
private $phingVersion;
|
||||
|
||||
/** 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;
|
||||
}
|
||||
$found = $this->properties[$name];
|
||||
// check to see if there are unresolved property references
|
||||
if (false !== strpos($found, '${')) {
|
||||
// attempt to resolve properties
|
||||
$found = $this->replaceProperties($found);
|
||||
// save resolved value
|
||||
$this->properties[$name] = $found;
|
||||
}
|
||||
return $found;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 the minimum required phing version **/
|
||||
function setPhingVersion($version) {
|
||||
$version = str_replace('phing', '', strtolower($version));
|
||||
$this->phingVersion = (string)trim($version);
|
||||
}
|
||||
|
||||
/** Get the minimum required phing version **/
|
||||
function getPhingVersion() {
|
||||
if($this->phingVersion === null) {
|
||||
$this->setPhingVersion(Phing::getPhingVersion());
|
||||
}
|
||||
return $this->phingVersion;
|
||||
}
|
||||
|
||||
/** 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 $typeName ($typeClass) 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;
|
||||
|
||||
$ctx = $this->getReference("phing.parsing.context");
|
||||
$current = $ctx->getConfigurator()->getCurrentTargets();
|
||||
$current[$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 {
|
||||
$classname = "";
|
||||
$tasklwr = strtolower($taskType);
|
||||
foreach ($this->taskdefs as $name => $class) {
|
||||
if (strtolower($name) === $tasklwr) {
|
||||
$classname = $class;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ($classname === "") {
|
||||
return null;
|
||||
}
|
||||
|
||||
$cls = Phing::import($classname);
|
||||
|
||||
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 datatype 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 {
|
||||
$c = (string) array_pop($stk);
|
||||
$sb .= " <- ".$c;
|
||||
} 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 Reference 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);
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue