libraries for propel

This commit is contained in:
naomiaro 2010-11-08 23:16:28 -05:00
parent 1e0cba6a63
commit 06cb25a68b
317 changed files with 58926 additions and 0 deletions

198
3rd_party/php/phing/BuildEvent.php vendored Normal file
View file

@ -0,0 +1,198 @@
<?php
/*
* $Id: BuildEvent.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>.
*/
require_once 'phing/system/lang/EventObject.php';
/**
* Encapsulates a build specific event.
*
* <p>We have three sources of events all handled by this class:
*
* <ul>
* <li>Project level events</li>
* <li>Target level events</li>
* <li>Task level events</li>
* </ul>
*
* <p> Events are all fired from the project class by creating an event object
* using this class and passing it to the listeners.
*
* @author Andreas Aderhold <andi@binarycloud.com>
* @author Hans Lellelid <hans@xmpl.org>
* @version $Revision: 905 $
* @package phing
*/
class BuildEvent extends EventObject {
/**
* A reference to the project
* @var Project
*/
protected $project;
/**
* A reference to the target
* @var Target
*/
protected $target;
/**
* A reference to the task
*
* @var Task
*/
protected $task;
/**
* The message of this event, if the event is a message
* @var string
*/
protected $message = null;
/**
* The priority of the message
*
* @var string
* @see $message
*/
protected $priority = Project::MSG_VERBOSE;
/**
* The execption that caused the event, if any
*
* @var object
*/
protected $exception = null;
/**
* Construct a BuildEvent for a project, task or target source event
*
* @param object project the project that emitted the event.
*/
public function __construct($source) {
parent::__construct($source);
if ($source instanceof Project) {
$this->project = $source;
$this->target = null;
$this->task = null;
} elseif ($source instanceof Target) {
$this->project = $source->getProject();
$this->target = $source;
$this->task = null;
} elseif ($source instanceof Task) {
$this->project = $source->getProject();
$this->target = $source->getOwningTarget();
$this->task = $source;
} else {
throw new Exception("Can not construct BuildEvent, unknown source given.");
}
}
/**
* Sets the message with details and the message priority for this event.
*
* @param string The string message of the event
* @param integer The priority this message should have
*/
public function setMessage($message, $priority) {
$this->message = (string) $message;
$this->priority = (int) $priority;
}
/**
* Set the exception that was the cause of this event.
*
* @param Exception The exception that caused the event
*/
public function setException($exception) {
$this->exception = $exception;
}
/**
* Returns the project instance that fired this event.
*
* The reference to the project instance is set by the constructor if this
* event was fired from the project class.
*
* @return Project The project instance that fired this event
*/
public function getProject() {
return $this->project;
}
/**
* Returns the target instance that fired this event.
*
* The reference to the target instance is set by the constructor if this
* event was fired from the target class.
*
* @return Target The target that fired this event
*/
public function getTarget() {
return $this->target;
}
/**
* Returns the target instance that fired this event.
*
* The reference to the task instance is set by the constructor if this
* event was fired within a task.
*
* @return Task The task that fired this event
*/
public function getTask() {
return $this->task;
}
/**
* Returns the logging message. This field will only be set for
* "messageLogged" events.
*
* @return string The log message
*/
function getMessage() {
return $this->message;
}
/**
* Returns the priority of the logging message. This field will only
* be set for "messageLogged" events.
*
* @return integer The message priority
*/
function getPriority() {
return $this->priority;
}
/**
* Returns the exception that was thrown, if any.
* This field will only be set for "taskFinished", "targetFinished", and
* "buildFinished" events.
*
* @see BuildListener::taskFinished()
* @see BuildListener::targetFinished()
* @see BuildListener::buildFinished()
* @return Exception
*/
public function getException() {
return $this->exception;
}
}

121
3rd_party/php/phing/BuildException.php vendored Normal file
View file

@ -0,0 +1,121 @@
<?php
/*
* $Id: BuildException.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>.
*/
/**
* BuildException is for when things go wrong in a build execution.
*
* @author Andreas Aderhold <andi@binarycloud.com>
* @version $Revision: 905 $
* @package phing
*/
class BuildException extends Exception {
/**
* Location in the xml file.
* @var Location
*/
protected $location;
/**
* The nested "cause" exception.
* @var Exception
*/
protected $cause;
/**
* Construct a BuildException.
* Supported signatures:
* throw new BuildException($causeExc);
* throw new BuildException($msg);
* throw new Buildexception($causeExc, $loc);
* throw new BuildException($msg, $causeExc);
* throw new BuildException($msg, $loc);
* throw new BuildException($msg, $causeExc, $loc);
*/
function __construct($p1, $p2 = null, $p3 = null) {
$cause = null;
$loc = null;
$msg = "";
if ($p3 !== null) {
$cause = $p2;
$loc = $p3;
$msg = $p1;
} elseif ($p2 !== null) {
if ($p2 instanceof Exception) {
$cause = $p2;
$msg = $p1;
} elseif ($p2 instanceof Location) {
$loc = $p2;
if ($p1 instanceof Exception) {
$cause = $p1;
} else {
$msg = $p1;
}
}
} elseif ($p1 instanceof Exception) {
$cause = $p1;
} else {
$msg = $p1;
}
parent::__construct($msg);
if ($cause !== null) {
$this->cause = $cause;
$this->message .= " [wrapped: " . $cause->getMessage() ."]";
}
if ($loc !== null) {
$this->setLocation($loc);
}
}
/**
* Gets the cause exception.
*
* @return Exception
*/
public function getCause() {
return $this->cause;
}
/**
* Gets the location of error in XML file.
*
* @return Location
*/
public function getLocation() {
return $this->location;
}
/**
* Sets the location of error in XML file.
*
* @param Locaiton $loc
*/
public function setLocation(Location $loc) {
$this->location = $loc;
$this->message = $loc->toString() . ': ' . $this->message;
}
}

91
3rd_party/php/phing/BuildListener.php vendored Normal file
View file

@ -0,0 +1,91 @@
<?php
/*
* $Id: BuildListener.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>.
*/
/**
* Interface for build listeners.
*
* Classes that implement a listener must extend this class and (faux)implement
* all methods that are decleard as dummies below.
*
* @author Andreas Aderhold <andi@binarycloud.com>
* @author Hans Lellelid <hans@xmpl.org>
* @version $Revision: 905 $
* @see BuildEvent
* @see Project::addBuildListener()
* @package phing
*/
interface BuildListener {
/**
* Fired before any targets are started.
*
* @param BuildEvent The BuildEvent
*/
function buildStarted(BuildEvent $event);
/**
* Fired after the last target has finished.
*
* @param BuildEvent The BuildEvent
* @see BuildEvent::getException()
*/
function buildFinished(BuildEvent $event);
/**
* Fired when a target is started.
*
* @param BuildEvent The BuildEvent
* @see BuildEvent::getTarget()
*/
function targetStarted(BuildEvent $event);
/**
* Fired when a target has finished.
*
* @param BuildEvent The BuildEvent
* @see BuildEvent#getException()
*/
function targetFinished(BuildEvent $event);
/**
* Fired when a task is started.
*
* @param BuildEvent The BuildEvent
* @see BuildEvent::getTask()
*/
function taskStarted(BuildEvent $event);
/**
* Fired when a task has finished.
*
* @param BuildEvent The BuildEvent
* @see BuildEvent::getException()
*/
function taskFinished(BuildEvent $event);
/**
* Fired whenever a message is logged.
*
* @param BuildEvent The BuildEvent
* @see BuildEvent::getMessage()
*/
function messageLogged(BuildEvent $event);
}

70
3rd_party/php/phing/BuildLogger.php vendored Normal file
View file

@ -0,0 +1,70 @@
<?php
/*
* $Id: BuildLogger.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>.
*/
require_once 'phing/BuildListener.php';
/**
* Interface for build loggers.
*
* Build loggers are build listeners but with some additional functionality:
* - They can be configured with a log level (below which they will ignore messages)
* - They have error and output streams
*
* Classes that implement a listener must implement this interface.
*
* @author Hans Lellelid <hans@xmpl.org>
* @version $Revision: 905 $
* @see BuildEvent
* @see Project::addBuildListener()
* @package phing
*/
interface BuildLogger extends BuildListener {
/**
* Sets the min log level that this logger should respect.
*
* Messages below this level are ignored.
*
* Constants for the message levels are in Project.php. The order of
* the levels, from least to most verbose, is:
* - Project::MSG_ERR
* - Project::MSG_WARN
* - Project::MSG_INFO
* - Project::MSG_VERBOSE
* - Project::MSG_DEBUG
*
* @param int $level The log level integer (e.g. Project::MSG_VERBOSE, etc.).
*/
public function setMessageOutputLevel($level);
/**
* Sets the standard output stream to use.
* @param OutputStream $output Configured output stream (e.g. STDOUT) for standard output.
*/
public function setOutputStream(OutputStream $output);
/**
* Sets the output stream to use for errors.
* @param OutputStream $err Configured output stream (e.g. STDERR) for errors.
*/
public function setErrorStream(OutputStream $err);
}

View file

@ -0,0 +1,83 @@
<?php
/*
* $Id: ConfigurationException.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>.
*/
/**
* ConfigurationException is thrown by Phing during the configuration and setup phase of the project.
*
* @author Hans Lellelid <hans@xmpl.org>
* @version $Revision: 905 $
* @package phing
*/
class ConfigurationException extends Exception {
/**
* Location in the xml file.
* @var Location
*/
protected $location;
/**
* The nested "cause" exception.
* @var Exception
*/
protected $cause;
/**
* Construct a BuildException.
* Supported signatures:
* throw new BuildException($causeExc);
* throw new BuildException($msg);
* throw new BuildException($msg, $causeExc);
*/
function __construct($p1, $p2 = null, $p3 = null) {
$cause = null;
$msg = "";
if ($p2 !== null) {
if ($p2 instanceof Exception) {
$cause = $p2;
$msg = $p1;
}
} elseif ($p1 instanceof Exception) {
$cause = $p1;
} else {
$msg = $p1;
}
parent::__construct($msg);
if ($cause !== null) {
$this->cause = $cause;
$this->message .= " [wrapped: " . $cause->getMessage() ."]";
}
}
/**
* Gets the cause exception.
*
* @return Exception
*/
public function getCause() {
return $this->cause;
}
}

View file

@ -0,0 +1,538 @@
<?php
/*
* $Id: IntrospectionHelper.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/types/Reference.php';
include_once 'phing/types/Path.php';
include_once 'phing/util/StringHelper.php';
/**
* Helper class that collects the methods that a task or nested element
* holds to set attributes, create nested elements or hold PCDATA
* elements.
*
*<ul>
* <li><strong>SMART-UP INLINE DOCS</strong></li>
* <li><strong>POLISH-UP THIS CLASS</strong></li>
*</ul>
*
* @author Andreas Aderhold <andi@binarycloud.com>
* @author Hans Lellelid <hans@xmpl.org>
* @copyright © 2001,2002 THYRELL. All rights reserved
* @version $Revision: 905 $
* @package phing
*/
class IntrospectionHelper {
/**
* Holds the attribute setter methods.
*
* @var array string[]
*/
private $attributeSetters = array();
/**
* Holds methods to create nested elements.
*
* @var array string[]
*/
private $nestedCreators = array();
/**
* Holds methods to store configured nested elements.
*
* @var array string[]
*/
private $nestedStorers = array();
/**
* Map from attribute names to nested types.
*/
private $nestedTypes = array();
/**
* New idea in phing: any class can register certain
* keys -- e.g. "task.current_file" -- which can be used in
* task attributes, if supported. In the build XML these
* are referred to like this:
* <regexp pattern="\n" replace="%{task.current_file}"/>
* In the type/task a listener method must be defined:
* function setListeningReplace($slot) {}
* @var array string[]
*/
private $slotListeners = array();
/**
* The method to add PCDATA stuff.
*
* @var string Method name of the addText (redundant?) method, if class supports it :)
*/
private $methodAddText = null;
/**
* The Class that's been introspected.
*
* @var object
* @access private
*/
private $bean;
/**
* The cache of IntrospectionHelper classes instantiated by getHelper().
* @var array IntrospectionHelpers[]
*/
private static $helpers = array();
/**
* Factory method for helper objects.
*
* @param string $class The class to create a Helper for
*/
public static function getHelper($class) {
if (!isset(self::$helpers[$class])) {
self::$helpers[$class] = new IntrospectionHelper($class);
}
return self::$helpers[$class];
}
/**
* This function constructs a new introspection helper for a specific class.
*
* This method loads all methods for the specified class and categorizes them
* as setters, creators, slot listeners, etc. This way, the setAttribue() doesn't
* need to perform any introspection -- either the requested attribute setter/creator
* exists or it does not & a BuildException is thrown.
*
* @param string $bean The classname for this IH.
*/
function __construct($class) {
$this->bean = new ReflectionClass($class);
//$methods = get_class_methods($bean);
foreach($this->bean->getMethods() as $method) {
if ($method->isPublic()) {
// We're going to keep case-insensitive method names
// for as long as we're allowed :) It makes it much
// easier to map XML attributes to PHP class method names.
$name = strtolower($method->getName());
// There are a few "reserved" names that might look like attribute setters
// but should actually just be skipped. (Note: this means you can't ever
// have an attribute named "location" or "tasktype" or a nested element named "task".)
if ($name === "setlocation" || $name === "settasktype" || $name === "addtask") {
continue;
}
if ($name === "addtext") {
$this->methodAddText = $method;
} elseif (strpos($name, "setlistening") === 0) {
// Phing supports something unique called "RegisterSlots"
// These are dynamic values that use a basic slot system so that
// classes can register to listen to specific slots, and the value
// will always be grabbed from the slot (and never set in the project
// component). This is useful for things like tracking the current
// file being processed by a filter (e.g. AppendTask sets an append.current_file
// slot, which can be ready by the XSLTParam type.)
if (count($method->getParameters()) !== 1) {
throw new BuildException($method->getDeclaringClass()->getName()."::".$method->getName()."() must take exactly one parameter.");
}
$this->slotListeners[$name] = $method;
} elseif (strpos($name, "set") === 0) {
// A standard attribute setter.
if (count($method->getParameters()) !== 1) {
throw new BuildException($method->getDeclaringClass()->getName()."::".$method->getName()."() must take exactly one parameter.");
}
$this->attributeSetters[$name] = $method;
} elseif (strpos($name, "create") === 0) {
if (count($method->getParameters()) > 0) {
throw new BuildException($method->getDeclaringClass()->getName()."::".$method->getName()."() may not take any parameters.");
}
// Because PHP doesn't support return types, we are going to do
// two things here to guess return type:
// 1) parse comments for an explicit value
// 2) if that fails, assume that the part of the method after "create"
// is the name of the return type (in many cases it is not)
// This isn't super important -- i.e. we're not instantaiting classes
// based on this information. It's more just so that IntrospectionHelper
// can keep track of all the nested types -- and provide more helpful
// exception messages, etc.
preg_match('/@return[\s]+([\w]+)/', $method->getDocComment(), $matches);
if (!empty($matches[1]) && class_exists($matches[1], false)) {
$this->nestedTypes[$name] = $matches[1];
} else {
// assume that method createEquals() creates object of type "Equals"
// (that example would be false, of course)
$this->nestedTypes[$name] = $this->getPropertyName($name, "create");
}
$this->nestedCreators[$name] = $method;
} elseif (strpos($name, "addconfigured") === 0) {
// *must* use class hints if using addConfigured ...
// 1 param only
$params = $method->getParameters();
if (count($params) < 1) {
throw new BuildException($method->getDeclaringClass()->getName()."::".$method->getName()."() must take at least one parameter.");
}
if (count($params) > 1) {
$this->warn($method->getDeclaringClass()->getName()."::".$method->getName()."() takes more than one parameter. (IH only uses the first)");
}
$classname = null;
if (($hint = $params[0]->getClass()) !== null) {
$classname = $hint->getName();
}
if ($classname === null) {
throw new BuildException($method->getDeclaringClass()->getName()."::".$method->getName()."() method MUST use a class hint to indicate the class type of parameter.");
}
$this->nestedTypes[$name] = $classname;
$this->nestedStorers[$name] = $method;
} elseif (strpos($name, "add") === 0) {
// *must* use class hints if using add ...
// 1 param only
$params = $method->getParameters();
if (count($params) < 1) {
throw new BuildException($method->getDeclaringClass()->getName()."::".$method->getName()."() must take at least one parameter.");
}
if (count($params) > 1) {
$this->warn($method->getDeclaringClass()->getName()."::".$method->getName()."() takes more than one parameter. (IH only uses the first)");
}
$classname = null;
if (($hint = $params[0]->getClass()) !== null) {
$classname = $hint->getName();
}
// we don't use the classname here, but we need to make sure it exists before
// we later try to instantiate a non-existant class
if ($classname === null) {
throw new BuildException($method->getDeclaringClass()->getName()."::".$method->getName()."() method MUST use a class hint to indicate the class type of parameter.");
}
$this->nestedCreators[$name] = $method;
}
} // if $method->isPublic()
} // foreach
}
/** Sets the named attribute. */
function setAttribute(Project $project, $element, $attributeName, &$value) {
// we want to check whether the value we are setting looks like
// a slot-listener variable: %{task.current_file}
//
// slot-listener variables are not like properties, in that they cannot be mixed with
// other text values. The reason for this disparity is that properties are only
// set when first constructing objects from XML, whereas slot-listeners are always dynamic.
//
// This is made possible by PHP5 (objects automatically passed by reference) and PHP's loose
// typing.
if (StringHelper::isSlotVar($value)) {
$as = "setlistening" . strtolower($attributeName);
if (!isset($this->slotListeners[$as])) {
$msg = $this->getElementName($project, $element) . " doesn't support a slot-listening '$attributeName' attribute.";
throw new BuildException($msg);
}
$method = $this->slotListeners[$as];
$key = StringHelper::slotVar($value);
$value = Register::getSlot($key); // returns a RegisterSlot object which will hold current value of that register (accessible using getValue())
} else {
// Traditional value options
$as = "set".strtolower($attributeName);
if (!isset($this->attributeSetters[$as])) {
$msg = $this->getElementName($project, $element) . " doesn't support the '$attributeName' attribute.";
throw new BuildException($msg);
}
$method = $this->attributeSetters[$as];
if ($as == "setrefid") {
$value = new Reference($value);
} else {
// value is a string representation of a boolean type,
// convert it to primitive
if (StringHelper::isBoolean($value)) {
$value = StringHelper::booleanValue($value);
}
// does method expect a PhingFile object? if so, then
// pass a project-relative file.
$params = $method->getParameters();
$classname = null;
if (($hint = $params[0]->getClass()) !== null) {
$classname = $hint->getName();
}
// there should only be one param; we'll just assume ....
if ($classname !== null) {
switch(strtolower($classname)) {
case "phingfile":
$value = $project->resolveFile($value);
break;
case "path":
$value = new Path($project, $value);
break;
case "reference":
$value = new Reference($value);
break;
// any other object params we want to support should go here ...
}
} // if hint !== null
} // if not setrefid
} // if is slot-listener
try {
$project->log(" -calling setter ".$method->getDeclaringClass()->getName()."::".$method->getName()."()", Project::MSG_DEBUG);
$method->invoke($element, $value);
} catch(Exception $exc) {
throw new BuildException($exc);
}
}
/** Adds PCDATA areas.*/
function addText(Project $project, $element, $text) {
if ($this->methodAddText === null) {
$msg = $this->getElementName($project, $element)." doesn't support nested text data.";
throw new BuildException($msg);
}
try {
$method = $this->methodAddText;
$method->invoke($element, $text);
} catch (Exception $exc) {
throw new BuildException($exc);
}
}
/**
* Creates a named nested element.
*
* Valid creators can be in the form createFoo() or addFoo(Bar).
* @return object Returns the nested element.
* @throws BuildException
*/
function createElement(Project $project, $element, $elementName) {
$addMethod = "add".strtolower($elementName);
$createMethod = "create".strtolower($elementName);
$nestedElement = null;
if (isset($this->nestedCreators[$createMethod])) {
$method = $this->nestedCreators[$createMethod];
try { // try to invoke the creator method on object
$project->log(" -calling creator ".$method->getDeclaringClass()->getName()."::".$method->getName()."()", Project::MSG_DEBUG);
$nestedElement = $method->invoke($element);
} catch (Exception $exc) {
throw new BuildException($exc);
}
} elseif (isset($this->nestedCreators[$addMethod])) {
$method = $this->nestedCreators[$addMethod];
// project components must use class hints to support the add methods
try { // try to invoke the adder method on object
$project->log(" -calling adder ".$method->getDeclaringClass()->getName()."::".$method->getName()."()", Project::MSG_DEBUG);
// we've already assured that correct num of params
// exist and that method is using class hints
$params = $method->getParameters();
$classname = null;
if (($hint = $params[0]->getClass()) !== null) {
$classname = $hint->getName();
}
// create a new instance of the object and add it via $addMethod
$nestedElement = new $classname();
$method->invoke($element, $nestedElement);
} catch (Exception $exc) {
throw new BuildException($exc);
}
} else {
$msg = $this->getElementName($project, $element) . " doesn't support the '$elementName' creator/adder.";
throw new BuildException($msg);
}
if ($nestedElement instanceof ProjectComponent) {
$nestedElement->setProject($project);
}
return $nestedElement;
}
/**
* Creates a named nested element.
* @return void
* @throws BuildException
*/
function storeElement($project, $element, $child, $elementName = null) {
if ($elementName === null) {
return;
}
$storer = "addconfigured".strtolower($elementName);
if (isset($this->nestedStorers[$storer])) {
$method = $this->nestedStorers[$storer];
try {
$project->log(" -calling storer ".$method->getDeclaringClass()->getName()."::".$method->getName()."()", Project::MSG_DEBUG);
$method->invoke($element, $child);
} catch (Exception $exc) {
throw new BuildException($exc);
}
}
}
/** Does the introspected class support PCDATA? */
function supportsCharacters() {
return ($this->methodAddText !== null);
}
/** Return all attribues supported by the introspected class. */
function getAttributes() {
$attribs = array();
foreach (array_keys($this->attributeSetters) as $setter) {
$attribs[] =$this->getPropertyName($setter, "set");
}
return $attribs;
}
/** Return all nested elements supported by the introspected class. */
function getNestedElements() {
return $this->nestedTypes;
}
/**
* Get the the name for an element.
* When possible the full classnam (phing.tasks.system.PropertyTask) will
* be returned. If not available (loaded in taskdefs or typedefs) then the
* XML element name will be returned.
*
* @param Project $project
* @param object $element The Task or type element.
* @return string Fully qualified class name of element when possible.
*/
function getElementName(Project $project, $element) {
$taskdefs = $project->getTaskDefinitions();
$typedefs = $project->getDataTypeDefinitions();
// check if class of element is registered with project (tasks & types)
// most element types don't have a getTag() method
$elClass = get_class($element);
if (!in_array('getTag', get_class_methods($elClass))) {
// loop through taskdefs and typesdefs and see if the class name
// matches (case-insensitive) any of the classes in there
foreach(array_merge($taskdefs, $typedefs) as $elName => $class) {
if (0 === strcasecmp($elClass, StringHelper::unqualify($class))) {
return $class;
}
}
return "$elClass (unknown)";
} else {
// ->getTag() method does exist, so use it
$elName = $element->getTag();
if (isset($taskdefs[$elName])) {
return $taskdefs[$elName];
} elseif (isset($typedefs[$elName])) {
return $typedefs[$elName];
} else {
return "$elName (unknown)";
}
}
}
/** extract the name of a property from a method name - subtracting a given prefix. */
function getPropertyName($methodName, $prefix) {
$start = strlen($prefix);
return strtolower(substr($methodName, $start));
}
/**
* Prints warning message to screen if -debug was used.
*/
function warn($msg) {
if (Phing::getMsgOutputLevel() === Project::MSG_DEBUG) {
print("[IntrospectionHelper] " . $msg . "\n");
}
}
}

1371
3rd_party/php/phing/Phing.php vendored Normal file

File diff suppressed because it is too large Load diff

999
3rd_party/php/phing/Project.php vendored Normal file
View 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);
}
}

View file

@ -0,0 +1,70 @@
<?php
/*
* $Id: ProjectComponent.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>.
*/
/**
* Abstract class providing properties and methods common to all
* the project components
*
* @author Andreas Aderhold <andi@binarycloud.com>
* @author Hans Lellelid <hans@xmpl.org>
* @version $Revision: 905 $
* @package phing
*/
abstract class ProjectComponent {
/**
* Holds a reference to the project that a project component
* (a task, a target, etc.) belongs to
*
* @var Project A reference to the current project instance
*/
protected $project = null;
/**
* References the project to the current component.
*
* @param Project $project The reference to the current project
*/
public function setProject($project) {
$this->project = $project;
}
/**
* Returns a reference to current project
*
* @return Project Reference to current porject object
*/
public function getProject() {
return $this->project;
}
/**
* Logs a message with the given priority.
*
* @param string $msg The message to be logged.
* @param integer $level The message's priority at this message should have
*/
public function log($msg, $level = Project::MSG_INFO) {
if ($this->project !== null) {
$this->project->log($msg, $level);
}
}
}

View file

@ -0,0 +1,118 @@
<?php
/*
* $Id: RuntimeConfigurable.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>.
*/
/**
* Wrapper class that holds the attributes of a Task (or elements
* nested below that level) and takes care of configuring that element
* at runtime.
*
* <strong>SMART-UP INLINE DOCS</strong>
*
* @author Andreas Aderhold <andi@binarycloud.com>
* @author Hans Lellelid <hans@xmpl.org>
* @version $Revision: 905 $
* @package phing
*/
class RuntimeConfigurable {
private $elementTag = null;
private $children = array();
private $wrappedObject = null;
private $attributes = array();
private $characters = "";
/** @param proxy The element to wrap. */
function __construct($proxy, $elementTag) {
$this->wrappedObject = $proxy;
$this->elementTag = $elementTag;
}
function setProxy($proxy) {
$this->wrappedObject = $proxy;
}
/** Set's the attributes for the wrapped element. */
function setAttributes($attributes) {
$this->attributes = $attributes;
}
/** Returns the AttributeList of the wrapped element. */
function getAttributes() {
return $this->attributes;
}
/** Adds child elements to the wrapped element. */
function addChild(RuntimeConfigurable $child) {
$this->children[] = $child;
}
/** Returns the child with index */
function getChild($index) {
return $this->children[(int)$index];
}
/** Add characters from #PCDATA areas to the wrapped element. */
function addText($data) {
$this->characters .= (string) $data;
}
function getElementTag() {
return $this->elementTag;
}
/** Configure the wrapped element and all children. */
function maybeConfigure(Project $project) {
$id = null;
// DataType configured in ProjectConfigurator
// if ( is_a($this->wrappedObject, "DataType") )
// return;
if ($this->attributes || $this->characters) {
ProjectConfigurator::configure($this->wrappedObject, $this->attributes, $project);
if (isset($this->attributes["id"])) {
$id = $this->attributes["id"];
}
$this->attributes = null;
if ($this->characters) {
ProjectConfigurator::addText($project, $this->wrappedObject, (string) $this->characters);
$this->characters="";
}
if ($id !== null) {
$project->addReference($id, $this->wrappedObject);
}
}
if ( is_array($this->children) && !empty($this->children) ) {
// Configure all child of this object ...
foreach($this->children as $child) {
$child->maybeConfigure($project);
ProjectConfigurator::storeChild($project, $this->wrappedObject, $child->wrappedObject, strtolower($child->getElementTag()));
}
}
}
}

317
3rd_party/php/phing/Target.php vendored Normal file
View file

@ -0,0 +1,317 @@
<?php
/*
* $Id: Target.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/TaskContainer.php';
/**
* The Target component. Carries all required target data. Implements the
* abstract class {@link TaskContainer}
*
* @author Andreas Aderhold <andi@binarycloud.com>
* @copyright <EFBFBD> 2001,2002 THYRELL. All rights reserved
* @version $Revision: 905 $ $Date: 2010-10-05 18:28:03 +0200 (Tue, 05 Oct 2010) $
* @access public
* @see TaskContainer
* @package phing
*/
class Target implements TaskContainer {
/** name of target */
private $name;
/** dependencies */
private $dependencies = array();
/** holds objects of children of this target */
private $children = array();
/** the if cond. from xml */
private $ifCondition = "";
/** the unless cond. from xml */
private $unlessCondition = "";
/** description of this target */
private $description;
/** reference to project */
private $project;
/**
* References the project to the current component.
*
* @param Project The reference to the current project
*/
public function setProject(Project $project) {
$this->project = $project;
}
/**
* Returns reference to current project
*
* @return Project Reference to current porject object
*/
public function getProject() {
return $this->project;
}
/**
* Sets the target dependencies from xml
*
* @param string $depends Comma separated list of targetnames that depend on
* this target
* @throws BuildException
*/
public function setDepends($depends) {
// explode should be faster than strtok
$deps = explode(',', $depends);
for ($i=0, $size=count($deps); $i < $size; $i++) {
$trimmed = trim($deps[$i]);
if ($trimmed === "") {
throw new BuildException("Syntax Error: Depend attribute for target ".$this->getName()." is malformed.");
}
$this->addDependency($trimmed);
}
}
/**
* Adds a singular dependent target name to the list
*
* @param string The dependency target to add
* @access public
*/
public function addDependency($dependency) {
$this->dependencies[] = (string) $dependency;
}
/**
* Returns reference to indexed array of the dependencies this target has.
*
* @return array Referece to target dependencoes
*/
public function getDependencies() {
return $this->dependencies;
}
/**
* Sets the name of the target
*
* @param string Name of this target
*/
public function setName($name) {
$this->name = (string) $name;
}
/**
* Returns name of this target.
*
* @return string The name of the target
* @access public
*/
function getName() {
return (string) $this->name;
}
/**
* Adds a task element to the list of this targets child elements
*
* @param object The task object to add
* @access public
*/
function addTask(Task $task) {
$this->children[] = $task;
}
/**
* Adds a runtime configurable element to the list of this targets child
* elements.
*
* @param object The RuntimeConfigurabel object
* @access public
*/
function addDataType($rtc) {
$this->children[] = $rtc;
}
/**
* Returns an array of all tasks this target has as childrens.
*
* The task objects are copied here. Don't use this method to modify
* task objects.
*
* @return array Task[]
*/
public function getTasks() {
$tasks = array();
for ($i=0,$size=count($this->children); $i < $size; $i++) {
$tsk = $this->children[$i];
if ($tsk instanceof Task) {
// note: we're copying objects here!
$tasks[] = clone $tsk;
}
}
return $tasks;
}
/**
* Set the if-condition from the XML tag, if any. The property name given
* as parameter must be present so the if condition evaluates to true
*
* @param string The property name that has to be present
* @access public
*/
public function setIf($property) {
$this->ifCondition = ($property === null) ? "" : $property;
}
/**
* Set the unless-condition from the XML tag, if any. The property name
* given as parameter must be present so the unless condition evaluates
* to true
*
* @param string The property name that has to be present
* @access public
*/
public function setUnless($property) {
$this->unlessCondition = ($property === null) ? "" : $property;
}
/**
* Sets a textual description of this target.
*
* @param string The description text
*/
public function setDescription($description) {
if ($description !== null && strcmp($description, "") !== 0) {
$this->description = (string) $description;
} else {
$this->description = null;
}
}
/**
* Returns the description of this target.
*
* @return string The description text of this target
*/
public function getDescription() {
return $this->description;
}
/**
* Returns a string representation of this target. In our case it
* simply returns the target name field
*
* @return string The string representation of this target
*/
function toString() {
return (string) $this->name;
}
/**
* The entry point for this class. Does some checking, then processes and
* performs the tasks for this target.
*
*/
public function main() {
if ($this->testIfCondition() && $this->testUnlessCondition()) {
foreach($this->children as $o) {
if ($o instanceof Task) {
// child is a task
$o->perform();
} else {
// child is a RuntimeConfigurable
$o->maybeConfigure($this->project);
}
}
} elseif (!$this->testIfCondition()) {
$this->project->log("Skipped target '".$this->name."' because property '".$this->ifCondition."' not set.", Project::MSG_VERBOSE);
} else {
$this->project->log("Skipped target '".$this->name."' because property '".$this->unlessCondition."' set.", Project::MSG_VERBOSE);
}
}
/**
* Performs the tasks by calling the main method of this target that
* actually executes the tasks.
*
* This method is for ZE2 and used for proper exception handling of
* task exceptions.
*/
public function performTasks() {
try {// try to execute this target
$this->project->fireTargetStarted($this);
$this->main();
$this->project->fireTargetFinished($this, $null=null);
} catch (BuildException $exc) {
// log here and rethrow
$this->project->fireTargetFinished($this, $exc);
throw $exc;
}
}
/**
* Tests if the property set in ifConfiditon exists.
*
* @return boolean <code>true</code> if the property specified
* in <code>$this->ifCondition</code> exists;
* <code>false</code> otherwise
*/
private function testIfCondition() {
if ($this->ifCondition === "") {
return true;
}
$properties = explode(",", $this->ifCondition);
$result = true;
foreach ($properties as $property) {
$test = ProjectConfigurator::replaceProperties($this->getProject(), $property, $this->project->getProperties());
$result = $result && ($this->project->getProperty($test) !== null);
}
return $result;
}
/**
* Tests if the property set in unlessCondition exists.
*
* @return boolean <code>true</code> if the property specified
* in <code>$this->unlessCondition</code> exists;
* <code>false</code> otherwise
*/
private function testUnlessCondition() {
if ($this->unlessCondition === "") {
return true;
}
$properties = explode(",", $this->unlessCondition);
$result = true;
foreach ($properties as $property) {
$test = ProjectConfigurator::replaceProperties($this->getProject(), $property, $this->project->getProperties());
$result = $result && ($this->project->getProperty($test) === null);
}
return $result;
}
}

265
3rd_party/php/phing/Task.php vendored Normal file
View file

@ -0,0 +1,265 @@
<?php
/*
* $Id: Task.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>.
*/
require_once 'phing/ProjectComponent.php';
include_once 'phing/RuntimeConfigurable.php';
/**
* The base class for all Tasks.
*
* Use {@link Project#createTask} to register a new Task.
*
* @author Andreas Aderhold <andi@binarycloud.com>
* @copyright <EFBFBD> 2001,2002 THYRELL. All rights reserved
* @version $Revision: 905 $
* @see Project#createTask()
* @package phing
*/
abstract class Task extends ProjectComponent {
/**
* @var Target owning Target object
*/
protected $target;
/**
* @var string description of the task
*/
protected $description;
/**
* @var string internal taskname (req)
*/
protected $taskType;
/**
* @var string Taskname for logger
*/
protected $taskName;
/**
* @var Location stored buildfile location
*/
protected $location;
/**
* @var RuntimeConfigurable wrapper of the task
*/
protected $wrapper;
/**
* Sets the owning target this task belongs to.
*
* @param Target Reference to owning target
*/
public function setOwningTarget(Target $target) {
$this->target = $target;
}
/**
* Returns the owning target of this task.
*
* @return Target The target object that owns this task
*/
public function getOwningTarget() {
return $this->target;
}
/**
* Returns the name of task, used only for log messages
*
* @return string Name of this task
*/
public function getTaskName() {
if ($this->taskName === null) {
// if no task name is set, then it's possible
// this task was created from within another task. We don't
// therefore know the XML tag name for this task, so we'll just
// use the class name stripped of "task" suffix. This is only
// for log messages, so we don't have to worry much about accuracy.
return preg_replace('/task$/i', '', get_class($this));
}
return $this->taskName;
}
/**
* Sets the name of this task for log messages
*
* @return string A string representing the name of this task for log
*/
public function setTaskName($name) {
$this->taskName = (string) $name;
}
/**
* Returns the name of the task under which it was invoked,
* usually the XML tagname
*
* @return string The type of this task (XML Tag)
*/
public function getTaskType() {
return $this->taskType;
}
/**
* Sets the type of the task. Usually this is the name of the XML tag
*
* @param string The type of this task (XML Tag)
*/
public function setTaskType($name) {
$this->taskType = (string) $name;
}
/**
* Returns a name
*
*/
protected function getRegisterSlot($slotName) {
return Register::getSlot('task.' . $this->getTaskName() . '.' . $slotName);
}
/**
* Provides a project level log event to the task.
*
* @param string The message to log
* @param integer The priority of the message
* @see BuildEvent
* @see BuildListener
*/
function log($msg, $level = Project::MSG_INFO) {
$this->project->logObject($this, $msg, $level);
}
/**
* Sets a textual description of the task
*
* @param string $desc The text describing the task
*/
public function setDescription($desc) {
$this->description = $desc;
}
/**
* Returns the textual description of the task
*
* @return string The text description of the task
*/
public function getDescription() {
return $this->description;
}
/**
* Called by the parser to let the task initialize properly.
* Should throw a BuildException if something goes wrong with the build
*
* This is abstract here, but may not be overloaded by subclasses.
*
* @throws BuildException
*/
public function init() {
}
/**
* Called by the project to let the task do it's work. This method may be
* called more than once, if the task is invoked more than once. For
* example, if target1 and target2 both depend on target3, then running
* <em>phing target1 target2</em> will run all tasks in target3 twice.
*
* Should throw a BuildException if someting goes wrong with the build
*
* This is abstract here. Must be overloaded by real tasks.
*/
abstract public function main();
/**
* Returns the location within the buildfile this task occurs. Used
* by {@link BuildException} to give detailed error messages.
*
* @return Location The location object describing the position of this
* task within the buildfile.
*/
function getLocation() {
return $this->location;
}
/**
* Sets the location within the buildfile this task occurs. Called by
* the parser to set location information.
*
* @param Location $location The location object describing the position of this
* task within the buildfile.
*/
function setLocation(Location $location) {
$this->location = $location;
}
/**
* Returns the wrapper object for runtime configuration
*
* @return RuntimeConfigurable The wrapper object used by this task
*/
function getRuntimeConfigurableWrapper() {
if ($this->wrapper === null) {
$this->wrapper = new RuntimeConfigurable($this, $this->getTaskName());
}
return $this->wrapper;
}
/**
* Sets the wrapper object this task should use for runtime
* configurable elements.
*
* @param RuntimeConfigurable $wrapper The wrapper object this task should use
*/
function setRuntimeConfigurableWrapper(RuntimeConfigurable $wrapper) {
$this->wrapper = $wrapper;
}
/**
* Configure this task if it hasn't been done already.
*/
public function maybeConfigure() {
if ($this->wrapper !== null) {
$this->wrapper->maybeConfigure($this->project);
}
}
/**
* Perfrom this task
*/
public function perform() {
try { // try executing task
$this->project->fireTaskStarted($this);
$this->maybeConfigure();
$this->main();
$this->project->fireTaskFinished($this, $null=null);
} catch (Exception $exc) {
if ($exc instanceof BuildException) {
if ($exc->getLocation() === null) {
$exc->setLocation($this->getLocation());
}
}
$this->project->fireTaskFinished($this, $exc);
throw $exc;
}
}
}

84
3rd_party/php/phing/TaskAdapter.php vendored Normal file
View file

@ -0,0 +1,84 @@
<?php
/*
* $Id: TaskAdapter.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>.
*/
require_once 'phing/Task.php';
/**
* Use introspection to "adapt" an arbitrary ( not extending Task, but with
* similar patterns).
*
* @author Andreas Aderhold <andi@binarycloud.com>
* @copyright © 2001,2002 THYRELL. All rights reserved
* @version $Revision: 905 $
* @package phing
*/
class TaskAdapter extends Task {
/** target object */
private $proxy;
/**
* Main entry point.
* @return void
*/
function main() {
if (method_exists($this->proxy, "setProject")) {
try { // try to set project
$this->proxy->setProject($this->project);
} catch (Exception $ex) {
$this->log("Error setting project in " . get_class($this->proxy) . Project::MSG_ERR);
throw new BuildException($ex);
}
} else {
throw new Exception("Error setting project in class " . get_class($this->proxy));
}
if (method_exists($this->proxy, "main")) {
try { //try to call main
$this->proxy->main($this->project);
} catch (Exception $ex) {
$this->log("Error in " . get_class($this->proxy), Project::MSG_ERR);
throw new BuildException($ex->getMessage());
}
} else {
throw new BuildException("Your task-like class '" . get_class($this->proxy) ."' does not have a main() method");
}
}
/**
* Set the target object.
* @param object $o
* @return void
*/
function setProxy($o) {
$this->proxy = $o;
}
/**
* Gets the target object.
* @return object
*/
function getProxy() {
return $this->proxy;
}
}

42
3rd_party/php/phing/TaskContainer.php vendored Normal file
View file

@ -0,0 +1,42 @@
<?php
/*
* $Id: TaskContainer.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>.
*/
/**
* Abstract interface for objects which can contain tasks (targets)
* Used to check if a class can contain tasks (via instanceof)
*
* @author Andreas Aderhold <andi@binarycloud.com>
* @copyright © 2001,2002 THYRELL. All rights reserved
* @version $Revision: 905 $ $Date: 2010-10-05 18:28:03 +0200 (Tue, 05 Oct 2010) $
* @access public
* @package phing
*/
interface TaskContainer {
/**
* Adds a task to this task container. Must be implemented
* by derived class
*
* @param object The task to be added to the container
* @access public
*/
function addTask(Task $task);
}

215
3rd_party/php/phing/UnknownElement.php vendored Normal file
View file

@ -0,0 +1,215 @@
<?php
/*
* $Id: UnknownElement.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>.
*/
require_once 'phing/Task.php';
/**
* Wrapper class that holds all information necessary to create a task
* that did not exist when Phing started.
*
* <em> This has something to do with phing encountering an task XML element
* it is not aware of at start time. This is a situation where special steps
* need to be taken so that the element is then known.</em>
*
* @author Andreas Aderhold <andi@binarycloud.com>
* @author Hans Lellelid <hans@xmpl.org>
* @version $Revision: 905 $
* @package phing
*/
class UnknownElement extends Task {
private $elementName;
private $realThing;
private $children = array();
/**
* Constructs a UnknownElement object
*
* @param string The XML element name that is unknown
* @access public
*/
function __construct($elementName) {
$this->elementName = (string) $elementName;
}
/**
* Return the XML element name that this <code>UnnownElement</code>
* handles.
*
* @return string The XML element name that is unknown
*/
public function getTag() {
return (string) $this->elementName;
}
/**
* Tries to configure the unknown element
*
* @throws BuildException if the element can not be configured
*/
public function maybeConfigure() {
$this->realThing = $this->makeObject($this, $this->wrapper);
$this->wrapper->setProxy($this->realThing);
if ($this->realThing instanceof Task) {
$this->realThing->setRuntimeConfigurableWrapper($this->wrapper);
}
$this->handleChildren($this->realThing, $this->wrapper);
$this->wrapper->maybeConfigure($this->getProject());
}
/**
* Called when the real task has been configured for the first time.
*
* @throws BuildException if the task can not be created
*/
public function main() {
if ($this->realThing === null) {
// plain impossible to get here, maybeConfigure should
// have thrown an exception.
throw new BuildException("Should not be executing UnknownElement::main() -- task/type: {$this->elementName}");
}
if ($this->realThing instanceof Task) {
$this->realThing->main();
}
}
/**
* Add a child element to the unknown element
*
* @param object The object representing the child element
*/
public function addChild(UnknownElement $child) {
$this->children[] = $child;
}
/**
* Handle child elemets of the unknown element, if any.
*
* @param ProjectComponent The parent object the unkown element belongs to
* @param object The parent wrapper object
*/
function handleChildren(ProjectComponent $parent, $parentWrapper) {
if ($parent instanceof TaskAdapter) {
$parent = $parent->getProxy();
}
$parentClass = get_class($parent);
$ih = IntrospectionHelper::getHelper($parentClass);
for ($i=0, $childrenCount=count($this->children); $i < $childrenCount; $i++) {
$childWrapper = $parentWrapper->getChild($i);
$child = $this->children[$i];
$realChild = null;
if ($parent instanceof TaskContainer) {
$realChild = $this->makeTask($child, $childWrapper, false);
$parent->addTask($realChild);
} else {
$project = $this->project === null ? $parent->project : $this->project;
$realChild = $ih->createElement($project, $parent, $child->getTag());
}
$childWrapper->setProxy($realChild);
if ($realChild instanceof Task) {
$realChild->setRuntimeConfigurableWrapper($childWrapper);
}
if ($realChild instanceof ProjectComponent) {
$child->handleChildren($realChild, $childWrapper);
}
if ($realChild instanceof Task) {
$realChild->maybeConfigure();
}
}
}
/**
* Creates a named task or data type. If the real object is a task,
* it is configured up to the init() stage.
*
* @param UnknownElement $ue The unknown element to create the real object for.
* Must not be <code>null</code>.
* @param RuntimeConfigurable $w Ignored in this implementation.
* @return object The Task or DataType represented by the given unknown element.
*/
protected function makeObject(UnknownElement $ue, RuntimeConfigurable $w) {
$o = $this->makeTask($ue, $w, true);
if ($o === null) {
$o = $this->project->createDataType($ue->getTag());
}
if ($o === null) {
throw new BuildException("Could not create task/type: '".$ue->getTag()."'. Make sure that this class has been declared using taskdef / typedef.");
}
return $o;
}
/**
* Create a named task and configure it up to the init() stage.
*
* @param UnknownElement $ue The unknwon element to create a task from
* @param RuntimeConfigurable $w The wrapper object
* @param boolean $onTopLevel Whether to treat this task as if it is top-level.
* @return Task The freshly created task
*/
protected function makeTask(UnknownElement $ue, RuntimeConfigurable $w, $onTopLevel = false) {
$task = $this->project->createTask($ue->getTag());
if ($task === null) {
if (!$onTopLevel) {
throw new BuildException("Could not create task of type: '".$this->elementName."'. Make sure that this class has been declared using taskdef.");
}
return null;
}
// used to set the location within the xmlfile so that exceptions can
// give detailed messages
$task->setLocation($this->getLocation());
$attrs = $w->getAttributes();
if (isset($attrs['id'])) {
$this->project->addReference($attrs['id'], $task);
}
// UnknownElement always has an associated target
$task->setOwningTarget($this->target);
$task->init();
return $task;
}
/**
* Get the name of the task to use in logging messages.
*
* @return string The task's name
*/
function getTaskName() {
return $this->realThing === null ? parent::getTaskName() : $this->realThing->getTaskName();
}
}

View file

@ -0,0 +1,157 @@
<?php
/*
* $Id: BaseFilterReader.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/FilterReader.php';
include_once 'phing/system/io/StringReader.php';
/**
* Base class for core filter readers.
*
* @author <a href="mailto:yl@seasonfive.com">Yannick Lecaillez</a>
* @version $Revision: 905 $ $Date: 2010-10-05 18:28:03 +0200 (Tue, 05 Oct 2010) $
* @access public
* @see FilterReader
* @package phing.filters
*/
class BaseFilterReader extends FilterReader {
/** Have the parameters passed been interpreted? */
protected $initialized = false;
/** The Phing project this filter is part of. */
protected $project = null;
/**
* Constructor used by Phing's introspection mechanism.
* The original filter reader is only used for chaining
* purposes, never for filtering purposes (and indeed
* it would be useless for filtering purposes, as it has
* no real data to filter). ChainedReaderHelper uses
* this placeholder instance to create a chain of real filters.
*
* @param Reader $in
*/
function __construct($in = null) {
if ($in === null) {
$dummy = "";
$in = new StringReader($dummy);
}
parent::__construct($in);
}
/**
* Returns the initialized status.
*
* @return boolean whether or not the filter is initialized
*/
function getInitialized() {
return $this->initialized;
}
/**
* Sets the initialized status.
*
* @param boolean $initialized Whether or not the filter is initialized.
*/
function setInitialized($initialized) {
$this->initialized = (boolean) $initialized;
}
/**
* Sets the project to work with.
*
* @param object $project The project this filter is part of.
* Should not be <code>null</code>.
*/
function setProject(Project $project) {
// type check, error must never occur, bad code of it does
$this->project = $project;
}
/**
* Returns the project this filter is part of.
*
* @return object The project this filter is part of
*/
function getProject() {
return $this->project;
}
/**
* Reads characters.
*
* @param off Offset at which to start storing characters.
* @param len Maximum number of characters to read.
*
* @return Characters read, or -1 if the end of the stream
* has been reached
*
* @throws IOException If an I/O error occurs
*/
function read($len = null) {
return $this->in->read($len);
}
/**
* Reads a line of text ending with '\n' (or until the end of the stream).
* The returned String retains the '\n'.
*
* @return the line read, or <code>null</code> if the end of the
stream has already been reached
*
* @throws IOException if the underlying reader throws one during
* reading
*/
function readLine() {
$line = null;
while ( ($ch = $this->in->read(1)) !== -1 ) {
$line .= $ch;
if ( $ch === "\n" )
break;
}
return $line;
}
/**
* Returns whether the end of file has been reached with input stream.
* @return boolean
*/
function eof() {
return $this->in->eof();
}
/**
* Convenience method to support logging in filters.
* @param string $msg Message to log.
* @param int $level Priority level.
*/
function log($msg, $level = Project::MSG_INFO) {
if ($this->project !== null) {
$this->project->log("[filter:".get_class($this)."] ".$msg, $level);
}
}
}

View file

@ -0,0 +1,69 @@
<?php
/*
* $Id: BaseParamFilterReader.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/filters/BaseFilterReader.php';
include_once 'phing/types/Parameterizable.php';
include_once 'phing/types/Parameter.php';
/**
* Base class for core filter readers.
*
* @author <a href="mailto:yl@seasonfive.com">Yannick Lecaillez</a>
* @copyright © 2003 seasonfive. All rights reserved
* @version $Revision: 905 $ $Date: 2010-10-05 18:28:03 +0200 (Tue, 05 Oct 2010) $
* @access public
* @see FilterReader
* @package phing.filters
*/
class BaseParamFilterReader extends BaseFilterReader implements Parameterizable {
/** The passed in parameter array. */
protected $_parameters = array();
/*
* Sets the parameters used by this filter, and sets
* the filter to an uninitialized status.
*
* @param array Array of parameters to be used by this filter.
* Should not be <code>null</code>.
*/
function setParameters($parameters) {
// type check, error must never occur, bad code of it does
if ( !is_array($parameters) ) {
throw new Exception("Expected parameters array got something else");
}
$this->_parameters = $parameters;
$this->setInitialized(false);
}
/*
* Returns the parameters to be used by this filter.
*
* @return the parameters to be used by this filter
*/
function &getParameters() {
return $this->_parameters;
}
}

View file

@ -0,0 +1,43 @@
<?php
/*
* $Id: ChainableReader.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>.
*/
/**
* Interface indicating that a reader may be chained to another one.
*
* @author Magesh Umasankar
* @package phing.filters
*/
interface ChainableReader {
/**
* Returns a reader with the same configuration as this one,
* but filtering input from the specified reader.
*
* @param Reader $rdr the reader which the returned reader should be filtering
*
* @return Reader A reader with the same configuration as this one, but
* filtering input from the specified reader
*/
public function chain(Reader $rdr);
}

View file

@ -0,0 +1,82 @@
<?php
/*
* $Id: ExpandProperties.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>.
*/
require_once 'phing/filters/BaseFilterReader.php';
include_once 'phing/filters/ChainableReader.php';
/**
* Expands Phing Properties, if any, in the data.
* <p>
* Example:<br>
* <pre><expandproperties/></pre>
* Or:
* <pre><filterreader classname="phing.filters.ExpandProperties'/></pre>
*
* @author Yannick Lecaillez <yl@seasonfive.com>
* @author Hans Lellelid <hans@xmpl.org>
* @version $Revision: 905 $
* @see BaseFilterReader
* @package phing.filters
*/
class ExpandProperties extends BaseFilterReader implements ChainableReader {
/**
* Returns the filtered stream.
* The original stream is first read in fully, and the Phing properties are expanded.
*
* @return mixed the filtered stream, or -1 if the end of the resulting stream has been reached.
*
* @exception IOException if the underlying stream throws an IOException
* during reading
*/
function read($len = null) {
$buffer = $this->in->read($len);
if($buffer === -1) {
return -1;
}
$project = $this->getProject();
$buffer = ProjectConfigurator::replaceProperties($project, $buffer, $project->getProperties());
return $buffer;
}
/**
* Creates a new ExpandProperties filter using the passed in
* Reader for instantiation.
*
* @param object A Reader object providing the underlying stream.
* Must not be <code>null</code>.
*
* @return object A new filter based on this configuration, but filtering
* the specified reader
*/
function chain(Reader $reader) {
$newFilter = new ExpandProperties($reader);
$newFilter->setProject($this->getProject());
return $newFilter;
}
}

View file

@ -0,0 +1,161 @@
<?php
/*
* $Id: HeadFilter.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/filters/BaseParamFilterReader.php';
include_once 'phing/filters/ChainableReader.php';
/**
* Reads the first <code>n</code> lines of a stream.
* (Default is first 10 lines.)
* <p>
* Example:
* <pre><headfilter lines="3"/></pre>
* Or:
* <pre><filterreader classname="phing.filters.HeadFilter">
* <param name="lines" value="3"/>
* </filterreader></pre>
*
* @author <a href="mailto:yl@seasonfive.com">Yannick Lecaillez</a>
* @author hans lellelid, hans@velum.net
* @version $Revision: 905 $ $Date: 2010-10-05 18:28:03 +0200 (Tue, 05 Oct 2010) $
* @access public
* @see FilterReader
* @package phing.filters
*/
class HeadFilter extends BaseParamFilterReader implements ChainableReader {
/**
* Parameter name for the number of lines to be returned.
*/
const LINES_KEY = "lines";
/**
* Number of lines currently read in.
* @var integer
*/
private $_linesRead = 0;
/**
* Number of lines to be returned in the filtered stream.
* @var integer
*/
private $_lines = 10;
/**
* Returns first n lines of stream.
* @return the resulting stream, or -1
* if the end of the resulting stream has been reached
*
* @exception IOException if the underlying stream throws an IOException
* during reading
*/
function read($len = null) {
if ( !$this->getInitialized() ) {
$this->_initialize();
$this->setInitialized(true);
}
// note, if buffer contains fewer lines than
// $this->_lines this code will not work.
if($this->_linesRead < $this->_lines) {
$buffer = $this->in->read($len);
if($buffer === -1) {
return -1;
}
// now grab first X lines from buffer
$lines = explode("\n", $buffer);
$linesCount = count($lines);
// must account for possibility that the num lines requested could
// involve more than one buffer read.
$len = ($linesCount > $this->_lines ? $this->_lines - $this->_linesRead : $linesCount);
$filtered_buffer = implode("\n", array_slice($lines, 0, $len) );
$this->_linesRead += $len;
return $filtered_buffer;
}
return -1; // EOF, since the file is "finished" as far as subsequent filters are concerned.
}
/**
* Sets the number of lines to be returned in the filtered stream.
*
* @param integer $lines the number of lines to be returned in the filtered stream.
*/
function setLines($lines) {
$this->_lines = (int) $lines;
}
/**
* Returns the number of lines to be returned in the filtered stream.
*
* @return integer The number of lines to be returned in the filtered stream.
*/
function getLines() {
return $this->_lines;
}
/**
* Creates a new HeadFilter using the passed in
* Reader for instantiation.
*
* @param object A Reader object providing the underlying stream.
* Must not be <code>null</code>.
*
* @return object A new filter based on this configuration, but filtering
* the specified reader.
*/
function chain(Reader $reader) {
$newFilter = new HeadFilter($reader);
$newFilter->setLines($this->getLines());
$newFilter->setInitialized(true);
$newFilter->setProject($this->getProject());
return $newFilter;
}
/**
* Scans the parameters list for the "lines" parameter and uses
* it to set the number of lines to be returned in the filtered stream.
*/
private function _initialize() {
$params = $this->getParameters();
if ( $params !== null ) {
for($i = 0, $_i=count($params) ; $i < $_i; $i++) {
if ( self::LINES_KEY == $params[$i]->getName() ) {
$this->_lines = (int) $params[$i]->getValue();
break;
}
}
}
}
}

View file

@ -0,0 +1,260 @@
<?php
/*
* $Id: LineContains.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/filters/BaseParamFilterReader.php';
include_once 'phing/filters/BaseFilterReader.php';
include_once 'phing/filters/ChainableReader.php';
/**
* Filter which includes only those lines that contain all the user-specified
* strings.
*
* Example:
*
* <pre><linecontains>
* <contains value="foo">
* <contains value="bar">
* </linecontains></pre>
*
* Or:
*
* <pre><filterreader classname="phing.filters.LineContains">
* <param type="contains" value="foo"/>
* <param type="contains" value="bar"/>
* </filterreader></pre>
*
* This will include only those lines that contain <code>foo</code> and
* <code>bar</code>.
*
* @author Yannick Lecaillez <yl@seasonfive.com>
* @author Hans Lellelid <hans@velum.net>
* @version $Revision: 905 $
* @see PhingFilterReader
* @package phing.filters
*/
class LineContains extends BaseParamFilterReader implements ChainableReader {
/**
* The parameter name for the string to match on.
* @var string
*/
const CONTAINS_KEY = "contains";
/**
* Array of Contains objects.
* @var array
*/
private $_contains = array();
/**
* [Deprecated]
* @var string
*/
private $_line = null;
/**
* Returns all lines in a buffer that contain specified strings.
* @return mixed buffer, -1 on EOF
*/
function read($len = null) {
if ( !$this->getInitialized() ) {
$this->_initialize();
$this->setInitialized(true);
}
$buffer = $this->in->read($len);
if ($buffer === -1) {
return -1;
}
$lines = explode("\n", $buffer);
$matched = array();
$containsSize = count($this->_contains);
foreach($lines as $line) {
for($i = 0 ; $i < $containsSize ; $i++) {
$containsStr = $this->_contains[$i]->getValue();
if ( strstr($line, $containsStr) === false ) {
$line = null;
break;
}
}
if($line !== null) {
$matched[] = $line;
}
}
$filtered_buffer = implode("\n", $matched);
return $filtered_buffer;
}
/**
* [Deprecated. For reference only, used to be read() method.]
* Returns the next character in the filtered stream, only including
* lines from the original stream which contain all of the specified words.
*
* @return the next character in the resulting stream, or -1
* if the end of the resulting stream has been reached
*
* @exception IOException if the underlying stream throws an IOException
* during reading
*/
function readChar() {
if ( !$this->getInitialized() ) {
$this->_initialize();
$this->setInitialized(true);
}
$ch = -1;
if ( $this->_line !== null ) {
$ch = substr($this->_line, 0, 1);
if ( strlen($this->_line) === 1 )
$this->_line = null;
else
$this->_line = substr($this->_line, 1);
} else {
$this->_line = $this->readLine();
if ( $this->_line === null ) {
$ch = -1;
} else {
$containsSize = count($this->_contains);
for($i = 0 ; $i < $containsSize ; $i++) {
$containsStr = $this->_contains[$i]->getValue();
if ( strstr($this->_line, $containsStr) === false ) {
$this->_line = null;
break;
}
}
return $this->readChar();
}
}
return $ch;
}
/**
* Adds a <code><contains></code> nested element.
*
* @return Contains The <code>contains</code> element added.
* Must not be <code>null</code>.
*/
function createContains() {
$num = array_push($this->_contains, new Contains());
return $this->_contains[$num-1];
}
/**
* Sets the array of words which must be contained within a line read
* from the original stream in order for it to match this filter.
*
* @param array $contains An array of words which must be contained
* within a line in order for it to match in this filter.
* Must not be <code>null<code>.
*/
function setContains($contains) {
// type check, error must never occur, bad code of it does
if ( !is_array($contains) ) {
throw new Exception("Excpected array got something else");
}
$this->_contains = $contains;
}
/**
* Returns the vector of words which must be contained within a line read
* from the original stream in order for it to match this filter.
*
* @return array The array of words which must be contained within a line read
* from the original stream in order for it to match this filter. The
* returned object is "live" - in other words, changes made to the
* returned object are mirrored in the filter.
*/
function getContains() {
return $this->_contains;
}
/**
* Creates a new LineContains using the passed in
* Reader for instantiation.
*
* @param object A Reader object providing the underlying stream.
* Must not be <code>null</code>.
*
* @return object A new filter based on this configuration, but filtering
* the specified reader
*/
function chain(Reader $reader) {
$newFilter = new LineContains($reader);
$newFilter->setContains($this->getContains());
$newFilter->setInitialized(true);
$newFilter->setProject($this->getProject());
return $newFilter;
}
/**
* Parses the parameters to add user-defined contains strings.
*/
private function _initialize() {
$params = $this->getParameters();
if ( $params !== null ) {
foreach($params as $param) {
if ( self::CONTAINS_KEY == $param->getType() ) {
$cont = new Contains();
$cont->setValue($param->getValue());
array_push($this->_contains, $cont);
break; // because we only support a single contains
}
}
}
}
}
/**
* Holds a contains element.
*
* @package phing.filters
*/
class Contains {
/**
* @var string
*/
private $_value;
/**
* Set 'contains' value.
* @param string $contains
*/
function setValue($contains) {
$this->_value = (string) $contains;
}
/**
* Returns 'contains' value.
* @return string
*/
function getValue() {
return $this->_value;
}
}

View file

@ -0,0 +1,179 @@
<?php
/*
* $Id: LineContainsRegexp.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/filters/BaseParamFilterReader.php';
include_once 'phing/types/RegularExpression.php';
include_once 'phing/filters/ChainableReader.php';
/**
* Filter which includes only those lines that contain the user-specified
* regular expression matching strings.
*
* Example:
* <pre><linecontainsregexp>
* <regexp pattern="foo*">
* </linecontainsregexp></pre>
*
* Or:
*
* <pre><filterreader classname="phing.filters.LineContainsRegExp">
* <param type="regexp" value="foo*"/>
* </filterreader></pre>
*
* This will fetch all those lines that contain the pattern <code>foo</code>
*
* @author Yannick Lecaillez <yl@seasonfive.com>
* @author Hans Lellelid <hans@xmpl.org>
* @version $Revision: 905 $
* @see FilterReader
* @package phing.filters
*/
class LineContainsRegexp extends BaseParamFilterReader implements ChainableReader {
/**
* Parameter name for regular expression.
* @var string
*/
const REGEXP_KEY = "regexp";
/**
* Regular expressions that are applied against lines.
* @var array
*/
private $_regexps = array();
/**
* Returns all lines in a buffer that contain specified strings.
* @return mixed buffer, -1 on EOF
*/
function read($len = null) {
if ( !$this->getInitialized() ) {
$this->_initialize();
$this->setInitialized(true);
}
$buffer = $this->in->read($len);
if ($buffer === -1) {
return -1;
}
$lines = explode("\n", $buffer);
$matched = array();
$regexpsSize = count($this->_regexps);
foreach($lines as $line) {
for($i = 0 ; $i<$regexpsSize ; $i++) {
$regexp = $this->_regexps[$i];
$re = $regexp->getRegexp($this->getProject());
$matches = $re->matches($line);
if ( !$matches ) {
$line = null;
break;
}
}
if($line !== null) {
$matched[] = $line;
}
}
$filtered_buffer = implode("\n", $matched);
return $filtered_buffer;
}
/**
* Adds a <code>regexp</code> element.
*
* @return object regExp The <code>regexp</code> element added.
*/
function createRegexp() {
$num = array_push($this->_regexps, new RegularExpression());
return $this->_regexps[$num-1];
}
/**
* Sets the vector of regular expressions which must be contained within
* a line read from the original stream in order for it to match this
* filter.
*
* @param regexps An array of regular expressions which must be contained
* within a line in order for it to match in this filter. Must not be
* <code>null</code>.
*/
function setRegexps($regexps) {
// type check, error must never occur, bad code of it does
if ( !is_array($regexps) ) {
throw new Exception("Excpected an 'array', got something else");
}
$this->_regexps = $regexps;
}
/**
* Returns the array of regular expressions which must be contained within
* a line read from the original stream in order for it to match this
* filter.
*
* @return array The array of regular expressions which must be contained within
* a line read from the original stream in order for it to match this
* filter. The returned object is "live" - in other words, changes made to
* the returned object are mirrored in the filter.
*/
function getRegexps() {
return $this->_regexps;
}
/**
* Creates a new LineContainsRegExp using the passed in
* Reader for instantiation.
*
* @param object A Reader object providing the underlying stream.
* Must not be <code>null</code>.
*
* @return object A new filter based on this configuration, but filtering
* the specified reader
*/
function chain(Reader $reader) {
$newFilter = new LineContainsRegExp($reader);
$newFilter->setRegexps($this->getRegexps());
$newFilter->setInitialized(true);
$newFilter->setProject($this->getProject());
return $newFilter;
}
/**
* Parses parameters to add user defined regular expressions.
*/
private function _initialize() {
$params = $this->getParameters();
if ( $params !== null ) {
for($i = 0 ; $i<count($params) ; $i++) {
if ( self::REGEXP_KEY === $params[$i]->getType() ) {
$pattern = $params[$i]->getValue();
$regexp = new RegularExpression();
$regexp->setPattern($pattern);
array_push($this->_regexps, $regexp);
}
}
}
}
}

View file

@ -0,0 +1,142 @@
<?php
/*
* $Id: PrefixLines.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/filters/BaseParamFilterReader.php';
include_once 'phing/filters/ChainableReader.php';
/**
* Attaches a prefix to every line.
*
* Example:
* <pre><prefixlines prefix="Foo"/></pre>
*
* Or:
*
* <pre><filterreader classname="phing.filters.PrefixLines">
* <param name="prefix" value="Foo"/>
* </filterreader></pre>
*
* @author <a href="mailto:yl@seasonfive.com">Yannick Lecaillez</a>
* @author hans lellelid, hans@velum.net
* @version $Revision: 905 $ $Date: 2010-10-05 18:28:03 +0200 (Tue, 05 Oct 2010) $
* @access public
* @see FilterReader
* @package phing.filters
*/
class PrefixLines extends BaseParamFilterReader implements ChainableReader {
/**
* Parameter name for the prefix.
* @var string
*/
const PREFIX_KEY = "lines";
/**
* The prefix to be used.
* @var string
*/
private $_prefix = null;
/**
* Adds a prefix to each line of input stream and returns resulting stream.
*
* @return mixed buffer, -1 on EOF
*/
function read($len = null) {
if ( !$this->getInitialized() ) {
$this->_initialize();
$this->setInitialized(true);
}
$buffer = $this->in->read($len);
if ($buffer === -1) {
return -1;
}
$lines = explode("\n", $buffer);
$filtered = array();
foreach($lines as $line) {
$line = $this->_prefix . $line;
$filtered[] = $line;
}
$filtered_buffer = implode("\n", $filtered);
return $filtered_buffer;
}
/**
* Sets the prefix to add at the start of each input line.
*
* @param string $prefix The prefix to add at the start of each input line.
* May be <code>null</code>, in which case no prefix
* is added.
*/
function setPrefix($prefix) {
$this->_prefix = (string) $prefix;
}
/**
* Returns the prefix which will be added at the start of each input line.
*
* @return string The prefix which will be added at the start of each input line
*/
function getPrefix() {
return $this->_prefix;
}
/**
* Creates a new PrefixLines filter using the passed in
* Reader for instantiation.
*
* @param object A Reader object providing the underlying stream.
* Must not be <code>null</code>.
*
* @return object A new filter based on this configuration, but filtering
* the specified reader
*/
function chain(Reader $reader) {
$newFilter = new PrefixLines($reader);
$newFilter->setPrefix($this->getPrefix());
$newFilter->setInitialized(true);
$newFilter->setProject($this->getProject());
return $newFilter;
}
/**
* Initializes the prefix if it is available from the parameters.
*/
private function _initialize() {
$params = $this->getParameters();
if ( $params !== null ) {
for($i = 0, $_i=count($params) ; $i < $_i ; $i++) {
if ( self::PREFIX_KEY == $params[$i]->getName() ) {
$this->_prefix = (string) $params[$i]->getValue();
break;
}
}
}
}
}

View file

@ -0,0 +1,129 @@
<?php
/*
* $Id: ReplaceRegexp.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>.
*/
require_once 'phing/filters/BaseFilterReader.php';
include_once 'phing/filters/ChainableReader.php';
include_once 'phing/types/RegularExpression.php';
/**
* Performs a regexp find/replace on stream.
* <p>
* Example:<br>
* <pre>
* <replaceregexp>
* <regexp pattern="\r\n" replace="\n"/>
* <regexp pattern="(\w+)\.xml" replace="\1.php" ignoreCase="true"/>
* </replaceregexp>
* </pre>
*
* @author Hans Lellelid <hans@xmpl.org>
* @version $Revision: 905 $
* @package phing.filters
*/
class ReplaceRegexp extends BaseFilterReader implements ChainableReader {
/**
* @var array RegularExpression[]
*/
private $regexps = array();
/**
* Creator method handles nested <regexp> tags.
* @return RegularExpression
*/
function createRegexp() {
$num = array_push($this->regexps, new RegularExpression());
return $this->regexps[$num-1];
}
/**
* Sets the current regexps.
* (Used when, e.g., cloning/chaining the method.)
* @param array RegularExpression[]
*/
function setRegexps($regexps) {
$this->regexps = $regexps;
}
/**
* Gets the current regexps.
* (Used when, e.g., cloning/chaining the method.)
* @return array RegularExpression[]
*/
function getRegexps() {
return $this->regexps;
}
/**
* Returns the filtered stream.
* The original stream is first read in fully, and the regex replace is performed.
*
* @param int $len Required $len for Reader compliance.
*
* @return mixed The filtered stream, or -1 if the end of the resulting stream has been reached.
*
* @exception IOException if the underlying stream throws an IOException
* during reading
*/
function read($len = null) {
$buffer = $this->in->read($len);
if($buffer === -1) {
return -1;
}
// perform regex replace here ...
foreach($this->regexps as $exptype) {
$regexp = $exptype->getRegexp($this->project);
try {
$buffer = $regexp->replace($buffer);
$this->log("Performing regexp replace: /".$regexp->getPattern()."/".$regexp->getReplace()."/g".$regexp->getModifiers(), Project::MSG_VERBOSE);
} catch (Exception $e) {
// perhaps mismatch in params (e.g. no replace or pattern specified)
$this->log("Error performing regexp replace: " . $e->getMessage(), Project::MSG_WARN);
}
}
return $buffer;
}
/**
* Creates a new ReplaceRegExp filter using the passed in
* Reader for instantiation.
*
* @param Reader $reader A Reader object providing the underlying stream.
* Must not be <code>null</code>.
*
* @return ReplaceRegExp A new filter based on this configuration, but filtering
* the specified reader
*/
function chain(Reader $reader) {
$newFilter = new ReplaceRegExp($reader);
$newFilter->setProject($this->getProject());
$newFilter->setRegexps($this->getRegexps());
return $newFilter;
}
}

View file

@ -0,0 +1,435 @@
<?php
/*
* $Id: ReplaceTokens.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/filters/BaseParamFilterReader.php';
include_once 'phing/types/TokenSource.php';
include_once 'phing/filters/ChainableReader.php';
/**
* Replaces tokens in the original input with user-supplied values.
*
* Example:
*
* <pre><replacetokens begintoken="#" endtoken="#">;
* <token key="DATE" value="${TODAY}"/>
* </replacetokens></pre>
*
* Or:
*
* <pre><filterreader classname="phing.filters.ReplaceTokens">
* <param type="tokenchar" name="begintoken" value="#"/>
* <param type="tokenchar" name="endtoken" value="#"/>
* <param type="token" name="DATE" value="${TODAY}"/>
* </filterreader></pre>
*
* @author <a href="mailto:yl@seasonfive.com">Yannick Lecaillez</a>
* @author hans lellelid, hans@velum.net
* @version $Revision: 905 $ $Date: 2010-10-05 18:28:03 +0200 (Tue, 05 Oct 2010) $
* @access public
* @see BaseParamFilterReader
* @package phing.filters
*/
class ReplaceTokens extends BaseParamFilterReader implements ChainableReader {
/**
* Default "begin token" character.
* @var string
*/
const DEFAULT_BEGIN_TOKEN = "@";
/**
* Default "end token" character.
* @var string
*/
const DEFAULT_END_TOKEN = "@";
/**
* [Deprecated] Data that must be read from, if not null.
* @var string
*/
private $_queuedData = null;
/**
* Array to hold the replacee-replacer pairs (String to String).
* @var array
*/
private $_tokens = array();
/**
* Array to hold the token sources that make tokens from
* different sources available
* @var array
*/
private $_tokensources = array();
/**
* Array holding all tokens given directly to the Filter and
* those passed via a TokenSource.
* @var array
*/
private $_alltokens = null;
/**
* Character marking the beginning of a token.
* @var string
*/
private $_beginToken = "@"; // self::DEFAULT_BEGIN_TOKEN;
/**
* Character marking the end of a token.
* @var string
*/
private $_endToken = "@"; //self::DEFAULT_END_TOKEN;
/**
* Performs lookup on key and returns appropriate replacement string.
* @param array $matches Array of 1 el containing key to search for.
* @return string Text with which to replace key or value of key if none is found.
* @access private
*/
private function replaceTokenCallback($matches) {
$key = $matches[1];
/* Get tokens from tokensource and merge them with the
* tokens given directly via build file. This should be
* done a bit more elegantly
*/
if ($this->_alltokens === null) {
$this->_alltokens = array();
$count = count($this->_tokensources);
for ($i = 0; $i < $count; $i++) {
$source = $this->_tokensources[$i];
$this->_alltokens = array_merge($this->_alltokens, $source->getTokens());
}
$this->_alltokens = array_merge($this->_tokens, $this->_alltokens);
}
$tokens = $this->_alltokens;
$replaceWith = null;
$count = count($tokens);
for ($i = 0; $i < $count; $i++) {
if ($tokens[$i]->getKey() === $key) {
$replaceWith = $tokens[$i]->getValue();
}
}
if ($replaceWith === null) {
$replaceWith = $this->_beginToken . $key . $this->_endToken;
$this->log("No token defined for key \"".$this->_beginToken . $key . $this->_endToken."\"");
} else {
$this->log("Replaced \"".$this->_beginToken . $key . $this->_endToken ."\" with \"".$replaceWith."\"");
}
return $replaceWith;
}
/**
* Returns stream with tokens having been replaced with appropriate values.
* If a replacement value is not found for a token, the token is left in the stream.
*
* @return mixed filtered stream, -1 on EOF.
*/
function read($len = null) {
if ( !$this->getInitialized() ) {
$this->_initialize();
$this->setInitialized(true);
}
// read from next filter up the chain
$buffer = $this->in->read($len);
if($buffer === -1) {
return -1;
}
// filter buffer
$buffer = preg_replace_callback(
"/".preg_quote($this->_beginToken)."([\w\.\-:]+?)".preg_quote($this->_endToken)."/",
array($this, 'replaceTokenCallback'), $buffer);
return $buffer;
}
/**
* Sets the "begin token" character.
*
* @param string $beginToken the character used to denote the beginning of a token.
*/
function setBeginToken($beginToken) {
$this->_beginToken = (string) $beginToken;
}
/**
* Returns the "begin token" character.
*
* @return string The character used to denote the beginning of a token.
*/
function getBeginToken() {
return $this->_beginToken;
}
/**
* Sets the "end token" character.
*
* @param string $endToken the character used to denote the end of a token
*/
function setEndToken($endToken) {
$this->_endToken = (string) $endToken;
}
/**
* Returns the "end token" character.
*
* @return the character used to denote the beginning of a token
*/
function getEndToken() {
return $this->_endToken;
}
/**
* Adds a token element to the map of tokens to replace.
*
* @return object The token added to the map of replacements.
* Must not be <code>null</code>.
*/
function createToken() {
$num = array_push($this->_tokens, new Token());
return $this->_tokens[$num-1];
}
/**
* Adds a token source to the sources of this filter.
*
* @return object A Reference to the source just added.
*/
function createTokensource() {
$num = array_push($this->_tokensources, new TokenSource());
return $this->_tokensources[$num-1];
}
/**
* Sets the map of tokens to replace.
* ; used by ReplaceTokens::chain()
*
* @param array A map (String->String) of token keys to replacement
* values. Must not be <code>null</code>.
*/
function setTokens($tokens) {
// type check, error must never occur, bad code of it does
if ( !is_array($tokens) ) {
throw new Exception("Excpected 'array', got something else");
}
$this->_tokens = $tokens;
}
/**
* Returns the map of tokens which will be replaced.
* ; used by ReplaceTokens::chain()
*
* @return array A map (String->String) of token keys to replacement values.
*/
function getTokens() {
return $this->_tokens;
}
/**
* Sets the tokensources to use; used by ReplaceTokens::chain()
*
* @param array An array of token sources.
*/
function setTokensources($sources) {
// type check
if ( !is_array($sources)) {
throw new Exception("Exspected 'array', got something else");
}
$this->_tokensources = $sources;
}
/**
* Returns the token sources used by this filter; used by ReplaceTokens::chain()
*
* @return array
*/
function getTokensources() {
return $this->_tokensources;
}
/**
* Creates a new ReplaceTokens using the passed in
* Reader for instantiation.
*
* @param object A Reader object providing the underlying stream.
* Must not be <code>null</code>.
*
* @return object A new filter based on this configuration, but filtering
* the specified reader
*/
function chain(Reader $reader) {
$newFilter = new ReplaceTokens($reader);
$newFilter->setProject($this->getProject());
$newFilter->setBeginToken($this->getBeginToken());
$newFilter->setEndToken($this->getEndToken());
$newFilter->setTokens($this->getTokens());
$newFilter->setTokensources($this->getTokensources());
$newFilter->setInitialized(true);
return $newFilter;
}
/**
* Initializes tokens and loads the replacee-replacer hashtable.
* This method is only called when this filter is used through
* a <filterreader> tag in build file.
*/
private function _initialize() {
$params = $this->getParameters();
if ( $params !== null ) {
for($i = 0 ; $i<count($params) ; $i++) {
if ( $params[$i] !== null ) {
$type = $params[$i]->getType();
if ( $type === "tokenchar" ) {
$name = $params[$i]->getName();
if ( $name === "begintoken" ) {
$this->_beginToken = substr($params[$i]->getValue(), 0, 1);
} else if ( $name === "endtoken" ) {
$this->_endToken = substr($params[$i]->getValue(), 0, 1);
}
} else if ( $type === "token" ) {
$name = $params[$i]->getName();
$value = $params[$i]->getValue();
$tok = new Token();
$tok->setKey($name);
$tok->setValue($value);
array_push($this->_tokens, $tok);
} else if ( $type === "tokensource" ) {
// Store data from nested tags in local array
$arr = array(); $subparams = $params[$i]->getParams();
$count = count($subparams);
for ($i = 0; $i < $count; $i++) {
$arr[$subparams[$i]->getName()] = $subparams[$i]->getValue();
}
// Create TokenSource
$tokensource = new TokenSource();
if (isset($arr["classname"]))
$tokensource->setClassname($arr["classname"]);
// Copy other parameters 1:1 to freshly created TokenSource
foreach ($arr as $key => $value) {
if (strtolower($key) === "classname")
continue;
$param = $tokensource->createParam();
$param->setName($key);
$param->setValue($value);
}
$this->_tokensources[] = $tokensource;
}
}
}
}
}
}
/**
* Holds a token.
*
* @package phing.filters
*/
class Token {
/**
* Token key.
* @var string
*/
private $_key;
/**
* Token value.
* @var string
*/
private $_value;
/**
* Sets the token key.
*
* @param string $key The key for this token. Must not be <code>null</code>.
*/
function setKey($key) {
$this->_key = (string) $key;
}
/**
* Sets the token value.
*
* @param string $value The value for this token. Must not be <code>null</code>.
*/
function setValue($value) {
// special case for boolean values
if (is_bool($value)) {
if ($value) {
$this->_value = "true";
} else {
$this->_value = "false";
}
} else {
$this->_value = (string) $value;
}
}
/**
* Returns the key for this token.
*
* @return string The key for this token.
*/
function getKey() {
return $this->_key;
}
/**
* Returns the value for this token.
*
* @return string The value for this token.
*/
function getValue() {
return $this->_value;
}
/**
* Sets the token value from text.
*
* @param string $value The value for this token. Must not be <code>null</code>.
*/
function addText($value) {
$this->setValue($value);
}
}

View file

@ -0,0 +1,325 @@
<?php
/*
* $Id: ReplaceTokensWithFile.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/filters/BaseParamFilterReader.php';
include_once 'phing/filters/ChainableReader.php';
/*
* Replaces tokens in the original input with the contents of a file.
* The file to be used is controlled by the name of the token which
* corresponds to the basename of the file to be used together with
* the optional pre and postfix strings that is possible to set.
*
* By default all HTML entities in the file is replaced by the
* corresponding HTML entities. This behaviour can be controlled by
* the "translatehtml" parameter.
*
* Supported parameters are:
* <pre>
* prefix string Text to be prefixed to token before using as filename
* postfix string Text to be prefixed to token before using as filename
* dir string The directory where the files should be read from
* translatehtml bool If we should translate all HTML entities in the file.
* </pre>
* Example:
*
* <pre><filterreader classname="phing.filters.ReplaceTokensWithFile">
* <param name="dir" value="examples/" />
* <param name="postfix" value=".php" />
* </filterreader></pre>
*
* @author johan persson, johanp@aditus.nu
* @version $Id: ReplaceTokensWithFile.php 905 2010-10-05 16:28:03Z mrook $
* @access public
* @see ReplaceTokensWithFile
* @package phing.filters
*/
class ReplaceTokensWithFile extends BaseParamFilterReader implements ChainableReader {
/**
* Default "begin token" character.
* @var string
*/
const DEFAULT_BEGIN_TOKEN = "#@#";
/**
* Default "end token" character.
* @var string
*/
const DEFAULT_END_TOKEN = "#@#";
/**
* Array to hold the token sources that make tokens from
* different sources available
* @var array
*/
private $_tokensources = array();
/**
* Character marking the beginning of a token.
* @var string
*/
private $_beginToken = ReplaceTokensWithFile::DEFAULT_BEGIN_TOKEN;
/**
* Character marking the end of a token.
* @var string
*/
private $_endToken = ReplaceTokensWithFile::DEFAULT_END_TOKEN;
/**
* File prefix to be inserted in front of the token to create the
* file name to be used.
* @var string
*/
private $_prefix = '';
/**
* File postfix to be inserted in front of the token to create the
* file name to be used.
* @var string
*/
private $_postfix = '';
/**
* Directory where to look for the files. The default is to look in the
* current file.
*
* @var string
*/
private $_dir = './';
/**
* Translate all HTML entities in the file to the corresponding HTML
* entities before it is used as replacements. For example all '<'
* will be translated to &lt; before the content is inserted.
*
* @var boolean
*/
private $_translatehtml = true;
/**
* Sets the drectory where to look for the files to use for token replacement
*
* @param string $dir
*/
function setTranslateHTML($translate) {
$this->_translatehtml = (bool) $translate;
}
/**
* Sets the drectory where to look for the files to use for token replacement
*
* @param string $dir
*/
function setDir($dir) {
$this->_dir = (string) $dir;
}
/**
* Sets the prefix that is prepended to the token in order to create the file
* name. For example if the token is 01 and the prefix is "example" then
* the filename to look for will be "example01"
*
* @param string $prefix
*/
function setPrefix($prefix) {
$this->_prefix = (string) $prefix;
}
/**
* Sets the postfix that is added to the token in order to create the file
* name. For example if the token is 01 and the postfix is ".php" then
* the filename to look for will be "01.php"
*
* @param string $postfix
*/
function setPostfix($postfix) {
$this->_postfix = (string) $postfix;
}
/**
* Sets the "begin token" character.
*
* @param string $beginToken the character used to denote the beginning of a token.
*/
function setBeginToken($beginToken) {
$this->_beginToken = (string) $beginToken;
}
/**
* Returns the "begin token" character.
*
* @return string The character used to denote the beginning of a token.
*/
function getBeginToken() {
return $this->_beginToken;
}
/**
* Sets the "end token" character.
*
* @param string $endToken the character used to denote the end of a token
*/
function setEndToken($endToken) {
$this->_endToken = (string) $endToken;
}
/**
* Returns the "end token" character.
*
* @return the character used to denote the beginning of a token
*/
function getEndToken() {
return $this->_endToken;
}
/**
* Replace the token found with the appropriate file contents
* @param array $matches Array of 1 el containing key to search for.
* @return string Text with which to replace key or value of key if none is found.
* @access private
*/
private function replaceTokenCallback($matches) {
$filetoken = $matches[1];
// We look in all specified directories for the named file and use
// the first directory which has the file.
$dirs = explode(';',$this->_dir);
$ndirs = count($dirs);
$n = 0;
$file = $dirs[$n] . $this->_prefix . $filetoken . $this->_postfix;
while ( $n < $ndirs && ! is_readable($file) ) {
++$n;
}
if( ! is_readable($file) || $n >= $ndirs ) {
$this->log("Can not read or find file \"$file\". Searched in directories: {$this->_dir}", Project::MSG_WARN);
//return $this->_beginToken . $filetoken . $this->_endToken;
return "[Phing::Filters::ReplaceTokensWithFile: Can not find file " . '"' . $filetoken . $this->_postfix . '"' . "]";
}
$buffer = file_get_contents($file);
if( $this->_translatehtml ) {
$buffer = htmlentities($buffer);
}
if ($buffer === null) {
$buffer = $this->_beginToken . $filetoken . $this->_endToken;
$this->log("No corresponding file found for key \"$buffer\"", Project::MSG_WARN);
} else {
$this->log("Replaced \"".$this->_beginToken . $filetoken . $this->_endToken."\" with content from file \"$file\"");
}
return $buffer;
}
/**
* Returns stream with tokens having been replaced with appropriate values.
* If a replacement value is not found for a token, the token is left in the stream.
*
* @return mixed filtered stream, -1 on EOF.
*/
function read($len = null) {
if ( !$this->getInitialized() ) {
$this->_initialize();
$this->setInitialized(true);
}
// read from next filter up the chain
$buffer = $this->in->read($len);
if($buffer === -1) {
return -1;
}
// filter buffer
$buffer = preg_replace_callback(
"/".preg_quote($this->_beginToken)."([\w\.\-:\/]+?)".preg_quote($this->_endToken)."/",
array($this, 'replaceTokenCallback'), $buffer);
return $buffer;
}
/**
* Creates a new ReplaceTokensWithFile using the passed in
* Reader for instantiation.
*
* @param object A Reader object providing the underlying stream.
* Must not be <code>null</code>.
*
* @return object A new filter based on this configuration, but filtering
* the specified reader
*/
function chain(Reader $reader) {
$newFilter = new ReplaceTokensWithFile($reader);
$newFilter->setProject($this->getProject());
$newFilter->setBeginToken($this->getBeginToken());
$newFilter->setEndToken($this->getEndToken());
$newFilter->setInitialized(true);
return $newFilter;
}
/**
* Initializes parameters
* This method is only called when this filter is used through
* a <filterreader> tag in build file.
*/
private function _initialize() {
$params = $this->getParameters();
$n = count($params);
if ( $params !== null ) {
for($i = 0 ; $i < $n ; $i++) {
if ( $params[$i] !== null ) {
$name = $params[$i]->getName();
switch( $name ) {
case 'begintoken' :
$this->_beginToken = $params[$i]->getValue();
break;
case 'endtoken' :
$this->_endToken = $params[$i]->getValue();
break;
case 'dir':
$this->_dir = $params[$i]->getValue();
break;
case 'prefix':
$this->_prefix = $params[$i]->getValue();
break;
case 'postfix':
$this->_postfix = $params[$i]->getValue();
break;
case 'translatehtml':
$this->_translatehtml = $params[$i]->getValue();
break;
}
}
}
}
}
}

View file

@ -0,0 +1,148 @@
<?php
/*
* $Id: StripLineBreaks.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/filters/BaseParamFilterReader.php';
include_once 'phing/filters/ChainableReader.php';
/**
* Filter to flatten the stream to a single line.
*
* Example:
*
* <pre><striplinebreaks/></pre>
*
* Or:
*
* <pre><filterreader classname="phing.filters.StripLineBreaks"/></pre>
*
* @author <a href="mailto:yl@seasonfive.com">Yannick Lecaillez</a>
* @author hans lellelid, hans@velum.net
* @version $Revision: 905 $ $Date: 2010-10-05 18:28:03 +0200 (Tue, 05 Oct 2010) $
* @access public
* @see BaseParamFilterReader
* @package phing.filters
*/
class StripLineBreaks extends BaseParamFilterReader implements ChainableReader {
/**
* Default line-breaking characters.
* @var string
*/
const DEFAULT_LINE_BREAKS = "\r\n";
/**
* Parameter name for the line-breaking characters parameter.
* @var string
*/
const LINES_BREAKS_KEY = "linebreaks";
/**
* The characters that are recognized as line breaks.
* @var string
*/
private $_lineBreaks = "\r\n"; // self::DEFAULT_LINE_BREAKS;
/**
* Returns the filtered stream, only including
* characters not in the set of line-breaking characters.
*
* @return mixed the resulting stream, or -1
* if the end of the resulting stream has been reached.
*
* @exception IOException if the underlying stream throws an IOException
* during reading
*/
function read($len = null) {
if ( !$this->getInitialized() ) {
$this->_initialize();
$this->setInitialized(true);
}
$buffer = $this->in->read($len);
if($buffer === -1) {
return -1;
}
$buffer = preg_replace("/[".$this->_lineBreaks."]/", '', $buffer);
return $buffer;
}
/**
* Sets the line-breaking characters.
*
* @param string $lineBreaks A String containing all the characters to be
* considered as line-breaking.
*/
function setLineBreaks($lineBreaks) {
$this->_lineBreaks = (string) $lineBreaks;
}
/**
* Gets the line-breaking characters.
*
* @return string A String containing all the characters that are considered as line-breaking.
*/
function getLineBreaks() {
return $this->_lineBreaks;
}
/**
* Creates a new StripLineBreaks using the passed in
* Reader for instantiation.
*
* @param object A Reader object providing the underlying stream.
* Must not be <code>null</code>.
*
* @return object A new filter based on this configuration, but filtering
* the specified reader
*/
function chain(Reader $reader) {
$newFilter = new StripLineBreaks($reader);
$newFilter->setLineBreaks($this->getLineBreaks());
$newFilter->setInitialized(true);
$newFilter->setProject($this->getProject());
return $newFilter;
}
/**
* Parses the parameters to set the line-breaking characters.
*/
private function _initialize() {
$userDefinedLineBreaks = null;
$params = $this->getParameters();
if ( $params !== null ) {
for($i = 0 ; $i<count($params) ; $i++) {
if ( self::LINE_BREAKS_KEY === $params[$i]->getName() ) {
$userDefinedLineBreaks = $params[$i]->getValue();
break;
}
}
}
if ( $userDefinedLineBreaks !== null ) {
$this->_lineBreaks = $userDefinedLineBreaks;
}
}
}

View file

@ -0,0 +1,207 @@
<?php
/*
* $Id: StripLineComments.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/filters/BaseParamFilterReader.php';
include_once 'phing/filters/ChainableReader.php';
/**
* This filter strips line comments.
*
* Example:
*
* <pre><striplinecomments>
* <comment value="#"/>
* <comment value="--"/>
* <comment value="REM "/>
* <comment value="rem "/>
* <comment value="//"/>
* </striplinecomments></pre>
*
* Or:
*
* <pre><filterreader classname="phing.filters.StripLineComments">
* <param type="comment" value="#"/>
* <param type="comment" value="--"/>
* <param type="comment" value="REM "/>
* <param type="comment" value="rem "/>
* <param type="comment" value="//"/>
* </filterreader></pre>
*
* @author <a href="mailto:yl@seasonfive.com">Yannick Lecaillez</a>
* @author hans lellelid, hans@velum.net
* @version $Revision: 905 $ $Date: 2010-10-05 18:28:03 +0200 (Tue, 05 Oct 2010) $
* @access public
* @see BaseParamFilterReader
* @package phing.filters
*/
class StripLineComments extends BaseParamFilterReader implements ChainableReader {
/** Parameter name for the comment prefix. */
const COMMENTS_KEY = "comment";
/** Array that holds the comment prefixes. */
private $_comments = array();
/**
* Returns stream only including
* lines from the original stream which don't start with any of the
* specified comment prefixes.
*
* @return mixed the resulting stream, or -1
* if the end of the resulting stream has been reached.
*
* @throws IOException if the underlying stream throws an IOException
* during reading
*/
function read($len = null) {
if ( !$this->getInitialized() ) {
$this->_initialize();
$this->setInitialized(true);
}
$buffer = $this->in->read($len);
if ($buffer === -1) {
return -1;
}
$lines = explode("\n", $buffer);
$filtered = array();
$commentsSize = count($this->_comments);
foreach($lines as $line) {
for($i = 0; $i < $commentsSize; $i++) {
$comment = $this->_comments[$i]->getValue();
if ( StringHelper::startsWith($comment, ltrim($line)) ) {
$line = null;
break;
}
}
if ($line !== null) {
$filtered[] = $line;
}
}
$filtered_buffer = implode("\n", $filtered);
return $filtered_buffer;
}
/*
* Adds a <code>comment</code> element to the list of prefixes.
*
* @return comment The <code>comment</code> element added to the
* list of comment prefixes to strip.
*/
function createComment() {
$num = array_push($this->_comments, new Comment());
return $this->_comments[$num-1];
}
/*
* Sets the list of comment prefixes to strip.
*
* @param comments A list of strings, each of which is a prefix
* for a comment line. Must not be <code>null</code>.
*/
function setComments($lineBreaks) {
if (!is_array($lineBreaks)) {
throw new Exception("Excpected 'array', got something else");
}
$this->_comments = $lineBreaks;
}
/*
* Returns the list of comment prefixes to strip.
*
* @return array The list of comment prefixes to strip.
*/
function getComments() {
return $this->_comments;
}
/*
* Creates a new StripLineComments using the passed in
* Reader for instantiation.
*
* @param reader A Reader object providing the underlying stream.
* Must not be <code>null</code>.
*
* @return a new filter based on this configuration, but filtering
* the specified reader
*/
function chain(Reader $reader) {
$newFilter = new StripLineComments($reader);
$newFilter->setComments($this->getComments());
$newFilter->setInitialized(true);
$newFilter->setProject($this->getProject());
return $newFilter;
}
/*
* Parses the parameters to set the comment prefixes.
*/
private function _initialize() {
$params = $this->getParameters();
if ( $params !== null ) {
for($i = 0 ; $i<count($params) ; $i++) {
if ( self::COMMENTS_KEY === $params[$i]->getType() ) {
$comment = new Comment();
$comment->setValue($params[$i]->getValue());
array_push($this->_comments, $comment);
}
}
}
}
}
/**
* The class that holds a comment representation.
*
* @package phing.filters
*/
class Comment {
/** The prefix for a line comment. */
private $_value;
/*
* Sets the prefix for this type of line comment.
*
* @param string $value The prefix for a line comment of this type.
* Must not be <code>null</code>.
*/
function setValue($value) {
$this->_value = (string) $value;
}
/*
* Returns the prefix for this type of line comment.
*
* @return string The prefix for this type of line comment.
*/
function getValue() {
return $this->_value;
}
}

View file

@ -0,0 +1,188 @@
<?php
/*
* $Id: StripPhpComments.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/filters/BaseFilterReader.php';
include_once 'phing/filters/ChainableReader.php';
/**
* This is a Php comment and string stripper reader that filters
* those lexical tokens out for purposes of simple Php parsing.
* (if you have more complex Php parsing needs, use a real lexer).
* Since this class heavily relies on the single char read function,
* you are reccomended to make it work on top of a buffered reader.
*
* @author <a href="mailto:yl@seasonfive.com">Yannick Lecaillez</a>
* @author hans lellelid, hans@velum.net
* @version $Revision: 905 $ $Date: 2010-10-05 18:28:03 +0200 (Tue, 05 Oct 2010) $
* @access public
* @see FilterReader
* @package phing.filters
*/
class StripPhpComments extends BaseFilterReader implements ChainableReader {
/**
* The read-ahead character, used for effectively pushing a single
* character back. -1 indicates that no character is in the buffer.
*/
private $_readAheadCh = -1;
/**
* Whether or not the parser is currently in the middle of a string
* literal.
* @var boolean
*/
private $_inString = false;
/**
* Returns the stream without Php comments.
*
* @return the resulting stream, or -1
* if the end of the resulting stream has been reached
*
* @throws IOException if the underlying stream throws an IOException
* during reading
*/
function read($len = null) {
$buffer = $this->in->read($len);
if($buffer === -1) {
return -1;
}
// This regex replace /* */ and // style comments
$buffer = preg_replace('/\/\*[^*]*\*+([^\/*][^*]*\*+)*\/|\/\/[^\n]*|("(\\\\.|[^"\\\\])*"|\'(\\\\.|[^\'\\\\])*\'|.[^\/"\'\\\\]*)/s', "$2", $buffer);
// The regex above is not identical to, but is based on the expression below:
//
// created by Jeffrey Friedl
// and later modified by Fred Curtis.
// s{
// /\* ## Start of /* ... */ comment
// [^*]*\*+ ## Non-* followed by 1-or-more *'s
// (
// [^/*][^*]*\*+
// )* ## 0-or-more things which don't start with /
// ## but do end with '*'
// / ## End of /* ... */ comment
//
// | ## OR various things which aren't comments:
//
// (
// " ## Start of " ... " string
// (
// \\. ## Escaped char
// | ## OR
// [^"\\] ## Non "\
// )*
// " ## End of " ... " string
//
// | ## OR
//
// ' ## Start of ' ... ' string
// (
// \\. ## Escaped char
// | ## OR
// [^'\\] ## Non '\
// )*
// ' ## End of ' ... ' string
//
// | ## OR
//
// . ## Anything other char
// [^/"'\\]* ## Chars which doesn't start a comment, string or escape
// )
// }{$2}gxs;
return $buffer;
}
/*
* Returns the next character in the filtered stream, not including
* Php comments.
*
* @return the next character in the resulting stream, or -1
* if the end of the resulting stream has been reached
*
* @throws IOException if the underlying stream throws an IOException
* during reading
* @deprecated
*/
function readChar() {
$ch = -1;
if ( $this->_readAheadCh !== -1 ) {
$ch = $this->_readAheadCh;
$this->_readAheadCh = -1;
} else {
$ch = $this->in->readChar();
if ( $ch === "\"" ) {
$this->_inString = !$this->_inString;
} else {
if ( !$this->_inString ) {
if ( $ch === "/" ) {
$ch = $this->in->readChar();
if ( $ch === "/" ) {
while ( $ch !== "\n" && $ch !== -1 ) {
$ch = $this->in->readChar();
}
} else if ( $ch === "*" ) {
while ( $ch !== -1 ) {
$ch = $this->in->readChar();
while ( $ch === "*" && $ch !== -1 ) {
$ch = $this->in->readChar();
}
if ( $ch === "/" ) {
$ch = $this->readChar();
echo "$ch\n";
break;
}
}
} else {
$this->_readAheadCh = $ch;
$ch = "/";
}
}
}
}
}
return $ch;
}
/**
* Creates a new StripPhpComments using the passed in
* Reader for instantiation.
*
* @param reader A Reader object providing the underlying stream.
* Must not be <code>null</code>.
*
* @return a new filter based on this configuration, but filtering
* the specified reader
*/
function chain(Reader $reader) {
$newFilter = new StripPhpComments($reader);
$newFilter->setProject($this->getProject());
return $newFilter;
}
}

View file

@ -0,0 +1,95 @@
<?php
/*
* $Id $
*
* 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/filters/BaseFilterReader.php';
include_once 'phing/filters/ChainableReader.php';
/**
* Strips whitespace from [php] files using PHP stripwhitespace() method.
*
* @author Hans Lellelid, hans@velum.net
* @version $Revision: 905 $ $Date: 2010-10-05 18:28:03 +0200 (Tue, 05 Oct 2010) $
* @see FilterReader
* @package phing.filters
* @todo -c use new PHP functions to perform this instead of regex.
*/
class StripWhitespace extends BaseFilterReader implements ChainableReader {
private $processed = false;
/**
* Returns the stream without Php comments and whitespace.
*
* @return the resulting stream, or -1
* if the end of the resulting stream has been reached
*
* @throws IOException if the underlying stream throws an IOException
* during reading
*/
function read($len = null) {
if ($this->processed === true) {
return -1; // EOF
}
// Read XML
$php = null;
while ( ($buffer = $this->in->read($len)) !== -1 ) {
$php .= $buffer;
}
if ($php === null ) { // EOF?
return -1;
}
if(empty($php)) {
$this->log("PHP file is empty!", Project::MSG_WARN);
return ''; // return empty string, don't attempt to strip whitespace
}
// write buffer to a temporary file, since php_strip_whitespace() needs a filename
$file = new PhingFile(tempnam(PhingFile::getTempDir(), 'stripwhitespace'));
file_put_contents($file->getAbsolutePath(), $php);
$output = php_strip_whitespace($file->getAbsolutePath());
unlink($file->getAbsolutePath());
$this->processed = true;
return $output;
}
/**
* Creates a new StripWhitespace using the passed in
* Reader for instantiation.
*
* @param reader A Reader object providing the underlying stream.
* Must not be <code>null</code>.
*
* @return a new filter based on this configuration, but filtering
* the specified reader
*/
public function chain(Reader $reader) {
$newFilter = new StripWhitespace($reader);
$newFilter->setProject($this->getProject());
return $newFilter;
}
}

View file

@ -0,0 +1,144 @@
<?php
/*
* $Id: TabToSpaces.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>.
*/
require_once 'phing/filters/BaseParamFilterReader.php';
require_once 'phing/filters/ChainableReader.php';
/**
* Converts tabs to spaces.
*
* Example:
*
* <pre><tabtospaces tablength="8"></pre>
*
* Or:
*
* <pre><filterreader classname="phing.filters.TabsToSpaces">
* <param name="tablength" value="8">
* </filterreader></pre>
*
* @author Yannick Lecaillez <yl@seasonfive.com>
* @author Hans Lellelid <hans@xmpl.org>
* @version $Revision: 905 $
* @see BaseParamFilterReader
* @package phing.filters
*/
class TabToSpaces extends BaseParamFilterReader implements ChainableReader {
/**
* The default tab length.
* @var int
*/
const DEFAULT_TAB_LENGTH = 8;
/**
* Parameter name for the length of a tab.
* @var string
*/
const TAB_LENGTH_KEY = "tablength";
/**
* Tab length in this filter.
* @var int
*/
private $tabLength = 8; //self::DEFAULT_TAB_LENGTH;
/**
* Returns stream after converting tabs to the specified number of spaces.
*
* @return the resulting stream, or -1
* if the end of the resulting stream has been reached
*
* @exception IOException if the underlying stream throws an IOException
* during reading
*/
function read($len = null) {
if ( !$this->getInitialized() ) {
$this->_initialize();
$this->setInitialized(true);
}
$buffer = $this->in->read($len);
if($buffer === -1) {
return -1;
}
$buffer = str_replace("\t", str_repeat(' ', $this->tabLength), $buffer);
return $buffer;
}
/**
* Sets the tab length.
*
* @param int $tabLength The number of spaces to be used when converting a tab.
*/
function setTablength($tabLength) {
$this->tabLength = (int) $tabLength;
}
/**
* Returns the tab length.
*
* @return int The number of spaces used when converting a tab
*/
function getTablength() {
return $this->tabLength;
}
/**
* Creates a new TabsToSpaces using the passed in
* Reader for instantiation.
*
* @param Reader $reader A Reader object providing the underlying stream.
* Must not be <code>null</code>.
*
* @return Reader A new filter based on this configuration, but filtering
* the specified reader
*/
function chain(Reader $reader) {
$newFilter = new TabToSpaces($reader);
$newFilter->setTablength($this->getTablength());
$newFilter->setInitialized(true);
$newFilter->setProject($this->getProject());
return $newFilter;
}
/**
* Parses the parameters to set the tab length.
*/
private function _initialize() {
$params = $this->getParameters();
if ( $params !== null ) {
for($i = 0 ; $i<count($params) ; $i++) {
if (self::TAB_LENGTH_KEY === $params[$i]->getName()) {
$this->tabLength = $params[$i]->getValue();
break;
}
}
}
}
}

View file

@ -0,0 +1,157 @@
<?php
/*
* $Id: TailFilter.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>.
*/
require_once 'phing/filters/BaseParamFilterReader.php';
/**
* Reads the last <code>n</code> lines of a stream. (Default is last10 lines.)
*
* Example:
*
* <pre><tailfilter lines="3" /></pre>
*
* Or:
*
* <pre><filterreader classname="phing.filters.TailFilter">
* <param name="lines" value="3">
* </filterreader></pre>
*
* @author <a href="mailto:yl@seasonfive.com">Yannick Lecaillez</a>
* @author hans lellelid, hans@velum.net
* @copyright © 2003 seasonfive. All rights reserved
* @version $Revision: 905 $
* @see BaseParamFilterReader
* @package phing.filters
*/
class TailFilter extends BaseParamFilterReader implements ChainableReader {
/**
* Parameter name for the number of lines to be returned.
* @var string
*/
const LINES_KEY = "lines";
/**
* Number of lines to be returned in the filtered stream.
* @var integer
*/
private $_lines = 10;
/**
* Array to hold lines.
* @var array
*/
private $_lineBuffer = array();
/**
* Returns the last n lines of a file.
* @param int $len Num chars to read.
* @return mixed The filtered buffer or -1 if EOF.
*/
function read($len = null) {
while ( ($buffer = $this->in->read($len)) !== -1 ) {
// Remove the last "\n" from buffer for
// prevent explode to add an empty cell at
// the end of array
$buffer= trim($buffer, "\n");
$lines = explode("\n", $buffer);
if ( count($lines) >= $this->_lines ) {
// Buffer have more (or same) number of lines than needed.
// Fill lineBuffer with the last "$this->_lines" lasts ones.
$off = count($lines)-$this->_lines;
$this->_lineBuffer = array_slice($lines, $off);
} else {
// Some new lines ...
// Prepare space for insert these new ones
$this->_lineBuffer = array_slice($this->_lineBuffer, count($lines)-1);
$this->_lineBuffer = array_merge($this->_lineBuffer, $lines);
}
}
if ( empty($this->_lineBuffer) )
$ret = -1;
else {
$ret = implode("\n", $this->_lineBuffer);
$this->_lineBuffer = array();
}
return $ret;
}
/**
* Sets the number of lines to be returned in the filtered stream.
*
* @param integer $lines the number of lines to be returned in the filtered stream.
*/
function setLines($lines) {
$this->_lines = (int) $lines;
}
/**
* Returns the number of lines to be returned in the filtered stream.
*
* @return integer The number of lines to be returned in the filtered stream.
*/
function getLines() {
return $this->_lines;
}
/**
* Creates a new TailFilter using the passed in
* Reader for instantiation.
*
* @param object A Reader object providing the underlying stream.
* Must not be <code>null</code>.
*
* @return object A new filter based on this configuration, but filtering
* the specified reader.
*/
function chain(Reader $reader) {
$newFilter = new TailFilter($reader);
$newFilter->setLines($this->getLines());
$newFilter->setInitialized(true);
$newFilter->setProject($this->getProject());
return $newFilter;
}
/**
* Scans the parameters list for the "lines" parameter and uses
* it to set the number of lines to be returned in the filtered stream.
*/
private function _initialize() {
$params = $this->getParameters();
if ( $params !== null ) {
for($i=0, $_i=count($params); $i < $_i; $i++) {
if ( self::LINES_KEY == $params[$i]->getName() ) {
$this->_lines = (int) $params[$i]->getValue();
break;
}
}
}
}
}

View file

@ -0,0 +1,162 @@
<?php
/*
* $Id: TidyFilter.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/filters/BaseParamFilterReader.php';
include_once 'phing/filters/ChainableReader.php';
/**
* This filter uses the bundled-with-PHP Tidy extension to filter input.
*
* <p>
* Example:<br/>
* <pre>
* <tidyfilter encoding="utf8">
* <config name="indent" value="true"/>
* <config name="output-xhtml" value="true"/>
* </tidyfilter>
* </pre>
*
* @author Hans Lellelid <hans@xmpl.org>
* @version $Revision: 905 $ $Date: 2010-10-05 18:28:03 +0200 (Tue, 05 Oct 2010) $
* @package phing.filters
*/
class TidyFilter extends BaseParamFilterReader implements ChainableReader {
/** @var string Encoding of resulting document. */
private $encoding = 'utf8';
/** @var array Parameter[] */
private $configParameters = array();
/**
* Set the encoding for resulting (X)HTML document.
* @param string $v
*/
public function setEncoding($v) {
$this->encoding = $v;
}
/**
* Sets the config params.
* @param array Parameter[]
* @see chain()
*/
public function setConfigParameters($params)
{
$this->configParameters = $params;
}
/**
* Adds a <config> element (which is a Parameter).
* @return Parameter
*/
public function createConfig() {
$num = array_push($this->configParameters, new Parameter());
return $this->configParameters[$num-1];
}
/**
* Converts the Parameter objects being used to store configuration into a simle assoc array.
* @return array
*/
private function getDistilledConfig() {
$config = array();
foreach($this->configParameters as $p) {
$config[$p->getName()] = $p->getValue();
}
return $config;
}
/**
* Reads input and returns Tidy-filtered output.
*
* @return the resulting stream, or -1 if the end of the resulting stream has been reached
*
* @throws IOException if the underlying stream throws an IOException
* during reading
*/
function read($len = null) {
if (!class_exists('Tidy')) {
throw new BuildException("You must enable the 'tidy' extension in your PHP configuration in order to use the Tidy filter.");
}
if ( !$this->getInitialized() ) {
$this->_initialize();
$this->setInitialized(true);
}
$buffer = $this->in->read($len);
if($buffer === -1) {
return -1;
}
$config = $this->getDistilledConfig();
$tidy = new Tidy();
$tidy->parseString($buffer, $config, $this->encoding);
$tidy->cleanRepair();
return tidy_get_output($tidy);
}
/**
* Creates a new TidyFilter using the passed in Reader for instantiation.
*
* @param reader A Reader object providing the underlying stream.
* Must not be <code>null</code>.
*
* @return a new filter based on this configuration, but filtering
* the specified reader
*/
public function chain(Reader $reader) {
$newFilter = new TidyFilter($reader);
$newFilter->setConfigParameters($this->configParameters);
$newFilter->setEncoding($this->encoding);
$newFilter->setProject($this->getProject());
return $newFilter;
}
/**
* Initializes any parameters (e.g. config options).
* This method is only called when this filter is used through a <filterreader> tag in build file.
*/
private function _initialize() {
$params = $this->getParameters();
if ($params) {
foreach($params as $param) {
if ($param->getType() == "config") {
$this->configParameters[] = $param;
} else {
if ($param->getName() == "encoding") {
$this->setEncoding($param->getValue());
}
}
}
}
}
}

View file

@ -0,0 +1,285 @@
<?php
/*
* $Id: TranslateGettext.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>.
*/
require_once 'phing/filters/BaseParamFilterReader.php';
include_once 'phing/filters/ChainableReader.php';
/**
* Replaces gettext("message id") and _("message id") with the translated string.
*
* Gettext is great for creating multi-lingual sites, but in some cases (e.g. for
* performance reasons) you may wish to replace the gettext calls with the translations
* of the strings; that's what this task is for. Note that this is similar to
* ReplaceTokens, but both the find and the replace aspect is more complicated -- hence
* this is a separate, stand-alone filter.
*
* <p>
* Example:<br>
* <pre>
* <translategettext locale="en_US" domain="messages" dir="${webroot}/local"/>
* </pre>
*
* @author Hans Lellelid <hans@xmpl.org>
* @version $Revision: 905 $ $Date: 2010-10-05 18:28:03 +0200 (Tue, 05 Oct 2010) $
* @access public
* @see BaseFilterReader
* @package phing.filters
*/
class TranslateGettext extends BaseParamFilterReader implements ChainableReader {
// constants for specifying keys to expect
// when this is called using <filterreader ... />
const DOMAIN_KEY = "domain";
const DIR_KEY = "dir";
const LOCALE_KEY = "locale";
/** The domain to use */
private $domain = 'messages';
/** The dir containing LC_MESSAGES */
private $dir;
/** The locale to use */
private $locale;
/** The system locale before it was changed for this filter. */
private $storedLocale;
/**
* Set the text domain to use.
* The text domain must correspond to the name of the compiled .mo files.
* E.g. "messages" ==> $dir/LC_MESSAGES/messages.mo
* "mydomain" ==> $dir/LC_MESSAGES/mydomain.mo
* @param string $domain
*/
function setDomain($domain) {
$this->domain = $domain;
}
/**
* Get the current domain.
* @return string
*/
function getDomain() {
return $this->domain;
}
/**
* Sets the root locale directory.
* @param PhingFile $dir
*/
function setDir(PhingFile $dir) {
$this->dir = $dir;
}
/**
* Gets the root locale directory.
* @return PhingFile
*/
function getDir() {
return $this->dir;
}
/**
* Sets the locale to use for translation.
* Note that for gettext() to work, you have to make sure this locale
* is specific enough for your system (e.g. some systems may allow an 'en' locale,
* but others will require 'en_US', etc.).
* @param string $locale
*/
function setLocale($locale) {
$this->locale = $locale;
}
/**
* Gets the locale to use for translation.
* @return string
*/
function getLocale() {
return $this->locale;
}
/**
* Make sure that required attributes are set.
* @throws BuldException - if any required attribs aren't set.
*/
protected function checkAttributes() {
if (!$this->domain || !$this->locale || !$this->dir) {
throw new BuildException("You must specify values for domain, locale, and dir attributes.");
}
}
/**
* Initialize the gettext/locale environment.
* This method will change some env vars and locale settings; the
* restoreEnvironment should put them all back :)
*
* @return void
* @throws BuildException - if locale cannot be set.
* @see restoreEnvironment()
*/
protected function initEnvironment() {
$this->storedLocale = getenv("LANG");
$this->log("Setting locale to " . $this->locale, Project::MSG_DEBUG);
putenv("LANG=".$this->locale);
$ret = setlocale(LC_ALL, $this->locale);
if ($ret === false) {
$msg = "Could not set locale to " . $this->locale
. ". You may need to use fully qualified name"
. " (e.g. en_US instead of en).";
throw new BuildException($msg);
}
$this->log("Binding domain '".$this->domain."' to " . $this->dir, Project::MSG_DEBUG);
bindtextdomain($this->domain, $this->dir->getAbsolutePath());
textdomain($this->domain);
}
/**
* Restores environment settings and locale.
* This does _not_ restore any gettext-specific settings
* (e.g. textdomain()).
*
* @return void
*/
protected function restoreEnvironment() {
putenv("LANG=".$this->storedLocale);
setlocale(LC_ALL, $this->storedLocale);
}
/**
* Performs gettext translation of msgid and returns translated text.
*
* This function simply wraps gettext() call, but provides ability to log
* string replacements. (alternative would be using preg_replace with /e which
* would probably be faster, but no ability to debug/log.)
*
* @param array $matches Array of matches; we're interested in $matches[2].
* @return string Translated text
*/
private function xlateStringCallback($matches) {
$charbefore = $matches[1];
$msgid = $matches[2];
$translated = gettext($msgid);
$this->log("Translating \"$msgid\" => \"$translated\"", Project::MSG_DEBUG);
return $charbefore . '"' . $translated . '"';
}
/**
* Returns the filtered stream.
* The original stream is first read in fully, and then translation is performed.
*
* @return mixed the filtered stream, or -1 if the end of the resulting stream has been reached.
*
* @throws IOException - if the underlying stream throws an IOException during reading
* @throws BuildException - if the correct params are not supplied
*/
function read($len = null) {
if ( !$this->getInitialized() ) {
$this->_initialize();
$this->setInitialized(true);
}
// Make sure correct params/attribs have been set
$this->checkAttributes();
$buffer = $this->in->read($len);
if($buffer === -1) {
return -1;
}
// Setup the locale/gettext environment
$this->initEnvironment();
// replace any occurrences of _("") or gettext("") with
// the translated value.
//
// ([^\w]|^)_\("((\\"|[^"])*)"\)
// --$1--- -----$2----
// ---$3-- [match escaped quotes or any char that's not a quote]
//
// also match gettext() -- same as above
$buffer = preg_replace_callback('/([^\w]|^)_\("((\\\"|[^"])*)"\)/', array($this, 'xlateStringCallback'), $buffer);
$buffer = preg_replace_callback('/([^\w]|^)gettext\("((\\\"|[^"])*)"\)/', array($this, 'xlateStringCallback'), $buffer);
// Check to see if there are any _('') calls and flag an error
// Check to see if there are any unmatched gettext() calls -- and flag an error
$matches = array();
if (preg_match('/([^\w]|^)(gettext\([^\)]+\))/', $buffer, $matches)) {
$this->log("Unable to perform translation on: " . $matches[2], Project::MSG_WARN);
}
$this->restoreEnvironment();
return $buffer;
}
/**
* Creates a new TranslateGettext filter using the passed in
* Reader for instantiation.
*
* @param Reader $reader A Reader object providing the underlying stream.
* Must not be <code>null</code>.
*
* @return TranslateGettext A new filter based on this configuration, but filtering
* the specified reader
*/
function chain(Reader $reader) {
$newFilter = new TranslateGettext($reader);
$newFilter->setProject($this->getProject());
$newFilter->setDomain($this->getDomain());
$newFilter->setLocale($this->getLocale());
$newFilter->setDir($this->getDir());
return $newFilter;
}
/**
* Parses the parameters if this filter is being used in "generic" mode.
*/
private function _initialize() {
$params = $this->getParameters();
if ( $params !== null ) {
foreach($params as $param) {
switch($param->getType()) {
case self::DOMAIN_KEY:
$this->setDomain($param->getValue());
break;
case self::DIR_KEY:
$this->setDir($this->project->resolveFile($param->getValue()));
break;
case self::LOCALE_KEY:
$this->setLocale($param->getValue());
break;
} // switch
}
} // if params !== null
}
}

View file

@ -0,0 +1,176 @@
<?php
/*
* $Id: XincludeFilter.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/filters/BaseParamFilterReader.php';
include_once 'phing/filters/ChainableReader.php';
/**
* Applies Xinclude parsing to incoming text.
*
* Uses PHP DOM XML support
*
* @author Bill Karwin <bill@karwin.com>
* @version $Id: XincludeFilter.php 905 2010-10-05 16:28:03Z mrook $
* @see FilterReader
* @package phing.filters
*/
class XincludeFilter extends BaseParamFilterReader implements ChainableReader {
private $basedir = null;
/**
* @var bool
*/
private $processed = false;
/**
* Whether to resolve entities.
*
* @var bool
*
* @since 2.4
*/
private $resolveExternals = false;
/**
* Whether to resolve entities.
*
* @param $resolveExternals
*
* @since 2.4
*/
public function setResolveExternals($resolveExternals)
{
$this->resolveExternals = (bool)$resolveExternals;
}
/**
* @return bool
*
* @since 2.4
*/
public function getResolveExternals()
{
return $this->resolveExternals;
}
public function setBasedir(PhingFile $dir)
{
$this->basedir = $dir;
}
public function getBasedir()
{
return $this->basedir;
}
/**
* Reads stream, applies XSLT and returns resulting stream.
* @return string transformed buffer.
* @throws BuildException - if XSLT support missing, if error in xslt processing
*/
function read($len = null) {
if (!class_exists('DomDocument')) {
throw new BuildException("Could not find the DomDocument class. Make sure PHP has been compiled/configured to support DOM XML.");
}
if ($this->processed === true) {
return -1; // EOF
}
// Read XML
$_xml = null;
while ( ($data = $this->in->read($len)) !== -1 )
$_xml .= $data;
if ($_xml === null ) { // EOF?
return -1;
}
if (empty($_xml)) {
$this->log("XML file is empty!", Project::MSG_WARN);
return '';
}
$this->log("Transforming XML " . $this->in->getResource() . " using Xinclude ", Project::MSG_VERBOSE);
$out = '';
try {
$out = $this->process($_xml);
$this->processed = true;
} catch (IOException $e) {
throw new BuildException($e);
}
return $out;
}
/**
* Try to process the Xinclude transformation
*
* @param string XML to process.
*
* @throws BuildException On errors
*/
protected function process($xml) {
if ($this->basedir) {
$cwd = getcwd();
chdir($this->basedir);
}
// Create and setup document.
$xmlDom = new DomDocument();
$xmlDom->resolveExternals = $this->resolveExternals;
$xmlDom->loadXML($xml);
$xmlDom->xinclude();
if ($this->basedir) {
chdir($cwd);
}
return $xmlDom->saveXML();
}
/**
* Creates a new XincludeFilter using the passed in
* Reader for instantiation.
*
* @param Reader A Reader object providing the underlying stream.
* Must not be <code>null</code>.
*
* @return Reader A new filter based on this configuration, but filtering
* the specified reader
*/
function chain(Reader $reader) {
$newFilter = new XincludeFilter($reader);
$newFilter->setProject($this->getProject());
$newFilter->setBasedir($this->getBasedir());
return $newFilter;
}
}

View file

@ -0,0 +1,408 @@
<?php
/*
* $Id: XsltFilter.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/filters/BaseParamFilterReader.php';
include_once 'phing/filters/ChainableReader.php';
/**
* Applies XSL stylesheet to incoming text.
*
* Uses PHP XSLT support (libxslt).
*
* @author Hans Lellelid <hans@velum.net>
* @author Yannick Lecaillez <yl@seasonfive.com>
* @author Andreas Aderhold <andi@binarycloud.com>
* @version $Id: XsltFilter.php 905 2010-10-05 16:28:03Z mrook $
* @see FilterReader
* @package phing.filters
*/
class XsltFilter extends BaseParamFilterReader implements ChainableReader {
/**
* Path to XSL stylesheet.
* @var string
*/
private $xslFile = null;
/**
* Whether XML file has been transformed.
* @var boolean
*/
private $processed = false;
/**
* XSLT Params.
* @var array
*/
private $xsltParams = array();
/**
* Whether to use loadHTML() to parse the input XML file.
*/
private $html = false;
/**
* Whether to resolve entities in the XML document (see
* {@link http://www.php.net/manual/en/class.domdocument.php#domdocument.props.resolveexternals}
* for more details).
*
* @var bool
*
* @since 2.4
*/
private $resolveDocumentExternals = false;
/**
* Whether to resolve entities in the stylesheet.
*
* @var bool
*
* @since 2.4
*/
private $resolveStylesheetExternals = false;
/**
* Create new XSLT Param object, to handle the <param/> nested element.
* @return XSLTParam
*/
function createParam() {
$num = array_push($this->xsltParams, new XSLTParam());
return $this->xsltParams[$num-1];
}
/**
* Sets the XSLT params for this class.
* This is used to "clone" this class, in the chain() method.
* @param array $params
*/
function setParams($params) {
$this->xsltParams = $params;
}
/**
* Returns the XSLT params set for this class.
* This is used to "clone" this class, in the chain() method.
* @return array
*/
function getParams() {
return $this->xsltParams;
}
/**
* Set the XSLT stylesheet.
* @param mixed $file PhingFile object or path.
*/
function setStyle(PhingFile $file) {
$this->xslFile = $file;
}
/**
* Whether to use HTML parser for the XML.
* This is supported in libxml2 -- Yay!
* @return boolean
*/
function getHtml() {
return $this->html;
}
/**
* Whether to use HTML parser for XML.
* @param boolean $b
*/
function setHtml($b) {
$this->html = (boolean) $b;
}
/**
* Get the path to XSLT stylesheet.
* @return mixed XSLT stylesheet path.
*/
function getStyle() {
return $this->xslFile;
}
/**
* Whether to resolve entities in document.
*
* @param bool $resolveExternals
*
* @since 2.4
*/
function setResolveDocumentExternals($resolveExternals) {
$this->resolveDocumentExternals = (bool)$resolveExternals;
}
/**
* @return bool
*
* @since 2.4
*/
function getResolveDocumentExternals() {
return $this->resolveDocumentExternals;
}
/**
* Whether to resolve entities in stylesheet.
*
* @param bool $resolveExternals
*
* @since 2.4
*/
function setResolveStylesheetExternals($resolveExternals) {
$this->resolveStylesheetExternals = (bool)$resolveExternals;
}
/**
* @return bool
*
* @since 2.4
*/
function getResolveStylesheetExternals() {
return $this->resolveStylesheetExternals;
}
/**
* Reads stream, applies XSLT and returns resulting stream.
* @return string transformed buffer.
* @throws BuildException - if XSLT support missing, if error in xslt processing
*/
function read($len = null) {
if (!class_exists('XSLTProcessor')) {
throw new BuildException("Could not find the XSLTProcessor class. Make sure PHP has been compiled/configured to support XSLT.");
}
if ($this->processed === true) {
return -1; // EOF
}
if ( !$this->getInitialized() ) {
$this->_initialize();
$this->setInitialized(true);
}
// Read XML
$_xml = null;
while ( ($data = $this->in->read($len)) !== -1 )
$_xml .= $data;
if ($_xml === null ) { // EOF?
return -1;
}
if(empty($_xml)) {
$this->log("XML file is empty!", Project::MSG_WARN);
return ''; // return empty string, don't attempt to apply XSLT
}
// Read XSLT
$_xsl = null;
$xslFr = new FileReader($this->xslFile);
$xslFr->readInto($_xsl);
$this->log("Tranforming XML " . $this->in->getResource() . " using style " . $this->xslFile->getPath(), Project::MSG_VERBOSE);
$out = '';
try {
$out = $this->process($_xml, $_xsl);
$this->processed = true;
} catch (IOException $e) {
throw new BuildException($e);
}
return $out;
}
// {{{ method _ProcessXsltTransformation($xml, $xslt) throws BuildException
/**
* Try to process the XSLT transformation
*
* @param string XML to process.
* @param string XSLT sheet to use for the processing.
*
* @throws BuildException On XSLT errors
*/
protected function process($xml, $xsl) {
$processor = new XSLTProcessor();
// Create and setup document.
$xmlDom = new DOMDocument();
$xmlDom->resolveExternals = $this->resolveDocumentExternals;
// Create and setup stylesheet.
$xslDom = new DOMDocument();
$xslDom->resolveExternals = $this->resolveStylesheetExternals;
if ($this->html) {
$xmlDom->loadHTML($xml);
} else {
$xmlDom->loadXML($xml);
}
$xslDom->loadxml($xsl);
$processor->importStylesheet($xslDom);
// ignoring param "type" attrib, because
// we're only supporting direct XSL params right now
foreach($this->xsltParams as $param) {
$this->log("Setting XSLT param: " . $param->getName() . "=>" . $param->getExpression(), Project::MSG_DEBUG);
$processor->setParameter(null, $param->getName(), $param->getExpression());
}
$errorlevel = error_reporting();
error_reporting($errorlevel & ~E_WARNING);
@$result = $processor->transformToXML($xmlDom);
error_reporting($errorlevel);
if (false === $result) {
//$errno = xslt_errno($processor);
//$err = xslt_error($processor);
throw new BuildException("XSLT Error");
} else {
return $result;
}
}
/**
* Creates a new XsltFilter using the passed in
* Reader for instantiation.
*
* @param Reader A Reader object providing the underlying stream.
* Must not be <code>null</code>.
*
* @return Reader A new filter based on this configuration, but filtering
* the specified reader
*/
function chain(Reader $reader) {
$newFilter = new XsltFilter($reader);
$newFilter->setProject($this->getProject());
$newFilter->setStyle($this->getStyle());
$newFilter->setInitialized(true);
$newFilter->setParams($this->getParams());
$newFilter->setHtml($this->getHtml());
return $newFilter;
}
/**
* Parses the parameters to get stylesheet path.
*/
private function _initialize() {
$params = $this->getParameters();
if ( $params !== null ) {
for($i = 0, $_i=count($params) ; $i < $_i; $i++) {
if ( $params[$i]->getType() === null ) {
if ($params[$i]->getName() === "style") {
$this->setStyle($params[$i]->getValue());
}
} elseif ($params[$i]->getType() == "param") {
$xp = new XSLTParam();
$xp->setName($params[$i]->getName());
$xp->setExpression($params[$i]->getValue());
$this->xsltParams[] = $xp;
}
}
}
}
}
/**
* Class that holds an XSLT parameter.
*
* @package phing.filters
*/
class XSLTParam {
private $name;
private $expr;
/**
* Sets param name.
* @param string $name
*/
public function setName($name) {
$this->name = $name;
}
/**
* Get param name.
* @return string
*/
public function getName() {
return $this->name;
}
/**
* Sets expression value (alias to the setExpression()) method.
*
* @param string $v
* @see setExpression()
*/
public function setValue($v)
{
$this->setExpression($v);
}
/**
* Gets expression value (alias to the getExpression()) method.
*
* @param string $v
* @see getExpression()
*/
public function getValue()
{
return $this->getExpression();
}
/**
* Sets expression value.
* @param string $expr
*/
public function setExpression($expr) {
$this->expr = $expr;
}
/**
* Sets expression to dynamic register slot.
* @param RegisterSlot $expr
*/
public function setListeningExpression(RegisterSlot $expr) {
$this->expr = $expr;
}
/**
* Returns expression value -- performs lookup if expr is registerslot.
* @return string
*/
public function getExpression() {
if ($this->expr instanceof RegisterSlot) {
return $this->expr->getValue();
} else {
return $this->expr;
}
}
}

View file

@ -0,0 +1,183 @@
<?php
/*
* $Id: ChainReaderHelper.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/Project.php';
include_once 'phing/filters/BaseFilterReader.php';
include_once 'phing/types/PhingFilterReader.php';
include_once 'phing/types/FilterChain.php';
include_once 'phing/types/Parameter.php';
include_once 'phing/util/FileUtils.php';
include_once 'phing/util/StringHelper.php';
include_once 'phing/filters/ChainableReader.php';
/**
* Process a FilterReader chain.
*
* Here, the interesting method is 'getAssembledReader'.
* The purpose of this one is to create a simple Reader object which
* apply all filters on another primary Reader object.
*
* For example : In copyFile (phing.util.FileUtils) the primary Reader
* is a FileReader object (more accuratly, a BufferedReader) previously
* setted for the source file to copy. So, consider this filterchain :
*
* <filterchain>
* <stripphpcomments />
* <linecontains>
* <contains value="foo">
* </linecontains>
* <tabtospaces tablength="8" />
* </filterchain>
*
* getAssembledReader will return a Reader object wich read on each
* of these filters. Something like this : ('->' = 'which read data from') :
*
* [TABTOSPACES] -> [LINECONTAINS] -> [STRIPPHPCOMMENTS] -> [FILEREADER]
* (primary reader)
*
* So, getAssembledReader will return the TABTOSPACES Reader object. Then
* each read done with this Reader object will follow this path.
*
* Hope this explanation is clear :)
*
* TODO: Implement the classPath feature.
*
* @author <a href="mailto:yl@seasonfive.com">Yannick Lecaillez</a>
* @version $Revision: 905 $ $Date: 2010-10-05 18:28:03 +0200 (Tue, 05 Oct 2010) $
* @access public
* @package phing.filters.util
*/
class ChainReaderHelper {
/** Primary reader to wich the reader chain is to be attached */
private $primaryReader = null;
/** The site of the buffer to be used. */
private $bufferSize = 8192;
/** Chain of filters */
private $filterChains = array();
/** The Phing project */
private $project;
/*
* Sets the primary reader
*/
function setPrimaryReader(Reader $reader) {
$this->primaryReader = $reader;
}
/*
* Set the project to work with
*/
function setProject(Project $project) {
$this->project = $project;
}
/*
* Get the project
*/
function getProject() {
return $this->project;
}
/*
* Sets the buffer size to be used. Defaults to 8192,
* if this method is not invoked.
*/
function setBufferSize($size) {
$this->bufferSize = $size;
}
/*
* Sets the collection of filter reader sets
*/
function setFilterChains(&$fchain) {
$this->filterChains = &$fchain;
}
/*
* Assemble the reader
*/
function getAssembledReader() {
$instream = $this->primaryReader;
$filterReadersCount = count($this->filterChains);
$finalFilters = array();
// Collect all filter readers of all filter chains used ...
for($i = 0 ; $i<$filterReadersCount ; $i++) {
$filterchain = &$this->filterChains[$i];
$filterReaders = $filterchain->getFilterReaders();
$readerCount = count($filterReaders);
for($j = 0 ; $j<$readerCount ; $j++) {
$finalFilters[] = $filterReaders[$j];
}
}
// ... then chain the filter readers.
$filtersCount = count($finalFilters);
if ( $filtersCount > 0 ) {
for($i = 0 ; $i<$filtersCount ; $i++) {
$filter = $finalFilters[$i];
if ( $filter instanceof PhingFilterReader ) {
// This filter reader is an external class.
$className = $filter->getClassName();
$classpath = $filter->getClasspath();
$project = $filter->getProject();
if ( $className !== null ) {
$cls = Phing::import($className, $classpath);
$impl = new $cls();
}
if ( !($impl instanceof FilterReader) ) {
throw new Exception($className." does not extend phing.system.io.FilterReader");
}
$impl->setReader($instream); // chain
$impl->setProject($this->getProject()); // what about $project above ?
if ( $impl instanceof Parameterizable ) {
$impl->setParameters($filter->getParams());
}
$instream = $impl; // now that it's been chained
} elseif (($filter instanceof ChainableReader) && ($filter instanceof Reader)) {
if ( $this->getProject() !== null && ($filter instanceof BaseFilterReader) ) {
$filter->setProject($this->getProject());
}
$instream = $filter->chain($instream);
} else {
throw new Exception("Cannot chain invalid filter: " . get_class($filter));
}
}
}
return $instream;
}
}

View file

@ -0,0 +1,97 @@
<?php
/*
* $Id: IniFileTokenReader.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/types/TokenReader.php';
include_once 'phing/system/io/IOException.php';
include_once 'phing/filters/ReplaceTokens.php'; // For class Token
/**
* Class that allows reading tokens from INI files.
*
* @author Manuel Holtgewe
* @version $Revision: 905 $
* @package phing.filters.util
*/
class IniFileTokenReader extends TokenReader {
/**
* Holds the path to the INI file that is to be read.
* @var object Reference to a PhingFile Object representing
* the path to the INI file.
*/
private $file = null;
/**
* @var string Sets the section to load from the INI file.
* if omitted, all sections are loaded.
*/
private $section = null;
/**
* Reads the next token from the INI file
*
* @throws IOException On error
* @return Token
*/
function readToken() {
if ($this->file === null) {
throw new BuildException("No File set for IniFileTokenReader");
}
static $tokens = null;
if ($tokens === null) {
$tokens = array();
$arr = parse_ini_file($this->file->getAbsolutePath(), true);
if ($this->section === null) {
foreach ($arr as $sec_name => $values) {
foreach($arr[$sec_name] as $key => $value) {
$tok = new Token;
$tok->setKey($key);
$tok->setValue($value);
$tokens[] = $tok;
}
}
} else if (isset($arr[$this->section])) {
foreach ($arr[$this->section] as $key => $value) {
$tok = new Token;
$tok->setKey($key);
$tok->setValue($value);
$tokens[] = $tok;
}
}
}
if (count($tokens) > 0) {
return array_pop($tokens);
} else
return null;
}
function setFile(PhingFile $file) {
$this->file = $file;
}
function setSection($str) {
$this->section = (string) $str;
}
}

View file

@ -0,0 +1,81 @@
<?php
/*
* $Id: DefaultInputHandler.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>.
*/
require_once 'phing/input/InputHandler.php';
include_once 'phing/system/io/ConsoleReader.php';
/**
* Prompts using print(); reads input from Console.
*
* @author Hans Lellelid <hans@xmpl.org> (Phing)
* @author Stefan Bodewig <stefan.bodewig@epost.de> (Ant)
* @version $Revision: 905 $
* @package phing.input
*/
class DefaultInputHandler implements InputHandler {
/**
* Prompts and requests input. May loop until a valid input has
* been entered.
* @throws BuildException
*/
public function handleInput(InputRequest $request) {
$prompt = $this->getPrompt($request);
$in = new ConsoleReader();
do {
print $prompt;
try {
$input = $in->readLine();
if ($input === "" && ($request->getDefaultValue() !== null) ) {
$input = $request->getDefaultValue();
}
$request->setInput($input);
} catch (Exception $e) {
throw new BuildException("Failed to read input from Console.", $e);
}
} while (!$request->isInputValid());
}
/**
* Constructs user prompt from a request.
*
* <p>This implementation adds (choice1,choice2,choice3,...) to the
* prompt for <code>MultipleChoiceInputRequest</code>s.</p>
*
* @param $request the request to construct the prompt for.
* Must not be <code>null</code>.
*/
protected function getPrompt(InputRequest $request) {
$prompt = $request->getPrompt();
if ($request instanceof YesNoInputRequest) {
$prompt .= '(' . implode('/', $request->getChoices()) .')';
} elseif ($request instanceof MultipleChoiceInputRequest) { // (a,b,c,d)
$prompt .= '(' . implode(',', $request->getChoices()) . ')';
}
if ($request->getDefaultValue() !== null) {
$prompt .= ' ['.$request->getDefaultValue().']';
}
$pchar = $request->getPromptChar();
return $prompt . ($pchar ? $pchar . ' ' : ' ');
}
}

View file

@ -0,0 +1,45 @@
<?php
/*
* $Id: InputHandler.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>.
*/
/**
* Plugin to Phing to handle requests for user input.
*
* @author Stefan Bodewig <stefan.bodewig@epost.de>
* @version $Revision: 905 $
* @package phing.input
*/
interface InputHandler {
/**
* Handle the request encapsulated in the argument.
*
* <p>Precondition: the request.getPrompt will return a non-null
* value.</p>
*
* <p>Postcondition: request.getInput will return a non-null
* value, request.isInputValid will return true.</p>
* @return void
* @throws BuildException
*/
public function handleInput(InputRequest $request);
}

View file

@ -0,0 +1,107 @@
<?php
/*
* $Id: InputRequest.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>.
*/
/**
* Encapsulates an input request.
*
* @author Hans Lellelid <hans@xmpl.org> (Phing)
* @author Stefan Bodewig <stefan.bodewig@epost.de> (Ant)
* @version $Revision: 905 $
* @package phing.input
*/
class InputRequest {
protected $prompt;
protected $input;
protected $defaultValue;
protected $promptChar;
/**
* @param string $prompt The prompt to show to the user. Must not be null.
*/
public function __construct($prompt) {
if ($prompt === null) {
throw new BuildException("prompt must not be null");
}
$this->prompt = $prompt;
}
/**
* Retrieves the prompt text.
*/
public function getPrompt() {
return $this->prompt;
}
/**
* Sets the user provided input.
*/
public function setInput($input) {
$this->input = $input;
}
/**
* Is the user input valid?
*/
public function isInputValid() {
return true;
}
/**
* Retrieves the user input.
*/
public function getInput() {
return $this->input;
}
/**
* Set the default value to use.
* @param mixed $v
*/
public function setDefaultValue($v) {
$this->defaultValue = $v;
}
/**
* Return the default value to use.
* @return mixed
*/
public function getDefaultValue() {
return $this->defaultValue;
}
/**
* Set the default value to use.
* @param string $c
*/
public function setPromptChar($c) {
$this->promptChar = $c;
}
/**
* Return the default value to use.
* @return string
*/
public function getPromptChar() {
return $this->promptChar;
}
}

View file

@ -0,0 +1,58 @@
<?php
/*
* $Id: MultipleChoiceInputRequest.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>.
*/
require_once 'phing/input/InputRequest.php';
/**
* Encapsulates an input request.
*
* @author Stefan Bodewig <stefan.bodewig@epost.de>
* @version $Revision: 905 $
* @package phing.input
*/
class MultipleChoiceInputRequest extends InputRequest {
protected $choices = array();
/**
* @param string $prompt The prompt to show to the user. Must not be null.
* @param array $choices holds all input values that are allowed.
* Must not be null.
*/
public function __construct($prompt, $choices) {
parent::__construct($prompt);
$this->choices = $choices;
}
/**
* @return The possible values.
*/
public function getChoices() {
return $this->choices;
}
/**
* @return true if the input is one of the allowed values.
*/
public function isInputValid() {
return in_array($this->getInput(), $this->choices); // not strict (?)
}
}

View file

@ -0,0 +1,47 @@
<?php
/*
* $Id: YesNoInputRequest.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>.
*/
require_once 'phing/input/MultipleChoiceInputRequest.php';
/**
* Encapsulates an input request that returns a boolean (yes/no).
*
* @author Hans Lellelid <hans@xmpl.org>
* @version $Revision: 905 $
* @package phing.input
*/
class YesNoInputRequest extends MultipleChoiceInputRequest {
/**
* @return true if the input is one of the allowed values.
*/
public function isInputValid() {
return StringHelper::isBoolean($this->input);
}
/**
* Converts input to boolean.
* @return boolean
*/
public function getInput() {
return StringHelper::booleanValue($this->input);
}
}

267
3rd_party/php/phing/lib/Capsule.php vendored Normal file
View file

@ -0,0 +1,267 @@
<?php
/**
* Capsule is a simple "template" engine that essentially provides an isolated context
* for PHP scripts.
*
* There is no special templating language, and therefore no limitations to what
* can be accomplished within templates. The main purpose of Capsule is to separate
* the business logic from display / output logic.
*
* @author Hans Lellelid <hans@xmpl.org>
* @version $Revision: 905 $
* @package phing.lib
*/
class Capsule {
/**
* Look for templates here (if relative path provided).
* @var string
*/
protected $templatePath;
/**
* Where should output files be written?
* (This is named inconsistently to be compatible w/ Texen.)
* @var string
*/
protected $outputDirectory;
/**
* The variables that can be used by the templates.
* @var array Hash of variables.
*/
public $vars = array();
/**
* Has template been initialized.
*/
protected $initialized = false;
/**
* Stores the pre-parse() include_path.
* @var string
*/
private $old_include_path;
function __construct() {
}
/**
* Clears one or several or all variables.
* @param mixed $which String name of var, or array of names.
* @return void
*/
function clear($which = null) {
if ($which === null) {
$this->vars = array();
} elseif (is_array($which)) {
foreach($which as $var) {
unset($this->vars[$var]);
}
} else {
unset($this->vars[$which]);
}
}
/**
* Set the basepath to use for template lookups.
* @param string $v
*/
function setTemplatePath($v) {
$this->templatePath = rtrim($v, DIRECTORY_SEPARATOR.'/');
}
/**
* Get the basepath to use for template lookups.
* @return string
*/
function getTemplatePath() {
return $this->templatePath;
}
/**
* Set a basepath to use for output file creation.
* @param string $v
*/
function setOutputDirectory($v) {
$this->outputDirectory = rtrim($v, DIRECTORY_SEPARATOR.'/');
}
/**
* Get basepath to use for output file creation.
* @return string
*/
function getOutputDirectory() {
return $this->outputDirectory;
}
/**
* Low overhead (no output buffering) method to simply dump template
* to buffer.
*
* @param string $__template
* @return void
* @throws Exception - if template cannot be found
*/
function display($__template) {
// Prepend "private" variable names with $__ in this function
// to keep namespace conflict potential to a minimum.
// Alias this class to $generator.
$generator = $this;
if (isset($this->vars['this'])) {
throw new Exception("Assigning a variable named \$this to a context conflicts with class namespace.");
}
// extract variables into local namespace
extract($this->vars);
// prepend template path to include path,
// so that include "path/relative/to/templates"; can be used within templates
$__old_inc_path = ini_get('include_path');
ini_set('include_path', $this->templatePath . PATH_SEPARATOR . $__old_inc_path);
@ini_set('track_errors', true);
include $__template;
@ini_restore('track_errors');
// restore the include path
ini_set('include_path', $__old_inc_path);
if (!empty($php_errormsg)) {
throw new Exception("Unable to parse template " . $__template . ": " . $php_errormsg);
}
}
/**
* Fetches the results of a tempalte parse and either returns
* the string or writes results to a specified output file.
*
* @param string $template The template filename (relative to templatePath or absolute).
* @param string $outputFile If specified, contents of template will also be written to this file.
* @param boolean $append Should output be appended to source file?
* @return string The "parsed" template output.
* @throws Exception - if template not found.
*/
function parse($template, $outputFile = null, $append = false) {
// main work done right here:
// hopefully this works recursively ... fingers crossed.
ob_start();
try {
$this->display($template);
} catch (Exception $e) {
ob_end_flush(); // flush the output on error (so we can see up to what point it parsed everything)
throw $e;
}
$output = ob_get_contents();
ob_end_clean();
if ($outputFile !== null) {
$outputFile = $this->resolvePath($outputFile, $this->outputDirectory);
$flags = null;
if ($append) $flags = FILE_APPEND;
if (!file_put_contents($outputFile, $output, $flags) && $output != "") {
throw new Exception("Unable to write output to " . $outputFile);
}
}
return $output;
}
/**
* This returns a "best guess" path for the given file.
*
* @param string $file File name or possibly absolute path.
* @param string $basepath The basepath that should be prepended if $file is not absolute.
* @return string "Best guess" path for this file.
*/
protected function resolvePath($file, $basepath) {
if ( !($file{0} == DIRECTORY_SEPARATOR || $file{0} == '/')
// also account for C:\ style path
&& !($file{1} == ':' && ($file{2} == DIRECTORY_SEPARATOR || $file{2} == '/'))) {
if ($basepath != null) {
$file = $basepath . DIRECTORY_SEPARATOR . $file;
}
}
return $file;
}
/**
* Gets value of specified var or NULL if var has not been put().
* @param string $name Variable name to retrieve.
* @return mixed
*/
function get($name) {
if (!isset($this->vars[$name])) return null;
return $this->vars[$name];
}
/**
* Merges in passed hash to vars array.
*
* Given an array like:
*
* array( 'myvar' => 'Hello',
* 'myvar2' => 'Hello')
*
* Resulting template will have access to $myvar and $myvar2.
*
* @param array $vars
* @param boolean $recursiveMerge Should matching keys be recursively merged?
* @return void
*/
function putAll($vars, $recursiveMerge = false) {
if ($recursiveMerge) {
$this->vars = array_merge_recursive($this->vars, $vars);
} else {
$this->vars = array_merge($this->vars, $vars);
}
}
/**
* Adds a variable to the context.
*
* Resulting template will have access to ${$name$} variable.
*
* @param string $name
* @param mixed $value
*/
function put($name, $value) {
$this->vars[$name] = $value;
}
/**
* Put a variable into the context, assigning it by reference.
* This means that if the template modifies the variable, then it
* will also be modified in the context.
*
* @param $name
* @param &$value
*/
function putRef($name, &$value) {
$this->vars[$name] = &$value;
}
/**
* Makes a copy of the value and puts it into the context.
* This is primarily to force copying (cloning) of objects, rather
* than the default behavior which is to assign them by reference.
* @param string $name
* @param mixed $value
*/
function putCopy($name, $value) {
if (is_object($value)) {
$value = clone $value;
}
$this->vars[$name] = $value;
}
}

View file

@ -0,0 +1,234 @@
<?php
/*
* $Id: AnsiColorLogger.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>.
*/
require_once 'phing/listener/DefaultLogger.php';
include_once 'phing/system/util/Properties.php';
/**
* Uses ANSI Color Code Sequences to colorize messages
* sent to the console.
*
* If used with the -logfile option, the output file
* will contain all the necessary escape codes to
* display the text in colorized mode when displayed
* in the console using applications like cat, more,
* etc.
*
* This is designed to work on terminals that support ANSI
* color codes. It works on XTerm, ETerm, Mindterm, etc.
* It also works on Win9x (with ANSI.SYS loaded.)
*
* NOTE:
* It doesn't work on WinNT's COMMAND.COM even with
* ANSI.SYS loaded.
*
* The default colors used for differentiating
* the message levels can be changed by editing the
* phing/listener/defaults.properties file.
*
* This file contains 5 key/value pairs:
* AnsiColorLogger.ERROR_COLOR=2;31
* AnsiColorLogger.WARNING_COLOR=2;35
* AnsiColorLogger.INFO_COLOR=2;36
* AnsiColorLogger.VERBOSE_COLOR=2;32
* AnsiColorLogger.DEBUG_COLOR=2;34
*
* Another option is to pass a system variable named
* ant.logger.defaults, with value set to the path of
* the file that contains user defined Ansi Color
* Codes, to the <B>java</B> command using -D option.
*
* To change these colors use the following chart:
*
* <B>ANSI COLOR LOGGER CONFIGURATION</B>
*
* Format for AnsiColorLogger.*=
* Attribute;Foreground;Background
*
* Attribute is one of the following:
* 0 -> Reset All Attributes (return to normal mode)
* 1 -> Bright (Usually turns on BOLD)
* 2 -> Dim
* 3 -> Underline
* 5 -> link
* 7 -> Reverse
* 8 -> Hidden
*
* Foreground is one of the following:
* 30 -> Black
* 31 -> Red
* 32 -> Green
* 33 -> Yellow
* 34 -> Blue
* 35 -> Magenta
* 36 -> Cyan
* 37 -> White
*
* Background is one of the following:
* 40 -> Black
* 41 -> Red
* 42 -> Green
* 43 -> Yellow
* 44 -> Blue
* 45 -> Magenta
* 46 -> Cyan
* 47 -> White
*
* @author Hans Lellelid <hans@xmpl.org> (Phing)
* @author Magesh Umasankar (Ant)
* @package phing.listener
* @version $Revision: 905 $
*/
class AnsiColorLogger extends DefaultLogger {
const ATTR_NORMAL = 0;
const ATTR_BRIGHT = 1;
const ATTR_DIM = 2;
const ATTR_UNDERLINE = 3;
const ATTR_BLINK = 5;
const ATTR_REVERSE = 7;
const ATTR_HIDDEN = 8;
const FG_BLACK = 30;
const FG_RED = 31;
const FG_GREEN = 32;
const FG_YELLOW = 33;
const FG_BLUE = 34;
const FG_MAGENTA = 35;
const FG_CYAN = 36;
const FG_WHITE = 37;
const BG_BLACK = 40;
const BG_RED = 41;
const BG_GREEN = 42;
const BG_YELLOW = 44;
const BG_BLUE = 44;
const BG_MAGENTA = 45;
const BG_CYAN = 46;
const BG_WHITE = 47;
const PREFIX = "\x1b[";
const SUFFIX = "m";
const SEPARATOR = ';';
const END_COLOR = "\x1b[m"; // self::PREFIX . self::SUFFIX;
private $errColor;
private $warnColor;
private $infoColor;
private $verboseColor;
private $debugColor;
private $colorsSet = false;
/**
* Construct new AnsiColorLogger
* Perform initializations that cannot be done in var declarations.
*/
public function __construct() {
parent::__construct();
$this->errColor = self::PREFIX . self::ATTR_NORMAL . self::SEPARATOR . self::FG_RED . self::SUFFIX;
$this->warnColor = self::PREFIX . self::ATTR_NORMAL . self::SEPARATOR . self::FG_MAGENTA . self::SUFFIX;
$this->infoColor = self::PREFIX . self::ATTR_NORMAL . self::SEPARATOR . self::FG_CYAN . self::SUFFIX;
$this->verboseColor = self::PREFIX . self::ATTR_NORMAL . self::SEPARATOR . self::FG_GREEN . self::SUFFIX;
$this->debugColor = self::PREFIX . self::ATTR_NORMAL . self::SEPARATOR . self::FG_BLUE . self::SUFFIX;
}
/**
* Set the colors to use from a property file specified by the
* special ant property ant.logger.defaults
*/
private final function setColors() {
$userColorFile = Phing::getProperty("phing.logger.defaults");
$systemColorFile = new PhingFile(Phing::getResourcePath("phing/listener/defaults.properties"));
$in = null;
try {
$prop = new Properties();
if ($userColorFile !== null) {
$prop->load($userColorFile);
} else {
$prop->load($systemColorFile);
}
$err = $prop->getProperty("AnsiColorLogger.ERROR_COLOR");
$warn = $prop->getProperty("AnsiColorLogger.WARNING_COLOR");
$info = $prop->getProperty("AnsiColorLogger.INFO_COLOR");
$verbose = $prop->getProperty("AnsiColorLogger.VERBOSE_COLOR");
$debug = $prop->getProperty("AnsiColorLogger.DEBUG_COLOR");
if ($err !== null) {
$this->errColor = self::PREFIX . $err . self::SUFFIX;
}
if ($warn !== null) {
$this->warnColor = self::PREFIX . $warn . self::SUFFIX;
}
if ($info !== null) {
$this->infoColor = self::PREFIX . $info . self::SUFFIX;
}
if ($verbose !== null) {
$this->verboseColor = self::PREFIX . $verbose . self::SUFFIX;
}
if ($debug !== null) {
$this->debugColor = self::PREFIX . $debug . self::SUFFIX;
}
} catch (IOException $ioe) {
//Ignore exception - we will use the defaults.
}
}
/**
* @see DefaultLogger#printMessage
* @param string $message
* @param OutputStream $stream
* @param int $priority
*/
protected final function printMessage($message, OutputStream $stream, $priority) {
if ($message !== null) {
if (!$this->colorsSet) {
$this->setColors();
$this->colorsSet = true;
}
switch ($priority) {
case Project::MSG_ERR:
$message = $this->errColor . $message . self::END_COLOR;
break;
case Project::MSG_WARN:
$message = $this->warnColor . $message . self::END_COLOR;
break;
case Project::MSG_INFO:
$message = $this->infoColor . $message . self::END_COLOR;
break;
case Project::MSG_VERBOSE:
$message = $this->verboseColor . $message . self::END_COLOR;
break;
case Project::MSG_DEBUG:
$message = $this->debugColor . $message . self::END_COLOR;
break;
}
$stream->write($message . PHP_EOL);
}
}
}

View file

@ -0,0 +1,279 @@
<?php
/*
* $Id: DefaultLogger.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>.
*/
require_once 'phing/listener/StreamRequiredBuildLogger.php';
include_once 'phing/BuildEvent.php';
/**
* Writes a build event to the console.
*
* Currently, it only writes which targets are being executed, and
* any messages that get logged.
*
* @author Andreas Aderhold <andi@binarycloud.com>
* @copyright <EFBFBD> 2001,2002 THYRELL. All rights reserved
* @version $Revision: 905 $ $Date: 2010-10-05 18:28:03 +0200 (Tue, 05 Oct 2010) $
* @see BuildEvent
* @package phing.listener
*/
class DefaultLogger implements StreamRequiredBuildLogger {
/**
* Size of the left column in output. The default char width is 12.
* @var int
*/
const LEFT_COLUMN_SIZE = 12;
/**
* The message output level that should be used. The default is
* <code>Project::MSG_VERBOSE</code>.
* @var int
*/
protected $msgOutputLevel = Project::MSG_ERR;
/**
* Time that the build started
* @var int
*/
protected $startTime;
/**
* @var OutputStream Stream to use for standard output.
*/
protected $out;
/**
* @var OutputStream Stream to use for error output.
*/
protected $err;
/**
* Construct a new default logger.
*/
public function __construct() {
}
/**
* Set the msgOutputLevel this logger is to respond to.
*
* Only messages with a message level lower than or equal to the given
* level are output to the log.
*
* <p> Constants for the message levels are in Project.php. The order of
* the levels, from least to most verbose, is:
*
* <ul>
* <li>Project::MSG_ERR</li>
* <li>Project::MSG_WARN</li>
* <li>Project::MSG_INFO</li>
* <li>Project::MSG_VERBOSE</li>
* <li>Project::MSG_DEBUG</li>
* </ul>
*
* The default message level for DefaultLogger is Project::MSG_ERR.
*
* @param int $level The logging level for the logger.
* @see BuildLogger#setMessageOutputLevel()
*/
public function setMessageOutputLevel($level) {
$this->msgOutputLevel = (int) $level;
}
/**
* Sets the output stream.
* @param OutputStream $output
* @see BuildLogger#setOutputStream()
*/
public function setOutputStream(OutputStream $output) {
$this->out = $output;
}
/**
* Sets the error stream.
* @param OutputStream $err
* @see BuildLogger#setErrorStream()
*/
public function setErrorStream(OutputStream $err) {
$this->err = $err;
}
/**
* Sets the start-time when the build started. Used for calculating
* the build-time.
*
* @param object The BuildEvent
* @access public
*/
public function buildStarted(BuildEvent $event) {
$this->startTime = Phing::currentTimeMillis();
if ($this->msgOutputLevel >= Project::MSG_INFO) {
$this->printMessage("Buildfile: ".$event->getProject()->getProperty("phing.file"), $this->out, Project::MSG_INFO);
}
}
/**
* Prints whether the build succeeded or failed, and any errors that
* occured during the build. Also outputs the total build-time.
*
* @param object The BuildEvent
* @see BuildEvent::getException()
*/
public function buildFinished(BuildEvent $event) {
$error = $event->getException();
if ($error === null) {
$msg = PHP_EOL . $this->getBuildSuccessfulMessage() . PHP_EOL;
} else {
$msg = PHP_EOL . $this->getBuildFailedMessage() . PHP_EOL;
if (Project::MSG_VERBOSE <= $this->msgOutputLevel || !($error instanceof BuildException)) {
$msg .= $error->__toString().PHP_EOL;
} else {
$msg .= $error->getMessage();
}
}
$msg .= PHP_EOL . "Total time: " .self::formatTime(Phing::currentTimeMillis() - $this->startTime) . PHP_EOL;
if ($error === null) {
$this->printMessage($msg, $this->out, Project::MSG_VERBOSE);
} else {
$this->printMessage($msg, $this->err, Project::MSG_ERR);
}
}
/**
* Get the message to return when a build failed.
* @return string The classic "BUILD FAILED"
*/
protected function getBuildFailedMessage() {
return "BUILD FAILED";
}
/**
* Get the message to return when a build succeeded.
* @return string The classic "BUILD FINISHED"
*/
protected function getBuildSuccessfulMessage() {
return "BUILD FINISHED";
}
/**
* Prints the current target name
*
* @param object The BuildEvent
* @access public
* @see BuildEvent::getTarget()
*/
public function targetStarted(BuildEvent $event) {
if (Project::MSG_INFO <= $this->msgOutputLevel) {
$showLongTargets = $event->getProject()->getProperty("phing.showlongtargets");
$msg = PHP_EOL . $event->getProject()->getName() . ' > ' . $event->getTarget()->getName() . ($showLongTargets ? ' [' . $event->getTarget()->getDescription() . ']' : '') . ':' . PHP_EOL;
$this->printMessage($msg, $this->out, $event->getPriority());
}
}
/**
* Fired when a target has finished. We don't need specific action on this
* event. So the methods are empty.
*
* @param object The BuildEvent
* @see BuildEvent::getException()
*/
public function targetFinished(BuildEvent $event) {}
/**
* Fired when a task is started. We don't need specific action on this
* event. So the methods are empty.
*
* @param object The BuildEvent
* @access public
* @see BuildEvent::getTask()
*/
public function taskStarted(BuildEvent $event) {}
/**
* Fired when a task has finished. We don't need specific action on this
* event. So the methods are empty.
*
* @param object The BuildEvent
* @access public
* @see BuildEvent::getException()
*/
public function taskFinished(BuildEvent $event) {}
/**
* Print a message to the stdout.
*
* @param object The BuildEvent
* @access public
* @see BuildEvent::getMessage()
*/
public function messageLogged(BuildEvent $event) {
$priority = $event->getPriority();
if ($priority <= $this->msgOutputLevel) {
$msg = "";
if ($event->getTask() !== null) {
$name = $event->getTask();
$name = $name->getTaskName();
$msg = str_pad("[$name] ", self::LEFT_COLUMN_SIZE, " ", STR_PAD_LEFT);
}
$msg .= $event->getMessage();
if ($priority != Project::MSG_ERR) {
$this->printMessage($msg, $this->out, $priority);
} else {
$this->printMessage($msg, $this->err, $priority);
}
}
}
/**
* Formats a time micro integer to human readable format.
*
* @param integer The time stamp
* @access private
*/
public static function formatTime($micros) {
$seconds = $micros;
$minutes = $seconds / 60;
if ($minutes > 1) {
return sprintf("%1.0f minute%s %0.2f second%s",
$minutes, ($minutes === 1 ? " " : "s "),
$seconds - floor($seconds/60) * 60, ($seconds%60 === 1 ? "" : "s"));
} else {
return sprintf("%0.4f second%s", $seconds, ($seconds%60 === 1 ? "" : "s"));
}
}
/**
* Prints a message to console.
*
* @param string $message The message to print.
* Should not be <code>null</code>.
* @param resource $stream The stream to use for message printing.
* @param int $priority The priority of the message.
* (Ignored in this implementation.)
* @return void
*/
protected function printMessage($message, OutputStream $stream, $priority) {
$stream->write($message . PHP_EOL);
}
}

View file

@ -0,0 +1,59 @@
<?php
/*
* $Id: NoBannerLogger.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>.
*/
require_once 'phing/listener/DefaultLogger.php';
/**
* Extends DefaultLogger to strip out empty targets.
*
* @author Andreas Aderhold <andi@binarycloud.com>
* @copyright <EFBFBD> 2001,2002 THYRELL. All rights reserved
* @version $Revision: 905 $ $Date: 2010-10-05 18:28:03 +0200 (Tue, 05 Oct 2010) $
* @package phing.listener
*/
class NoBannerLogger extends DefaultLogger {
private $targetName = null;
function targetStarted(BuildEvent $event) {
$target = $event->getTarget();
$this->targetName = $target->getName();
}
function targetFinished(BuildEvent $event) {
$this->targetName = null;
}
function messageLogged(BuildEvent $event) {
if ($event->getPriority() > $this->msgOutputLevel || null === $event->getMessage() || trim($event->getMessage() === "")) {
return;
}
if ($this->targetName !== null) {
$msg = PHP_EOL . $event->getProject()->getName() . ' > ' . $this->targetName . ':' . PHP_EOL;
$this->printMessage($msg, $this->out, $event->getPriority());
$this->targetName = null;
}
parent::messageLogged($event);
}
}

View file

@ -0,0 +1,197 @@
<?php
/*
* $Id: PearLogListener.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>.
*/
require_once 'phing/BuildListener.php';
/**
* Writes build messages to PEAR Log.
*
* By default it will log to file in current directory w/ name 'phing.log'. You can customize
* this behavior by setting properties:
* - pear.log.type
* - pear.log.name
* - pear.log.ident (note that this class changes ident to project name)
* - pear.log.conf (note that array values are currently unsupported in Phing property files)
*
* <code>
* phing -f build.xml -logger phing.listener.PearLogger -Dpear.log.type=file -Dpear.log.name=/path/to/log.log
* </code>
*
* @author Hans Lellelid <hans@xmpl.org>
* @version $Revision: 905 $ $Date: 2010-10-05 18:28:03 +0200 (Tue, 05 Oct 2010) $
* @see BuildEvent
* @package phing.listener
*/
class PearLogListener implements BuildListener {
/**
* Size of the left column in output. The default char width is 12.
* @var int
*/
const LEFT_COLUMN_SIZE = 12;
/**
* Time that the build started
* @var int
*/
protected $startTime;
/**
* Maps Phing Project::MSG_* constants to PEAR_LOG_* constants.
* @var array
*/
protected static $levelMap = array( Project::MSG_DEBUG => PEAR_LOG_DEBUG,
Project::MSG_INFO => PEAR_LOG_INFO,
Project::MSG_VERBOSE => PEAR_LOG_NOTICE,
Project::MSG_WARN => PEAR_LOG_WARNING,
Project::MSG_ERR => PEAR_LOG_ERR
);
/**
* Whether logging has been configured.
* @var boolean
*/
protected $logConfigured = false;
/**
* @var Log PEAR Log object.
*/
protected $logger;
/**
* Configure the logger.
*/
protected function configureLogging() {
$type = Phing::getDefinedProperty('pear.log.type');
$name = Phing::getDefinedProperty('pear.log.name');
$ident = Phing::getDefinedProperty('pear.log.ident');
$conf = Phing::getDefinedProperty('pear.log.conf');
if ($type === null) $type = 'file';
if ($name === null) $name = 'phing.log';
if ($ident === null) $ident = 'phing';
if ($conf === null) $conf = array();
include_once 'Log.php';
if (!class_exists('Log')) {
throw new BuildException("Cannot find PEAR Log class for use by PearLogger.");
}
$this->logger = Log::singleton($type, $name, $ident, $conf, self::$levelMap[$this->msgOutputLevel]);
}
/**
* Get the configured PEAR logger to use.
* This method just ensures that logging has been configured and returns the configured logger.
* @return Log
*/
protected function logger() {
if (!$this->logConfigured) {
$this->configureLogging();
}
return $this->logger;
}
/**
* Sets the start-time when the build started. Used for calculating
* the build-time.
*
* @param BuildEvent The BuildEvent
*/
public function buildStarted(BuildEvent $event) {
$this->startTime = Phing::currentTimeMillis();
$this->logger()->setIdent($event->getProject()->getName());
$this->logger()->info("Starting build with buildfile: ". $event->getProject()->getProperty("phing.file"));
}
/**
* Logs whether the build succeeded or failed, and any errors that
* occured during the build. Also outputs the total build-time.
*
* @param BuildEvent The BuildEvent
* @see BuildEvent::getException()
*/
public function buildFinished(BuildEvent $event) {
$error = $event->getException();
if ($error === null) {
$msg = "Finished successful build.";
} else {
$msg = "Build failed. [reason: " . $error->getMessage() ."]";
}
$this->logger()->log($msg . " Total time: " . DefaultLogger::formatTime(Phing::currentTimeMillis() - $this->startTime));
}
/**
* Logs the current target name
*
* @param BuildEvent The BuildEvent
* @see BuildEvent::getTarget()
*/
public function targetStarted(BuildEvent $event) {}
/**
* Fired when a target has finished. We don't need specific action on this
* event. So the methods are empty.
*
* @param BuildEvent The BuildEvent
* @access public
* @see BuildEvent::getException()
*/
public function targetFinished(BuildEvent $event) {}
/**
* Fired when a task is started. We don't need specific action on this
* event. So the methods are empty.
*
* @param BuildEvent The BuildEvent
* @access public
* @see BuildEvent::getTask()
*/
public function taskStarted(BuildEvent $event) {}
/**
* Fired when a task has finished. We don't need specific action on this
* event. So the methods are empty.
*
* @param BuildEvent The BuildEvent
* @see BuildEvent::getException()
*/
public function taskFinished(BuildEvent $event) {}
/**
* Logs a message to the configured PEAR logger.
*
* @param BuildEvent The BuildEvent
* @see BuildEvent::getMessage()
*/
public function messageLogged(BuildEvent $event) {
if ($event->getPriority() <= $this->msgOutputLevel) {
$msg = "";
if ($event->getTask() !== null) {
$name = $event->getTask();
$name = $name->getTaskName();
$msg = str_pad("[$name] ", self::LEFT_COLUMN_SIZE, " ", STR_PAD_LEFT);
}
$msg .= $event->getMessage();
$this->logger()->log($msg, self::$levelMap[$event->getPriority()]);
}
}
}

View file

@ -0,0 +1,39 @@
<?php
/*
* $Id: StreamRequiredBuildLogger.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>.
*/
require_once 'phing/BuildLogger.php';
/**
* Interface for build loggers that require that out/err streams be set in order to function.
*
* This is just an empty sub-interface to BuildLogger, but is used by Phing to throw
* graceful errors when classes like phing.listener.DefaultLogger are being used as
* -listener.
*
* @author Hans Lellelid <hans@xmpl.org>
* @version $Revision: 905 $
* @see BuildEvent
* @see Project::addBuildListener()
* @package phing
*/
interface StreamRequiredBuildLogger extends BuildLogger {
}

View file

@ -0,0 +1,354 @@
<?php
/**
* $Id: XmlLogger.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>.
*/
require_once 'phing/BuildLogger.php';
require_once 'phing/listener/DefaultLogger.php';
require_once 'phing/system/util/Timer.php';
/**
* Generates a file in the current directory with
* an XML description of what happened during a build.
* The default filename is "log.xml", but this can be overridden
* with the property <code>XmlLogger.file</code>.
*
* @author Michiel Rook <michiel.rook@gmail.com>
* @version $Id: XmlLogger.php 905 2010-10-05 16:28:03Z mrook $
* @package phing.listener
*/
class XmlLogger implements BuildLogger {
/** XML element name for a build. */
const BUILD_TAG = "build";
/** XML element name for a target. */
const TARGET_TAG = "target";
/** XML element name for a task. */
const TASK_TAG = "task";
/** XML element name for a message. */
const MESSAGE_TAG = "message";
/** XML attribute name for a name. */
const NAME_ATTR = "name";
/** XML attribute name for a time. */
const TIME_ATTR = "time";
/** XML attribute name for a message priority. */
const PRIORITY_ATTR = "priority";
/** XML attribute name for a file location. */
const LOCATION_ATTR = "location";
/** XML attribute name for an error description. */
const ERROR_ATTR = "error";
/** XML element name for a stack trace. */
const STACKTRACE_TAG = "stacktrace";
/**
* @var DOMDocument The XML document created by this logger.
*/
private $doc;
/**
* @var int Start time for entire build.
*/
private $buildTimerStart = 0;
/**
* @var DOMElement Top-level (root) build element
*/
private $buildElement;
/**
* @var array DOMElement[] The parent of the element being processed.
*/
private $elementStack = array();
/**
* @var array int[] Array of millisecond times for the various elements being processed.
*/
private $timesStack = array();
/**
* @var int
*/
private $msgOutputLevel = Project::MSG_DEBUG;
/**
* @var OutputStream Stream to use for standard output.
*/
private $out;
/**
* @var OutputStream Stream to use for error output.
*/
private $err;
/**
* @var string Name of filename to create.
*/
private $outFilename;
/**
* Constructs a new BuildListener that logs build events to an XML file.
*/
public function __construct() {
$this->doc = new DOMDocument("1.0", "UTF-8");
$this->doc->formatOutput = true;
}
/**
* Fired when the build starts, this builds the top-level element for the
* document and remembers the time of the start of the build.
*
* @param BuildEvent Ignored.
*/
function buildStarted(BuildEvent $event) {
$this->buildTimerStart = Phing::currentTimeMillis();
$this->buildElement = $this->doc->createElement(XmlLogger::BUILD_TAG);
array_push($this->elementStack, $this->buildElement);
array_push($this->timesStack, $this->buildTimerStart);
}
/**
* Fired when the build finishes, this adds the time taken and any
* error stacktrace to the build element and writes the document to disk.
*
* @param BuildEvent $event An event with any relevant extra information.
* Will not be <code>null</code>.
*/
public function buildFinished(BuildEvent $event) {
$elapsedTime = Phing::currentTimeMillis() - $this->buildTimerStart;
$this->buildElement->setAttribute(XmlLogger::TIME_ATTR, DefaultLogger::formatTime($elapsedTime));
if ($event->getException() != null) {
$this->buildElement->setAttribute(XmlLogger::ERROR_ATTR, $event->getException()->getMessage());
$errText = $this->doc->createCDATASection($event->getException()->getTraceAsString());
$stacktrace = $this->doc->createElement(XmlLogger::STACKTRACE_TAG);
$stacktrace->appendChild($errText);
$this->buildElement->appendChild($stacktrace);
}
$this->doc->appendChild($this->buildElement);
$outFilename = $event->getProject()->getProperty("XmlLogger.file");
if ($outFilename == null) {
$outFilename = "log.xml";
}
try {
$stream = $this->out;
if ($stream === null) {
$stream = new FileOutputStream($outFilename);
}
// Yes, we could just stream->write() but this will eventually be the better
// way to do this (when we need to worry about charset conversions.
$writer = new OutputStreamWriter($stream);
$writer->write($this->doc->saveXML());
$writer->close();
} catch (IOException $exc) {
try {
$stream->close(); // in case there is a stream open still ...
} catch (Exception $x) {}
throw new BuildException("Unable to write log file.", $exc);
}
// cleanup:remove the buildElement
$this->buildElement = null;
array_pop($this->elementStack);
array_pop($this->timesStack);
}
/**
* Fired when a target starts building, remembers the current time and the name of the target.
*
* @param BuildEvent $event An event with any relevant extra information.
* Will not be <code>null</code>.
*/
public function targetStarted(BuildEvent $event) {
$target = $event->getTarget();
$targetElement = $this->doc->createElement(XmlLogger::TARGET_TAG);
$targetElement->setAttribute(XmlLogger::NAME_ATTR, $target->getName());
array_push($this->timesStack, Phing::currentTimeMillis());
array_push($this->elementStack, $targetElement);
}
/**
* Fired when a target finishes building, this adds the time taken
* to the appropriate target element in the log.
*
* @param BuildEvent $event An event with any relevant extra information.
* Will not be <code>null</code>.
*/
public function targetFinished(BuildEvent $event) {
$targetTimerStart = array_pop($this->timesStack);
$targetElement = array_pop($this->elementStack);
$elapsedTime = Phing::currentTimeMillis() - $targetTimerStart;
$targetElement->setAttribute(XmlLogger::TIME_ATTR, DefaultLogger::formatTime($elapsedTime));
$parentElement = $this->elementStack[ count($this->elementStack) - 1 ];
$parentElement->appendChild($targetElement);
}
/**
* Fired when a task starts building, remembers the current time and the name of the task.
*
* @param BuildEvent $event An event with any relevant extra information.
* Will not be <code>null</code>.
*/
public function taskStarted(BuildEvent $event) {
$task = $event->getTask();
$taskElement = $this->doc->createElement(XmlLogger::TASK_TAG);
$taskElement->setAttribute(XmlLogger::NAME_ATTR, $task->getTaskName());
$taskElement->setAttribute(XmlLogger::LOCATION_ATTR, $task->getLocation()->toString());
array_push($this->timesStack, Phing::currentTimeMillis());
array_push($this->elementStack, $taskElement);
}
/**
* Fired when a task finishes building, this adds the time taken
* to the appropriate task element in the log.
*
* @param BuildEvent $event An event with any relevant extra information.
* Will not be <code>null</code>.
*/
public function taskFinished(BuildEvent $event) {
$taskTimerStart = array_pop($this->timesStack);
$taskElement = array_pop($this->elementStack);
$elapsedTime = Phing::currentTimeMillis() - $taskTimerStart;
$taskElement->setAttribute(XmlLogger::TIME_ATTR, DefaultLogger::formatTime($elapsedTime));
$parentElement = $this->elementStack[ count($this->elementStack) - 1 ];
$parentElement->appendChild($taskElement);
}
/**
* Fired when a message is logged, this adds a message element to the
* most appropriate parent element (task, target or build) and records
* the priority and text of the message.
*
* @param BuildEvent An event with any relevant extra information.
* Will not be <code>null</code>.
*/
public function messageLogged(BuildEvent $event)
{
$priority = $event->getPriority();
if ($priority > $this->msgOutputLevel) {
return;
}
$messageElement = $this->doc->createElement(XmlLogger::MESSAGE_TAG);
switch ($priority) {
case Project::MSG_ERR:
$name = "error";
break;
case Project::MSG_WARN:
$name = "warn";
break;
case Project::MSG_INFO:
$name = "info";
break;
default:
$name = "debug";
break;
}
$messageElement->setAttribute(XmlLogger::PRIORITY_ATTR, $name);
if (function_exists('mb_convert_encoding'))
{
$messageConverted = mb_convert_encoding($event->getMessage(), 'UTF-8');
}
else
{
$messageConverted = utf8_encode($event->getMessage());
}
$messageText = $this->doc->createCDATASection($messageConverted);
$messageElement->appendChild($messageText);
if (!empty($this->elementStack)) {
$this->elementStack[count($this->elementStack)-1]->appendChild($messageElement);
}
}
/**
* Set the msgOutputLevel this logger is to respond to.
*
* Only messages with a message level lower than or equal to the given
* level are output to the log.
*
* <p> Constants for the message levels are in Project.php. The order of
* the levels, from least to most verbose, is:
*
* <ul>
* <li>Project::MSG_ERR</li>
* <li>Project::MSG_WARN</li>
* <li>Project::MSG_INFO</li>
* <li>Project::MSG_VERBOSE</li>
* <li>Project::MSG_DEBUG</li>
* </ul>
*
* The default message level for DefaultLogger is Project::MSG_ERR.
*
* @param int $level The logging level for the logger.
* @see BuildLogger#setMessageOutputLevel()
*/
public function setMessageOutputLevel($level) {
$this->msgOutputLevel = (int) $level;
}
/**
* Sets the output stream.
* @param OutputStream $output
* @see BuildLogger#setOutputStream()
*/
public function setOutputStream(OutputStream $output) {
$this->out = $output;
}
/**
* Sets the error stream.
* @param OutputStream $err
* @see BuildLogger#setErrorStream()
*/
public function setErrorStream(OutputStream $err) {
$this->err = $err;
}
}

View file

@ -0,0 +1,59 @@
<?php
/*
* $Id: FileNameMapper.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>.
*/
/**
* Interface for filename mapper classes.
*
* @author Andreas Aderhold, andi@binarycloud.com
* @author Hans Lellelid <hans@xmpl.org>
* @version $Revision: 905 $
* @package phing.mappers
*/
interface FileNameMapper {
/**
* The mapper implementation.
*
* @param mixed $sourceFileName The data the mapper works on.
* @return array The data after the mapper has been applied; must be in array format (for some reason).
*/
public function main($sourceFileName);
/**
* Accessor. Sets the to property. The actual implementation
* depends on the child class.
*
* @param string $to To what this mapper should convert the from string
* @return void
*/
public function setTo($to);
/**
* Accessor. Sets the from property. What this mapper should
* recognize. The actual implementation is dependent upon the
* child class
*
* @param string $from On what this mapper should work
* @return void
*/
public function setFrom($from);
}

View file

@ -0,0 +1,55 @@
<?php
/*
* $Id: FlattenMapper.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>.
*/
require_once 'phing/mappers/FileNameMapper.php';
/**
* Removes any directory information from the passed path.
*
* @author Andreas Aderhold <andi@binarycloud.com>
* @version $Revision: 905 $
* @package phing.mappers
*/
class FlattenMapper implements FileNameMapper {
/**
* The mapper implementation. Returns string with source filename
* but without leading directory information
*
* @param string $sourceFileName The data the mapper works on
* @return array The data after the mapper has been applied
*/
function main($sourceFileName) {
$f = new PhingFile($sourceFileName);
return array($f->getName());
}
/**
* Ignored here.
*/
function setTo($to) {}
/**
* Ignored here.
*/
function setFrom($from) {}
}

View file

@ -0,0 +1,113 @@
<?php
/*
* $Id: GlobMapper.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/mappers/FileNameMapper.php';
/**
* description here
*
* @author Andreas Aderhold, andi@binarycloud.com
* @version $Revision: 905 $
* @package phing.mappers
*/
class GlobMapper implements FileNameMapper {
/**
* Part of &quot;from&quot; pattern before the *.
*/
private $fromPrefix = null;
/**
* Part of &quot;from&quot; pattern after the *.
*/
private $fromPostfix = null;
/**
* Length of the prefix (&quot;from&quot; pattern).
*/
private $prefixLength;
/**
* Length of the postfix (&quot;from&quot; pattern).
*/
private $postfixLength;
/**
* Part of &quot;to&quot; pattern before the *.
*/
private $toPrefix = null;
/**
* Part of &quot;to&quot; pattern after the *.
*/
private $toPostfix = null;
function main($_sourceFileName) {
if (($this->fromPrefix === null)
|| !StringHelper::startsWith($this->fromPrefix, $_sourceFileName)
|| !StringHelper::endsWith($this->fromPostfix, $_sourceFileName)) {
return null;
}
$varpart = $this->_extractVariablePart($_sourceFileName);
$substitution = $this->toPrefix.$varpart.$this->toPostfix;
return array($substitution);
}
function setFrom($from) {
$index = strrpos($from, '*');
if ($index === false) {
$this->fromPrefix = $from;
$this->fromPostfix = "";
} else {
$this->fromPrefix = substr($from, 0, $index);
$this->fromPostfix = substr($from, $index+1);
}
$this->prefixLength = strlen($this->fromPrefix);
$this->postfixLength = strlen($this->fromPostfix);
}
/**
* Sets the &quot;to&quot; pattern. Required.
*/
function setTo($to) {
$index = strrpos($to, '*');
if ($index === false) {
$this->toPrefix = $to;
$this->toPostfix = "";
} else {
$this->toPrefix = substr($to, 0, $index);
$this->toPostfix = substr($to, $index+1);
}
}
private function _extractVariablePart($_name) {
// ergh, i really hate php's string functions .... all but natural
$start = ($this->prefixLength === 0) ? 0 : $this->prefixLength;
$end = ($this->postfixLength === 0) ? strlen($_name) : strlen($_name) - $this->postfixLength;
$len = $end-$start;
return substr($_name, $start, $len);
}
}

View file

@ -0,0 +1,54 @@
<?php
/*
* $Id: IdentityMapper.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>.
*/
require_once 'phing/mappers/FileNameMapper.php';
/**
* This mapper does nothing ;)
*
* @author Andreas Aderhold <andi@binarycloud.com>
* @author Hans Lellelid <hans@xmpl.org>
* @version $Revision: 905 $
* @package phing.mappers
*/
class IdentityMapper implements FileNameMapper {
/**
* The mapper implementation. Basically does nothing in this case.
*
* @param string $sourceFileName The data the mapper works on.
* @return array The data after the mapper has been applied
*/
function main($sourceFileName) {
return array($sourceFileName);
}
/**
* Ignored here.
*/
function setTo($to) {}
/**
* Ignored here.
*/
function setFrom($from) {}
}

View file

@ -0,0 +1,69 @@
<?php
/*
* $Id: MergeMapper.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/mappers/FileNameMapper.php';
/**
* For merging files into a single file. In practice just returns whatever value
* was set for "to".
*
* @author Andreas Aderhold <andi@binarycloud.com>
* @version $Revision: 905 $
* @package phing.mappers
*/
class MergeMapper implements FileNameMapper {
/** the merge */
private $mergedFile;
/**
* The mapper implementation. Basically does nothing in this case.
*
* @param mixed The data the mapper works on
* @returns mixed The data after the mapper has been applied
* @access public
* @author Andreas Aderhold, andi@binarycloud.com
*/
function main($sourceFileName) {
if ($this->mergedFile === null) {
throw new BuildException("MergeMapper error, to attribute not set");
}
return array($this->mergedFile);
}
/**
* Accessor. Sets the to property
*
* @param string To what this mapper should convert the from string
* @returns boolean True
* @access public
* @author Andreas Aderhold, andi@binarycloud.com
*/
function setTo($to) {
$this->mergedFile = $to;
}
/**
* Ignored.
*/
function setFrom($from) {}
}

View file

@ -0,0 +1,97 @@
<?php
/*
* $Id: RegexpMapper.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>.
*/
require_once 'phing/mappers/FileNameMapper.php';
include_once 'phing/util/StringHelper.php';
include_once 'phing/util/regexp/Regexp.php';
/**
* Uses regular expressions to perform filename transformations.
*
* @author Andreas Aderhold <andi@binarycloud.com>
* @author Hans Lellelid <hans@velum.net>
* @version $Revision: 905 $
* @package phing.mappers
*/
class RegexpMapper implements FileNameMapper {
/**
* @var string
*/
private $to;
/**
* The Regexp engine.
* @var Regexp
*/
private $reg;
function __construct() {
// instantiage regexp matcher here
$this->reg = new Regexp();
}
/**
* Sets the &quot;from&quot; pattern. Required.
*/
function setFrom($from) {
$this->reg->SetPattern($from);
}
/**
* Sets the &quot;to&quot; pattern. Required.
*/
function setTo($to) {
// [HL] I'm changing the way this works for now to just use string
//$this->to = StringHelper::toCharArray($to);
$this->to = $to;
}
function main($sourceFileName) {
if ($this->reg === null || $this->to === null || !$this->reg->matches((string) $sourceFileName)) {
return null;
}
return array($this->replaceReferences($sourceFileName));
}
/**
* Replace all backreferences in the to pattern with the matched groups.
* groups of the source.
* @param string $source The source filename.
*/
private function replaceReferences($source) {
// FIXME
// Can't we just use engine->replace() to handle this? the Preg engine
// will automatically convert \1 references to $1
// the expression has already been processed (when ->matches() was run in Main())
// so no need to pass $source again to the engine.
$groups = (array) $this->reg->getGroups();
// replace \1 with value of $groups[1] and return the modified "to" string
return preg_replace('/\\\([\d]+)/e', "\$groups[$1]", $this->to);
}
}

View file

@ -0,0 +1,98 @@
<?php
/*
* $Id: AbstractHandler.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/parser/ExpatParseException.php';
/**
* This is an abstract class all SAX handler classes must extend
*
* @author Andreas Aderhold <andi@binarycloud.com>
* @copyright © 2001,2002 THYRELL. All rights reserved
* @version $Revision: 905 $
* @package phing.parser
*/
abstract class AbstractHandler {
public $parentHandler = null;
public $parser = null;
/**
* Constructs a SAX handler parser.
*
* The constructor must be called by all derived classes.
*
* @param object the parser object
* @param object the parent handler of this handler
*/
protected function __construct($parser, $parentHandler) {
$this->parentHandler = $parentHandler;
$this->parser = $parser;
$this->parser->setHandler($this);
}
/**
* Gets invoked when a XML open tag occurs
*
* Must be overloaded by the child class. Throws an ExpatParseException
* if there is no handler registered for an element.
*
* @param string the name of the XML element
* @param array the attributes of the XML element
*/
public function startElement($name, $attribs) {
throw new ExpatParseException("Unexpected element $name");
}
/**
* Gets invoked when element closes method.
*
*/
protected function finished() {}
/**
* Gets invoked when a XML element ends.
*
* Can be overloaded by the child class. But should not. It hands
* over control to the parentHandler of this.
*
* @param string the name of the XML element
*/
public function endElement($name) {
$this->finished();
$this->parser->setHandler($this->parentHandler);
}
/**
* Invoked by occurance of #PCDATA.
*
* @param string the name of the XML element
* @exception ExpatParserException if there is no CDATA but method
* was called
* @access public
*/
public function characters($data) {
$s = trim($data);
if (strlen($s) > 0) {
throw new ExpatParseException("Unexpected text '$s'", $this->parser->getLocation());
}
}
}

View file

@ -0,0 +1,116 @@
<?php
/*
* $Id: AbstractSAXParser.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>.
*/
/**
* The abstract SAX parser class.
*
* This class represents a SAX parser. It is a abstract calss that must be
* implemented by the real parser that must extend this class
*
* @author Andreas Aderhold <andi@binarycloud.com>
* @author Hans Lellelid <hans@xmpl.org>
* @copyright <EFBFBD> 2001,2002 THYRELL. All rights reserved
* @version $Revision: 905 $
* @package phing.parser
*/
abstract class AbstractSAXParser {
/** The AbstractHandler object. */
protected $handler;
/**
* Constructs a SAX parser
*/
function __construct() {}
/**
* Sets options for PHP interal parser. Must be implemented by the parser
* class if it should be used.
*/
abstract function parserSetOption($opt, $val);
/**
* Sets the current element handler object for this parser. Usually this
* is an object using extending "AbstractHandler".
*
* @param AbstractHandler $obj The handler object.
*/
function setHandler( $obj) {
$this->handler = $obj;
}
/**
* Method that gets invoked when the parser runs over a XML start element.
*
* This method is called by PHP's internal parser functions and registered
* in the actual parser implementation.
* It gives control to the current active handler object by calling the
* <code>startElement()</code> method.
*
* @param object the php's internal parser handle
* @param string the open tag name
* @param array the tag's attributes if any
* @throws Exception - Exceptions may be thrown by the Handler
*/
function startElement($parser, $name, $attribs) {
$this->handler->startElement($name, $attribs);
}
/**
* Method that gets invoked when the parser runs over a XML close element.
*
* This method is called by PHP's internal parser funcitons and registered
* in the actual parser implementation.
*
* It gives control to the current active handler object by calling the
* <code>endElement()</code> method.
*
* @param object the php's internal parser handle
* @param string the closing tag name
* @throws Exception - Exceptions may be thrown by the Handler
*/
function endElement($parser, $name) {
$this->handler->endElement($name);
}
/**
* Method that gets invoked when the parser runs over CDATA.
*
* This method is called by PHP's internal parser functions and registered
* in the actual parser implementation.
*
* It gives control to the current active handler object by calling the
* <code>characters()</code> method. That processes the given CDATA.
*
* @param resource $parser php's internal parser handle.
* @param string $data the CDATA
* @throws Exception - Exceptions may be thrown by the Handler
*/
function characters($parser, $data) {
$this->handler->characters($data);
}
/**
* Entrypoint for parser. This method needs to be implemented by the
* child classt that utilizes the concrete parser
*/
abstract function parse();
}

View file

@ -0,0 +1,144 @@
<?php
/*
* $Id: DataTypeHandler.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/RuntimeConfigurable.php';
/**
* Configures a Project (complete with Targets and Tasks) based on
* a XML build file.
* <p>
* Design/ZE2 migration note:
* If PHP would support nested classes. All the phing/parser/*Filter
* classes would be nested within this class
*
* @author Andreas Aderhold <andi@binarycloud.com>
* @copyright © 2001,2002 THYRELL. All rights reserved
* @version $Revision: 905 $ $Date: 2010-10-05 18:28:03 +0200 (Tue, 05 Oct 2010) $
* @access public
* @package phing.parser
*/
class DataTypeHandler extends AbstractHandler {
private $target;
private $element;
private $wrapper;
/**
* Constructs a new DataTypeHandler and sets up everything.
*
* @param AbstractSAXParser $parser The XML parser (default: ExpatParser)
* @param AbstractHandler $parentHandler The parent handler that invoked this handler.
* @param ProjectConfigurator $configurator The ProjectConfigurator object
* @param Target $target The target object this datatype is contained in (null for top-level datatypes).
*/
function __construct(AbstractSAXParser $parser, AbstractHandler $parentHandler, ProjectConfigurator $configurator, $target = null) { // FIXME b2 typehinting
parent::__construct($parser, $parentHandler);
$this->target = $target;
$this->configurator = $configurator;
}
/**
* Executes initialization actions required to setup the data structures
* related to the tag.
* <p>
* This includes:
* <ul>
* <li>creation of the datatype object</li>
* <li>calling the setters for attributes</li>
* <li>adding the type to the target object if any</li>
* <li>adding a reference to the task (if id attribute is given)</li>
* </ul>
*
* @param string the tag that comes in
* @param array attributes the tag carries
* @throws ExpatParseException if attributes are incomplete or invalid
* @access public
*/
function init($propType, $attrs) {
// shorthands
$project = $this->configurator->project;
$configurator = $this->configurator;
try {//try
$this->element = $project->createDataType($propType);
if ($this->element === null) {
throw new BuildException("Unknown data type $propType");
}
if ($this->target !== null) {
$this->wrapper = new RuntimeConfigurable($this->element, $propType);
$this->wrapper->setAttributes($attrs);
$this->target->addDataType($this->wrapper);
} else {
$configurator->configure($this->element, $attrs, $project);
$configurator->configureId($this->element, $attrs);
}
} catch (BuildException $exc) {
throw new ExpatParseException($exc, $this->parser->getLocation());
}
}
/**
* Handles character data.
*
* @param string the CDATA that comes in
* @access public
*/
function characters($data) {
$project = $this->configurator->project;
try {//try
$this->configurator->addText($project, $this->element, $data);
} catch (BuildException $exc) {
throw new ExpatParseException($exc->getMessage(), $this->parser->getLocation());
}
}
/**
* Checks for nested tags within the current one. Creates and calls
* handlers respectively.
*
* @param string the tag that comes in
* @param array attributes the tag carries
* @access public
*/
function startElement($name, $attrs) {
$nef = new NestedElementHandler($this->parser, $this, $this->configurator, $this->element, $this->wrapper, $this->target);
$nef->init($name, $attrs);
}
/**
* Overrides endElement for data types. Tells the type
* handler that processing the element had been finished so
* handlers know they can perform actions that need to be
* based on the data contained within the element.
*
* @param string the name of the XML element
* @return void
*/
function endElement($name) {
$this->element->parsingComplete();
parent::endElement($name);
}
}

View file

@ -0,0 +1,31 @@
<?php
/*
* $Id: ExpatParseException.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>.
*/
require_once 'phing/BuildException.php';
/**
* This class throws errors for Expat, the XML processor.
*
* @author Andreas Aderhold, andi@binarycloud.com
* @version $Revision: 905 $ $Date: 2010-10-05 18:28:03 +0200 (Tue, 05 Oct 2010) $
* @package phing.parser
*/
class ExpatParseException extends BuildException {}

View file

@ -0,0 +1,140 @@
<?php
/*
* $Id: ExpatParser.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>.
*/
require_once 'phing/parser/AbstractSAXParser.php';
include_once 'phing/parser/ExpatParseException.php';
include_once 'phing/system/io/IOException.php';
include_once 'phing/system/io/FileReader.php';
/**
* This class is a wrapper for the PHP's internal expat parser.
*
* It takes an XML file represented by a abstract path name, and starts
* parsing the file and calling the different "trap" methods inherited from
* the AbstractParser class.
*
* Those methods then invoke the represenatative methods in the registered
* handler classes.
*
* @author Andreas Aderhold <andi@binarycloud.com>
* @copyright © 2001,2002 THYRELL. All rights reserved
* @version $Revision: 905 $ $Date: 2010-10-05 18:28:03 +0200 (Tue, 05 Oct 2010) $
* @access public
* @package phing.parser
*/
class ExpatParser extends AbstractSAXParser {
/** @var resource */
private $parser;
/** @var Reader */
private $reader;
private $file;
private $buffer = 4096;
private $error_string = "";
private $line = 0;
/** @var Location Current cursor pos in XML file. */
private $location;
/**
* Constructs a new ExpatParser object.
*
* The constructor accepts a PhingFile object that represents the filename
* for the file to be parsed. It sets up php's internal expat parser
* and options.
*
* @param Reader $reader The Reader Object that is to be read from.
* @param string $filename Filename to read.
* @throws Exception if the given argument is not a PhingFile object
*/
function __construct(Reader $reader, $filename=null) {
$this->reader = $reader;
if ($filename !== null) {
$this->file = new PhingFile($filename);
}
$this->parser = xml_parser_create();
$this->buffer = 4096;
$this->location = new Location();
xml_set_object($this->parser, $this);
xml_set_element_handler($this->parser, array($this,"startElement"),array($this,"endElement"));
xml_set_character_data_handler($this->parser, array($this, "characters"));
}
/**
* Override PHP's parser default settings, created in the constructor.
*
* @param string the option to set
* @throws mixed the value to set
* @return boolean true if the option could be set, otherwise false
* @access public
*/
function parserSetOption($opt, $val) {
return xml_parser_set_option($this->parser, $opt, $val);
}
/**
* Returns the location object of the current parsed element. It describes
* the location of the element within the XML file (line, char)
*
* @return object the location of the current parser
* @access public
*/
function getLocation() {
if ($this->file !== null) {
$path = $this->file->getAbsolutePath();
} else {
$path = $this->reader->getResource();
}
$this->location = new Location($path, xml_get_current_line_number($this->parser), xml_get_current_column_number($this->parser));
return $this->location;
}
/**
* Starts the parsing process.
*
* @param string the option to set
* @return int 1 if the parsing succeeded
* @throws ExpatParseException if something gone wrong during parsing
* @throws IOException if XML file can not be accessed
* @access public
*/
function parse() {
while ( ($data = $this->reader->read()) !== -1 ) {
if (!xml_parse($this->parser, $data, $this->reader->eof())) {
$error = xml_error_string(xml_get_error_code($this->parser));
$e = new ExpatParseException($error, $this->getLocation());
xml_parser_free($this->parser);
throw $e;
}
}
xml_parser_free($this->parser);
return 1;
}
}

76
3rd_party/php/phing/parser/Location.php vendored Normal file
View file

@ -0,0 +1,76 @@
<?php
/*
* $Id: Location.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>.
*/
/**
* Stores the file name and line number of a XML file
*
* @author Andreas Aderhold <andi@binarycloud.com>
* @copyright © 2001,2002 THYRELL. All rights reserved
* @version $Revision: 905 $ $Date: 2010-10-05 18:28:03 +0200 (Tue, 05 Oct 2010) $
* @access public
* @package phing.parser
*/
class Location {
private $fileName;
private $lineNumber;
private $columnNumber;
/**
* Constructs the location consisting of a file name and line number
*
* @param string the filename
* @param integer the line number
* @param integer the column number
* @access public
*/
function Location($fileName = null, $lineNumber = null, $columnNumber = null) {
$this->fileName = $fileName;
$this->lineNumber = $lineNumber;
$this->columnNumber = $columnNumber;
}
/**
* Returns the file name, line number and a trailing space.
*
* An error message can be appended easily. For unknown locations,
* returns empty string.
*
* @return string the string representation of this Location object
* @access public
*/
function toString() {
$buf = "";
if ($this->fileName !== null) {
$buf.=$this->fileName;
if ($this->lineNumber !== null) {
$buf.= ":".$this->lineNumber;
}
$buf.=":".$this->columnNumber;
}
return (string) $buf;
}
function __toString () {
return $this->toString();
}
}

View file

@ -0,0 +1,186 @@
<?php
/*
* $Id: NestedElementHandler.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/IntrospectionHelper.php';
include_once 'phing/TaskContainer.php';
/**
* The nested element handler class.
*
* This class handles the occurance of runtime registered tags like
* datatypes (fileset, patternset, etc) and it's possible nested tags. It
* introspects the implementation of the class and sets up the data structures.
*
* @author Andreas Aderhold <andi@binarycloud.com>
* @copyright © 2001,2002 THYRELL. All rights reserved
* @version $Revision: 905 $ $Date: 2010-10-05 18:28:03 +0200 (Tue, 05 Oct 2010) $
* @access public
* @package phing.parser
*/
class NestedElementHandler extends AbstractHandler {
/**
* Reference to the parent object that represents the parent tag
* of this nested element
* @var object
*/
private $parent;
/**
* Reference to the child object that represents the child tag
* of this nested element
* @var object
*/
private $child;
/**
* Reference to the parent wrapper object
* @var object
*/
private $parentWrapper;
/**
* Reference to the child wrapper object
* @var object
*/
private $childWrapper;
/**
* Reference to the related target object
* @var object the target instance
*/
private $target;
/**
* Constructs a new NestedElement handler and sets up everything.
*
* @param object the ExpatParser object
* @param object the parent handler that invoked this handler
* @param object the ProjectConfigurator object
* @param object the parent object this element is contained in
* @param object the parent wrapper object
* @param object the target object this task is contained in
* @access public
*/
function __construct($parser, $parentHandler, $configurator, $parent, $parentWrapper, $target) {
parent::__construct($parser, $parentHandler);
$this->configurator = $configurator;
if ($parent instanceof TaskAdapter) {
$this->parent = $parent->getProxy();
} else {
$this->parent = $parent;
}
$this->parentWrapper = $parentWrapper;
$this->target = $target;
}
/**
* Executes initialization actions required to setup the data structures
* related to the tag.
* <p>
* This includes:
* <ul>
* <li>creation of the nested element</li>
* <li>calling the setters for attributes</li>
* <li>adding the element to the container object</li>
* <li>adding a reference to the element (if id attribute is given)</li>
* </ul>
*
* @param string the tag that comes in
* @param array attributes the tag carries
* @throws ExpatParseException if the setup process fails
* @access public
*/
function init($propType, $attrs) {
$configurator = $this->configurator;
$project = $this->configurator->project;
// introspect the parent class that is custom
$parentClass = get_class($this->parent);
$ih = IntrospectionHelper::getHelper($parentClass);
try {
if ($this->parent instanceof UnknownElement) {
$this->child = new UnknownElement(strtolower($propType));
$this->parent->addChild($this->child);
} else {
$this->child = $ih->createElement($project, $this->parent, strtolower($propType));
}
$configurator->configureId($this->child, $attrs);
if ($this->parentWrapper !== null) {
$this->childWrapper = new RuntimeConfigurable($this->child, $propType);
$this->childWrapper->setAttributes($attrs);
$this->parentWrapper->addChild($this->childWrapper);
} else {
$configurator->configure($this->child, $attrs, $project);
$ih->storeElement($project, $this->parent, $this->child, strtolower($propType));
}
} catch (BuildException $exc) {
throw new ExpatParseException("Error initializing nested element <$propType>", $exc, $this->parser->getLocation());
}
}
/**
* Handles character data.
*
* @param string the CDATA that comes in
* @throws ExpatParseException if the CDATA could not be set-up properly
* @access public
*/
function characters($data) {
$configurator = $this->configurator;
$project = $this->configurator->project;
if ($this->parentWrapper === null) {
try {
$configurator->addText($project, $this->child, $data);
} catch (BuildException $exc) {
throw new ExpatParseException($exc->getMessage(), $this->parser->getLocation());
}
} else {
$this->childWrapper->addText($data);
}
}
/**
* Checks for nested tags within the current one. Creates and calls
* handlers respectively.
*
* @param string the tag that comes in
* @param array attributes the tag carries
* @access public
*/
function startElement($name, $attrs) {
//print(get_class($this) . " name = $name, attrs = " . implode(",",$attrs) . "\n");
if ($this->child instanceof TaskContainer) {
// taskcontainer nested element can contain other tasks - no other
// nested elements possible
$tc = new TaskHandler($this->parser, $this, $this->configurator, $this->child, $this->childWrapper, $this->target);
$tc->init($name, $attrs);
} else {
$neh = new NestedElementHandler($this->parser, $this, $this->configurator, $this->child, $this->childWrapper, $this->target);
$neh->init($name, $attrs);
}
}
}

View file

@ -0,0 +1,81 @@
<?php
/*
* $Id: PhingXMLContext.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>.
*/
/**
* Track the current state of the Xml parse operation.
*
* @author Bryan Davis <bpd@keynetics.com>
* @version $Revision: 905 $ $Date: 2010-10-05 18:28:03 +0200 (Tue, 05 Oct 2010) $
* @access public
* @package phing.parser
*/
class PhingXMLContext {
/**
* Constructor
* @param $project the project to which this antxml context belongs to
*/
public function __construct ($project) {
$this->project = $project;
}
/** The project to configure. */
private $project;
private $configurators = array();
public function startConfigure ($cfg) {
$this->configurators[] = $cfg;
}
public function endConfigure () {
array_pop($this->configurators);
}
public function getConfigurator () {
$l = count($this->configurators);
if (0 == $l) {
return null;
} else {
return $this->configurators[$l - 1];
}
}
/** Impoerted files */
private $importStack = array();
public function addImport ($file) {
$this->importStack[] = $file;
}
public function getImportStack () {
return $this->importStack;
}
/**
* find out the project to which this context belongs
* @return project
*/
public function getProject() {
return $this->project;
}
} //end PhingXMLContext

View file

@ -0,0 +1,373 @@
<?php
/*
* $Id: ProjectConfigurator.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/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';
include_once 'phing/parser/PhingXMLContext.php';
include_once 'phing/IntrospectionHelper.php';
/**
* The datatype handler class.
*
* This class handles the occurance of registered datatype tags like
* FileSet
*
* @author Andreas Aderhold <andi@binarycloud.com>
* @copyright <EFBFBD> 2001,2002 THYRELL. All rights reserved
* @version $Revision: 905 $ $Date: 2010-10-05 18:28:03 +0200 (Tue, 05 Oct 2010) $
* @access public
* @package phing.parser
*/
class ProjectConfigurator {
public $project;
public $locator;
public $buildFile;
public $buildFileParent;
/** Targets in current file */
private $currentTargets;
/** Synthetic target that will be called at the end to the parse phase */
private $parseEndTarget;
/** Name of the current project */
private $currentProjectName;
private $isParsing = true;
/**
* Indicates whether the project tag attributes are to be ignored
* when processing a particular build file.
*/
private $ignoreProjectTag = false;
/**
* 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());
$this->currentTargets = array();
$this->parseEndTarget = new Target();
}
/**
* find out the build file
* @return the build file to which the xml context belongs
*/
public function getBuildFile() {
return $this->buildFile;
}
/**
* find out the parent build file of this build file
* @return the parent build file of this build file
*/
public function getBuildFileParent() {
return $this->buildFileParent;
}
/**
* find out the current project name
* @return current project name
*/
public function getCurrentProjectName() {
return $this->currentProjectName;
}
/**
* set the name of the current project
* @param name name of the current project
*/
public function setCurrentProjectName($name) {
$this->currentProjectName = $name;
}
/**
* tells whether the project tag is being ignored
* @return whether the project tag is being ignored
*/
public function isIgnoringProjectTag() {
return $this->ignoreProjectTag;
}
/**
* sets the flag to ignore the project tag
* @param flag to ignore the project tag
*/
public function setIgnoreProjectTag($flag) {
$this->ignoreProjectTag = $flag;
}
public function &getCurrentTargets () {
return $this->currentTargets;
}
public function isParsing () {
return $this->isParsing;
}
/**
* 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 {
// get parse context
$ctx = $this->project->getReference("phing.parsing.context");
if (null == $ctx) {
// make a new context and register it with project
$ctx = new PhingXMLContext($this->project);
$this->project->addReference("phing.parsing.context", $ctx);
}
//record this parse with context
$ctx->addImport($this->buildFile);
if (count($ctx->getImportStack()) > 1) {
// this is an imported file
// modify project tag parse behavior
$this->setIgnoreProjectTag(true);
}
// push action onto global stack
$ctx->startConfigure($this);
$reader = new BufferedReader(new FileReader($this->buildFile));
$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();
// mark parse phase as completed
$this->isParsing = false;
// execute delayed tasks
$this->parseEndTarget->main();
// pop this action from the global stack
$ctx->endConfigure();
} catch (Exception $exc) {
throw new BuildException("Error reading project file", $exc);
}
}
/**
* Delay execution of a task until after the current parse phase has
* completed.
*
* @param Task $task Task to execute after parse
*/
public function delayTaskUntilParseEnd ($task) {
$this->parseEndTarget->addTask($task);
}
/**
* 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
*/
public static 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
*/
public static 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
*/
public static 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 = $value;
$iteration = 0;
// loop to recursively replace tokens
while (strpos($sb, '${') !== false)
{
$sb = preg_replace_callback('/\$\{([^\$}]+)\}/', array('ProjectConfigurator', 'replacePropertyCallback'), $sb);
// keep track of iterations so we can break out of otherwise infinite loops.
$iteration++;
if ($iteration == 5)
{
return $sb;
}
}
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
*/
public function configureId($target, $attr) {
if (isset($attr['id']) && $attr['id'] !== null) {
$this->project->addReference($attr['id'], $target);
}
}
}

View file

@ -0,0 +1,176 @@
<?php
/*
* $Id: ProjectHandler.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>.
*/
require_once 'phing/parser/AbstractHandler.php';
require_once 'phing/system/io/PhingFile.php';
/**
* Handler class for the <project> XML element This class handles all elements
* under the <project> element.
*
* @author Andreas Aderhold <andi@binarycloud.com>
* @copyright (c) 2001,2002 THYRELL. All rights reserved
* @version $Revision: 905 $ $Date: 2010-10-05 18:28:03 +0200 (Tue, 05 Oct 2010) $
* @access public
* @package phing.parser
*/
class ProjectHandler extends AbstractHandler {
/**
* The phing project configurator object.
* @var ProjectConfigurator
*/
private $configurator;
/**
* Constructs a new ProjectHandler
*
* @param object the ExpatParser object
* @param object the parent handler that invoked this handler
* @param object the ProjectConfigurator object
* @access public
*/
function __construct($parser, $parentHandler, $configurator) {
$this->configurator = $configurator;
parent::__construct($parser, $parentHandler);
}
/**
* Executes initialization actions required to setup the project. Usually
* this method handles the attributes of a tag.
*
* @param string the tag that comes in
* @param array attributes the tag carries
* @param object the ProjectConfigurator object
* @throws ExpatParseException if attributes are incomplete or invalid
* @access public
*/
function init($tag, $attrs) {
$def = null;
$name = null;
$id = null;
$desc = null;
$baseDir = null;
$ver = null;
// some shorthands
$project = $this->configurator->project;
$buildFileParent = $this->configurator->buildFileParent;
foreach ($attrs as $key => $value) {
if ($key === "default") {
$def = $value;
} elseif ($key === "name") {
$name = $value;
} elseif ($key === "id") {
$id = $value;
} elseif ($key === "basedir") {
$baseDir = $value;
} elseif ($key === "description") {
$desc = $value;
} elseif ($key === "phingVersion") {
$ver = $value;
} else {
throw new ExpatParseException("Unexpected attribute '$key'");
}
}
// these things get done no matter what
if (null != $name) {
$canonicalName = self::canonicalName($name);
$this->configurator->setCurrentProjectName($canonicalName);
$project->setUserProperty("phing.file.{$canonicalName}",
(string) $this->configurator->getBuildFile());
}
if (!$this->configurator->isIgnoringProjectTag()) {
if ($def === null) {
throw new ExpatParseException(
"The default attribute of project is required");
}
$project->setDefaultTarget($def);
if ($name !== null) {
$project->setName($name);
$project->addReference($name, $project);
}
if ($id !== null) {
$project->addReference($id, $project);
}
if ($desc !== null) {
$project->setDescription($desc);
}
if($ver !== null) {
$project->setPhingVersion($ver);
}
if ($project->getProperty("project.basedir") !== null) {
$project->setBasedir($project->getProperty("project.basedir"));
} else {
if ($baseDir === null) {
$project->setBasedir($buildFileParent->getAbsolutePath());
} else {
// check whether the user has specified an absolute path
$f = new PhingFile($baseDir);
if ($f->isAbsolute()) {
$project->setBasedir($baseDir);
} else {
$project->setBaseDir($project->resolveFile($baseDir, new PhingFile(getcwd())));
}
}
}
}
}
/**
* Handles start elements within the <project> tag by creating and
* calling the required handlers for the detected element.
*
* @param string the tag that comes in
* @param array attributes the tag carries
* @throws ExpatParseException if a unxepected element occurs
* @access public
*/
function startElement($name, $attrs) {
$project = $this->configurator->project;
$types = $project->getDataTypeDefinitions();
if ($name == "target") {
$tf = new TargetHandler($this->parser, $this, $this->configurator);
$tf->init($name, $attrs);
} elseif (isset($types[$name])) {
$tyf = new DataTypeHandler($this->parser, $this, $this->configurator);
$tyf->init($name, $attrs);
} else {
$tf = new TaskHandler($this->parser, $this, $this->configurator);
$tf->init($name, $attrs);
}
}
static function canonicalName ($name) {
return preg_replace('/\W/', '_', strtolower($name));
}
}

View file

@ -0,0 +1,82 @@
<?php
/*
* $Id: RootHandler.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>.
*/
require_once 'phing/parser/AbstractHandler.php';
include_once 'phing/parser/ExpatParseException.php';
include_once 'phing/parser/ProjectHandler.php';
/**
* Root filter class for a phing buildfile.
*
* The root filter is called by the parser first. This is where the phing
* specific parsing starts. RootHandler decides what to do next.
*
* @author Andreas Aderhold <andi@binarycloud.com>
* @copyright © 2001,2002 THYRELL. All rights reserved
* @version $Revision: 905 $
* @package phing.parser
*/
class RootHandler extends AbstractHandler {
/**
* The phing project configurator object
*/
private $configurator;
/**
* Constructs a new RootHandler
*
* The root filter is required so the parser knows what to do. It's
* called by the ExpatParser that is instatiated in ProjectConfigurator.
*
* It recieves the expat parse object ref and a reference to the
* configurator
*
* @param AbstractSAXParser $parser The ExpatParser object.
* @param ProjectConfigurator $configurator The ProjectConfigurator object.
*/
function __construct(AbstractSAXParser $parser, ProjectConfigurator $configurator) {
$this->configurator = $configurator;
parent::__construct($parser, $this);
}
/**
* Kick off a custom action for a start element tag.
*
* The root element of our buildfile is the &lt;project&gt; element. The
* root filter handles this element if it occurs, creates ProjectHandler
* to handle any nested tags & attributes of the &lt;project&gt; tag,
* and calls init.
*
* @param string $tag The xml tagname
* @param array $attrs The attributes of the tag
* @throws ExpatParseException if the first element within our build file
* is not the &gt;project&lt; element
*/
function startElement($tag, $attrs) {
if ($tag === "project") {
$ph = new ProjectHandler($this->parser, $this, $this->configurator);
$ph->init($tag, $attrs);
} else {
throw new ExpatParseException("Unexpected tag <$tag> in top-level of build file.", $this->parser->getLocation());
}
}
}

View file

@ -0,0 +1,180 @@
<?php
/*
* $Id: TargetHandler.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>.
*/
require_once 'phing/parser/AbstractHandler.php';
/**
* The target handler class.
*
* This class handles the occurance of a <target> tag and it's possible
* nested tags (datatypes and tasks).
*
* @author Andreas Aderhold <andi@binarycloud.com>
* @copyright 2001,2002 THYRELL. All rights reserved
* @version $Revision: 905 $
* @package phing.parser
*/
class TargetHandler extends AbstractHandler {
/**
* Reference to the target object that represents the currently parsed
* target.
* @var object the target instance
*/
private $target;
/**
* The phing project configurator object
* @var ProjectConfigurator
*/
private $configurator;
/**
* Constructs a new TargetHandler
*
* @param object the ExpatParser object
* @param object the parent handler that invoked this handler
* @param object the ProjectConfigurator object
*/
function __construct(AbstractSAXParser $parser, AbstractHandler $parentHandler, ProjectConfigurator $configurator) {
parent::__construct($parser, $parentHandler);
$this->configurator = $configurator;
}
/**
* Executes initialization actions required to setup the data structures
* related to the tag.
* <p>
* This includes:
* <ul>
* <li>creation of the target object</li>
* <li>calling the setters for attributes</li>
* <li>adding the target to the project</li>
* <li>adding a reference to the target (if id attribute is given)</li>
* </ul>
*
* @param string the tag that comes in
* @param array attributes the tag carries
* @throws ExpatParseException if attributes are incomplete or invalid
*/
function init($tag, $attrs) {
$name = null;
$depends = "";
$ifCond = null;
$unlessCond = null;
$id = null;
$description = null;
foreach($attrs as $key => $value) {
if ($key==="name") {
$name = (string) $value;
} else if ($key==="depends") {
$depends = (string) $value;
} else if ($key==="if") {
$ifCond = (string) $value;
} else if ($key==="unless") {
$unlessCond = (string) $value;
} else if ($key==="id") {
$id = (string) $value;
} else if ($key==="description") {
$description = (string)$value;
} else {
throw new ExpatParseException("Unexpected attribute '$key'", $this->parser->getLocation());
}
}
if ($name === null) {
throw new ExpatParseException("target element appears without a name attribute", $this->parser->getLocation());
}
// shorthand
$project = $this->configurator->project;
// check to see if this target is a dup within the same file
if (isset($this->configurator->getCurrentTargets[$name])) {
throw new BuildException("Duplicate target: $targetName",
$this->parser->getLocation());
}
$this->target = new Target();
$this->target->setName($name);
$this->target->setIf($ifCond);
$this->target->setUnless($unlessCond);
$this->target->setDescription($description);
// take care of dependencies
if (strlen($depends) > 0) {
$this->target->setDepends($depends);
}
$usedTarget = false;
// check to see if target with same name is already defined
$projectTargets = $project->getTargets();
if (isset($projectTargets[$name])) {
$project->log("Already defined in main or a previous import, " .
"ignore {$name}", Project::MSG_VERBOSE);
} else {
$project->addTarget($name, $this->target);
if ($id !== null && $id !== "") {
$project->addReference($id, $this->target);
}
$usedTarget = true;
}
if ($this->configurator->isIgnoringProjectTag() &&
$this->configurator->getCurrentProjectName() != null &&
strlen($this->configurator->getCurrentProjectName()) != 0) {
// In an impored file (and not completely
// ignoring the project tag)
$newName = $this->configurator->getCurrentProjectName() . "." . $name;
if ($usedTarget) {
// clone needs to make target->children a shared reference
$newTarget = clone $this->target;
} else {
$newTarget = $this->target;
}
$newTarget->setName($newName);
$ct = $this->configurator->getCurrentTargets();
$ct[$newName] = $newTarget;
$project->addTarget($newName, $newTarget);
}
}
/**
* Checks for nested tags within the current one. Creates and calls
* handlers respectively.
*
* @param string the tag that comes in
* @param array attributes the tag carries
*/
function startElement($name, $attrs) {
// shorthands
$project = $this->configurator->project;
$types = $project->getDataTypeDefinitions();
if (isset($types[$name])) {
$th = new DataTypeHandler($this->parser, $this, $this->configurator, $this->target);
$th->init($name, $attrs);
} else {
$tmp = new TaskHandler($this->parser, $this, $this->configurator, $this->target, null, $this->target);
$tmp->init($name, $attrs);
}
}
}

View file

@ -0,0 +1,234 @@
<?php
/*
* $Id: TaskHandler.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/UnknownElement.php';
/**
* The task handler class.
*
* This class handles the occurance of a <task> tag and it's possible
* nested tags (datatypes and tasks) that may be unknown off bat and are
* initialized on the fly.
*
* @author Andreas Aderhold <andi@binarycloud.com>
* @copyright <EFBFBD> 2001,2002 THYRELL. All rights reserved
* @version $Revision: 905 $
* @package phing.parser
*/
class TaskHandler extends AbstractHandler {
/**
* Reference to the target object that contains the currently parsed
* task
* @var object the target instance
*/
private $target;
/**
* Reference to the target object that represents the currently parsed
* target. This must not necessarily be a target, hence extra variable.
* @var object the target instance
*/
private $container;
/**
* Reference to the task object that represents the currently parsed
* target.
* @var Task
*/
private $task;
/**
* Wrapper for the parent element, if any. The wrapper for this
* element will be added to this wrapper as a child.
* @var RuntimeConfigurable
*/
private $parentWrapper;
/**
* Wrapper for this element which takes care of actually configuring
* the element, if this element is contained within a target.
* Otherwise the configuration is performed with the configure method.
* @see ProjectHelper::configure(Object,AttributeList,Project)
*/
private $wrapper;
/**
* The phing project configurator object
* @var ProjectConfigurator
*/
private $configurator;
/**
* Constructs a new TaskHandler and sets up everything.
*
* @param AbstractSAXParser The ExpatParser object
* @param object $parentHandler The parent handler that invoked this handler
* @param ProjectConfigurator $configurator
* @param TaskContainer $container The container object this task is contained in (null for top-level tasks).
* @param RuntimeConfigurable $parentWrapper Wrapper for the parent element, if any.
* @param Target $target The target object this task is contained in (null for top-level tasks).
*/
function __construct(AbstractSAXParser $parser, $parentHandler, ProjectConfigurator $configurator, $container = null, $parentWrapper = null, $target = null) {
parent::__construct($parser, $parentHandler);
if (($container !== null) && !($container instanceof TaskContainer)) {
throw new Exception("Argument expected to be a TaskContainer, got something else");
}
if (($parentWrapper !== null) && !($parentWrapper instanceof RuntimeConfigurable)) {
throw new Exception("Argument expected to be a RuntimeConfigurable, got something else.");
}
if (($target !== null) && !($target instanceof Target)) {
throw new Exception("Argument expected to be a Target, got something else");
}
$this->configurator = $configurator;
$this->container = $container;
$this->parentWrapper = $parentWrapper;
$this->target = $target;
}
/**
* Executes initialization actions required to setup the data structures
* related to the tag.
* <p>
* This includes:
* <ul>
* <li>creation of the task object</li>
* <li>calling the setters for attributes</li>
* <li>adding the task to the container object</li>
* <li>adding a reference to the task (if id attribute is given)</li>
* <li>executing the task if the container is the &lt;project&gt;
* element</li>
* </ul>
*
* @param string $tag The tag that comes in
* @param array $attrs Attributes the tag carries
* @throws ExpatParseException if attributes are incomplete or invalid
*/
function init($tag, $attrs) {
// shorthands
try {
$configurator = $this->configurator;
$project = $this->configurator->project;
$this->task = $project->createTask($tag);
} catch (BuildException $be) {
// swallow here, will be thrown again in
// UnknownElement->maybeConfigure if the problem persists.
print("Swallowing exception: ".$be->getMessage() . "\n");
}
// the task is not known of bat, try to load it on thy fly
if ($this->task === null) {
$this->task = new UnknownElement($tag);
$this->task->setProject($project);
$this->task->setTaskType($tag);
$this->task->setTaskName($tag);
}
// add file position information to the task (from parser)
// should be used in task exceptions to provide details
$this->task->setLocation($this->parser->getLocation());
$configurator->configureId($this->task, $attrs);
if ($this->container) {
$this->container->addTask($this->task);
}
// Top level tasks don't have associated targets
// FIXME: if we do like Ant 1.6 and create an implicitTarget in the projectconfigurator object
// then we don't need to check for null here ... but there's a lot of stuff that will break if we
// do that at this point.
if ($this->target !== null) {
$this->task->setOwningTarget($this->target);
$this->task->init();
$this->wrapper = $this->task->getRuntimeConfigurableWrapper();
$this->wrapper->setAttributes($attrs);
/*
Commenting this out as per thread on Premature configurate of ReuntimeConfigurables
with Matthias Pigulla: http://phing.tigris.org/servlets/ReadMsg?list=dev&msgNo=251
if ($this->parentWrapper !== null) { // this may not make sense only within this if-block, but it
// seems to address current use cases adequately
$this->parentWrapper->addChild($this->wrapper);
}
*/
} else {
$this->task->init();
$configurator->configure($this->task, $attrs, $project);
}
}
/**
* Executes the task at once if it's directly beneath the <project> tag.
*/
protected function finished() {
if ($this->task !== null && $this->target === null && $this->container === null) {
try {
$this->task->perform();
} catch (Exception $e) {
$this->task->log($e->getMessage(), Project::MSG_ERR);
throw $e;
}
}
}
/**
* Handles character data.
*
* @param string $data The CDATA that comes in
*/
function characters($data) {
if ($this->wrapper === null) {
$configurator = $this->configurator;
$project = $this->configurator->project;
try { // try
$configurator->addText($project, $this->task, $data);
} catch (BuildException $exc) {
throw new ExpatParseException($exc->getMessage(), $this->parser->getLocation());
}
} else {
$this->wrapper->addText($data);
}
}
/**
* Checks for nested tags within the current one. Creates and calls
* handlers respectively.
*
* @param string $name The tag that comes in
* @param array $attrs Attributes the tag carries
*/
function startElement($name, $attrs) {
$project = $this->configurator->project;
if ($this->task instanceof TaskContainer) {
//print("TaskHandler::startElement() (TaskContainer) name = $name, attrs = " . implode(",",$attrs) . "\n");
$th = new TaskHandler($this->parser, $this, $this->configurator, $this->task, $this->wrapper, $this->target);
$th->init($name, $attrs);
} else {
//print("TaskHandler::startElement() name = $name, attrs = " . implode(",",$attrs) . "\n");
$tmp = new NestedElementHandler($this->parser, $this, $this->configurator, $this->task, $this->wrapper, $this->target);
$tmp->init($name, $attrs);
}
}
}

View file

@ -0,0 +1,168 @@
<?php
/*
* $Id: BufferedReader.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/Reader.php';
/**
* Convenience class for reading files.
*
* @author <a href="mailto:yl@seasonfive.com">Yannick Lecaillez</a>
* @version $Revision: 905 $ $Date: 2010-10-05 18:28:03 +0200 (Tue, 05 Oct 2010) $
* @access public
* @see FilterReader
* @package phing.system.io
*/
class BufferedReader extends Reader {
private $bufferSize = 0;
private $buffer = null;
private $bufferPos = 0;
/**
* The Reader we are buffering for.
*/
private $in;
/**
*
* @param object $reader The reader (e.g. FileReader).
* @param integer $buffsize The size of the buffer we should use for reading files.
* A large buffer ensures that most files (all scripts?) are parsed in 1 buffer.
*/
function __construct(Reader $reader, $buffsize = 65536) {
$this->in = $reader;
$this->bufferSize = $buffsize;
}
/**
* Reads and returns a chunk of data.
* @param int $len Number of bytes to read. Default is to read configured buffer size number of bytes.
* @return mixed buffer or -1 if EOF.
*/
function read($len = null) {
// if $len is specified, we'll use that; otherwise, use the configured buffer size.
if ($len === null) $len = $this->bufferSize;
if ( ($data = $this->in->read($len)) !== -1 ) {
// not all files end with a newline character, so we also need to check EOF
if (!$this->in->eof()) {
$notValidPart = strrchr($data, "\n");
$notValidPartSize = strlen($notValidPart);
if ( $notValidPartSize > 1 ) {
// Block doesn't finish on a EOL
// Find the last EOL and forget all following stuff
$dataSize = strlen($data);
$validSize = $dataSize - $notValidPartSize + 1;
$data = substr($data, 0, $validSize);
// Rewind to the begining of the forgotten stuff.
$this->in->skip(-$notValidPartSize+1);
}
} // if !EOF
}
return $data;
}
function skip($n) {
return $this->in->skip($n);
}
function reset() {
return $this->in->reset();
}
function close() {
return $this->in->close();
}
function open() {
return $this->in->open();
}
/**
* Read a line from input stream.
*/
function readLine() {
$line = null;
while ( ($ch = $this->readChar()) !== -1 ) {
if ( $ch === "\n" ) {
break;
}
$line .= $ch;
}
// Warning : Not considering an empty line as an EOF
if ( $line === null && $ch !== -1 )
return "";
return $line;
}
/**
* Reads a single char from the reader.
* @return string single char or -1 if EOF.
*/
function readChar() {
if ( $this->buffer === null ) {
// Buffer is empty, fill it ...
$read = $this->in->read($this->bufferSize);
if ($read === -1) {
$ch = -1;
} else {
$this->buffer = $read;
return $this->readChar(); // recurse
}
} else {
// Get next buffered char ...
// handle case where buffer is read-in, but is empty. The next readChar() will return -1 EOF,
// so we just return empty string (char) at this point. (Probably could also return -1 ...?)
$ch = ($this->buffer !== "") ? $this->buffer{$this->bufferPos} : '';
$this->bufferPos++;
if ( $this->bufferPos >= strlen($this->buffer) ) {
$this->buffer = null;
$this->bufferPos = 0;
}
}
return $ch;
}
/**
* Returns whether eof has been reached in stream.
* This is important, because filters may want to know if the end of the file (and not just buffer)
* has been reached.
* @return boolean
*/
function eof() {
return $this->in->eof();
}
function getResource() {
return $this->in->getResource();
}
}

View file

@ -0,0 +1,71 @@
<?php
/*
* $Id: BufferedWriter.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/Writer.php';
/**
* Convenience class for writing files.
*
* @author Hans Lellelid <hans@xmpl.org>
* @version $Revision: 905 $
* @package phing.system.io
*/
class BufferedWriter extends Writer {
/**
* The size of the buffer in kb.
*/
private $bufferSize = 0;
/**
* @var Writer The Writer we are buffering output to.
*/
private $out;
public function __construct(Writer $writer, $buffsize = 8192) {
$this->out = $writer;
$this->bufferSize = $buffsize;
}
public function write($buf, $off = null, $len = null) {
return $this->out->write($buf, $off, $len);
}
public function newLine() {
$this->write(PHP_EOL);
}
public function getResource() {
return $this->out->getResource();
}
public function flush() {
$this->out->flush();
}
/**
* Close attached stream.
*/
public function close() {
return $this->out->close();
}
}

View file

@ -0,0 +1,84 @@
<?php
/*
* $Id: ConsoleReader.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/Reader.php';
/**
* Convenience class for reading console input.
*
* @author Hans Lellelid <hans@xmpl.org>
* @author Matthew Hershberger <matthewh@lightsp.com>
* @version $Revision: 905 $
* @package phing.system.io
*/
class ConsoleReader extends Reader {
function readLine() {
$out = fgets(STDIN); // note: default maxlen is 1kb
$out = rtrim($out);
return $out;
}
/**
*
* @param int $len Num chars to read.
* @return string chars read or -1 if eof.
*/
function read($len = null) {
$out = fread(STDIN, $len);
return $out;
// FIXME
// read by chars doesn't work (yet?) with PHP stdin. Maybe
// this is just a language feature, maybe there's a way to get
// ability to read chars w/o <enter> ?
}
function close() {
// STDIN is always open
}
function open() {
// STDIN is always open
}
/**
* Whether eof has been reached with stream.
* @return boolean
*/
function eof() {
return feof(STDIN);
}
/**
* Returns path to file we are reading.
* @return string
*/
function getResource() {
return "console";
}
}

View file

@ -0,0 +1,76 @@
<?php
/*
* $Id: FileInputStream.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>.
*/
require_once 'phing/system/io/InputStream.php';
require_once 'phing/system/io/PhingFile.php';
/**
* Input stream subclass for file streams.
*
* @package phing.system.io
*/
class FileInputStream extends InputStream {
/**
* @var PhingFile The associated file.
*/
protected $file;
/**
* Construct a new FileInputStream.
* @param mixed $file
* @throws Exception - if invalid argument specified.
* @throws IOException - if unable to open file.
*/
public function __construct($file, $append = false) {
if ($file instanceof PhingFile) {
$this->file = $file;
} elseif (is_string($file)) {
$this->file = new PhingFile($file);
} else {
throw new Exception("Invalid argument type for \$file.");
}
$stream = @fopen($this->file->getAbsolutePath(), "rb");
if ($stream === false) {
throw new IOException("Unable to open " . $this->file->__toString() . " for reading: " . $php_errormsg);
}
parent::__construct($stream);
}
/**
* Returns a string representation of the attached file.
* @return string
*/
public function __toString() {
return $this->file->getPath();
}
/**
* Mark is supported by FileInputStream.
* @return boolean TRUE
*/
public function markSupported() {
return true;
}
}

View file

@ -0,0 +1,71 @@
<?php
/*
* $Id: FileOutputStream.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>.
*/
require_once 'phing/system/io/OutputStream.php';
require_once 'phing/system/io/PhingFile.php';
/**
* Output stream subclass for file streams.
*
* @package phing.system.io
*/
class FileOutputStream extends OutputStream {
/**
* @var PhingFile The associated file.
*/
protected $file;
/**
* Construct a new FileOutputStream.
* @param mixed $file
* @param boolean $append Whether to append bytes to end of file rather than beginning.
* @throws Exception - if invalid argument specified.
* @throws IOException - if unable to open file.
*/
public function __construct($file, $append = false) {
if ($file instanceof PhingFile) {
$this->file = $file;
} elseif (is_string($file)) {
$this->file = new PhingFile($file);
} else {
throw new Exception("Invalid argument type for \$file.");
}
if ($append) {
$stream = @fopen($this->file->getAbsolutePath(), "ab");
} else {
$stream = @fopen($this->file->getAbsolutePath(), "wb");
}
if ($stream === false) {
throw new IOException("Unable to open " . $this->file->__toString() . " for writing: " . $php_errormsg);
}
parent::__construct($stream);
}
/**
* Returns a string representation of the attached file.
* @return string
*/
public function __toString() {
return $this->file->getPath();
}
}

View file

@ -0,0 +1,41 @@
<?php
/*
* $Id: FileReader.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>.
*/
require_once 'phing/system/io/InputStreamReader.php';
require_once 'phing/system/io/FileInputStream.php';
/**
* Convenience class for reading files.
* @package phing.system.io
*/
class FileReader extends InputStreamReader {
/**
* Construct a new FileReader.
* @param mixed $file PhingFile or string pathname.
*/
public function __construct($file) {
$in = new FileInputStream($file);
parent::__construct($in);
}
}

View file

@ -0,0 +1,757 @@
<?php
/*
* $Id: FileSystem.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>.
*/
/**
* This is an abstract class for platform specific filesystem implementations
* you have to implement each method in the platform specific filesystem implementation
* classes Your local filesytem implementation must extend this class.
* You should also use this class as a template to write your local implementation
* Some native PHP filesystem specific methods are abstracted here as well. Anyway
* you _must_ always use this methods via a PhingFile object (that by nature uses the
* *FileSystem drivers to access the real filesystem via this class using natives.
*
* FIXME:
* - Error handling reduced to min fallthrough runtime excetions
* more precise errorhandling is done by the PhingFile class
*
* @author Charlie Killian <charlie@tizac.com>
* @author Hans Lellelid <hans@xmpl.org>
* @version $Revision: 905 $
* @package phing.system.io
*/
abstract class FileSystem {
/* properties for simple boolean attributes */
const BA_EXISTS = 0x01;
const BA_REGULAR = 0x02;
const BA_DIRECTORY = 0x04;
const BA_HIDDEN = 0x08;
/** Instance for getFileSystem() method. */
private static $fs;
/**
* Static method to return the FileSystem singelton representing
* this platform's local filesystem driver.
* @return FileSystem
*/
public static function getFileSystem() {
if (self::$fs === null) {
switch(Phing::getProperty('host.fstype')) {
case 'UNIX':
include_once 'phing/system/io/UnixFileSystem.php';
self::$fs = new UnixFileSystem();
break;
case 'WIN32':
include_once 'phing/system/io/Win32FileSystem.php';
self::$fs = new Win32FileSystem();
break;
case 'WINNT':
include_once 'phing/system/io/WinNTFileSystem.php';
self::$fs = new WinNTFileSystem();
break;
default:
throw new Exception("Host uses unsupported filesystem, unable to proceed");
}
}
return self::$fs;
}
/* -- Normalization and construction -- */
/**
* Return the local filesystem's name-separator character.
*/
abstract function getSeparator();
/**
* Return the local filesystem's path-separator character.
*/
abstract function getPathSeparator();
/**
* Convert the given pathname string to normal form. If the string is
* already in normal form then it is simply returned.
*/
abstract function normalize($strPath);
/**
* Compute the length of this pathname string's prefix. The pathname
* string must be in normal form.
*/
abstract function prefixLength($pathname);
/**
* Resolve the child pathname string against the parent.
* Both strings must be in normal form, and the result
* will be a string in normal form.
*/
abstract function resolve($parent, $child);
/**
* Resolve the given abstract pathname into absolute form. Invoked by the
* getAbsolutePath and getCanonicalPath methods in the PhingFile class.
*/
abstract function resolveFile(PhingFile $f);
/**
* Return the parent pathname string to be used when the parent-directory
* argument in one of the two-argument PhingFile constructors is the empty
* pathname.
*/
abstract function getDefaultParent();
/**
* Post-process the given URI path string if necessary. This is used on
* win32, e.g., to transform "/c:/foo" into "c:/foo". The path string
* still has slash separators; code in the PhingFile class will translate them
* after this method returns.
*/
abstract function fromURIPath($path);
/* -- Path operations -- */
/**
* Tell whether or not the given abstract pathname is absolute.
*/
abstract function isAbsolute(PhingFile $f);
/**
* canonicalize filename by checking on disk
* @return mixed Canonical path or false if the file doesn't exist.
*/
function canonicalize($strPath) {
return @realpath($strPath);
}
/* -- Attribute accessors -- */
/**
* Return the simple boolean attributes for the file or directory denoted
* by the given abstract pathname, or zero if it does not exist or some
* other I/O error occurs.
*/
function getBooleanAttributes($f) {
throw new Exception("SYSTEM ERROR method getBooleanAttributes() not implemented by fs driver");
}
/**
* Check whether the file or directory denoted by the given abstract
* pathname may be accessed by this process. If the second argument is
* false, then a check for read access is made; if the second
* argument is true, then a check for write (not read-write)
* access is made. Return false if access is denied or an I/O error
* occurs.
*/
function checkAccess(PhingFile $f, $write = false) {
// we clear stat cache, its expensive to look up from scratch,
// but we need to be sure
@clearstatcache();
// Shouldn't this be $f->GetAbsolutePath() ?
// And why doesn't GetAbsolutePath() work?
$strPath = (string) $f->getPath();
// FIXME
// if file object does denote a file that yet not existst
// path rights are checked
if (!@file_exists($strPath) && !is_dir($strPath)) {
$strPath = $f->getParent();
if ($strPath === null || !is_dir($strPath)) {
$strPath = Phing::getProperty("user.dir");
}
//$strPath = dirname($strPath);
}
if (!$write) {
return (boolean) @is_readable($strPath);
} else {
return (boolean) @is_writable($strPath);
}
}
/**
* Whether file can be deleted.
* @param PhingFile $f
* @return boolean
*/
function canDelete(PhingFile $f)
{
clearstatcache();
$dir = dirname($f->getAbsolutePath());
return (bool) @is_writable($dir);
}
/**
* Return the time at which the file or directory denoted by the given
* abstract pathname was last modified, or zero if it does not exist or
* some other I/O error occurs.
*/
function getLastModifiedTime(PhingFile $f) {
if (!$f->exists()) {
return 0;
}
@clearstatcache();
$strPath = (string) $f->getPath();
$mtime = @filemtime($strPath);
if (false === $mtime) {
// FAILED. Log and return err.
$msg = "FileSystem::Filemtime() FAILED. Cannot can not get modified time of $strPath. $php_errormsg";
throw new Exception($msg);
} else {
return (int) $mtime;
}
}
/**
* Return the length in bytes of the file denoted by the given abstract
* pathname, or zero if it does not exist, is a directory, or some other
* I/O error occurs.
*/
function getLength(PhingFile $f) {
$strPath = (string) $f->getAbsolutePath();
$fs = filesize((string) $strPath);
if ($fs !== false) {
return $fs;
} else {
$msg = "FileSystem::Read() FAILED. Cannot get filesize of $strPath. $php_errormsg";
throw new Exception($msg);
}
}
/* -- File operations -- */
/**
* Create a new empty file with the given pathname. Return
* true if the file was created and false if a
* file or directory with the given pathname already exists. Throw an
* IOException if an I/O error occurs.
*
* @param string Path of the file to be created.
*
* @throws IOException
*/
function createNewFile($strPathname) {
if (@file_exists($strPathname))
return false;
// Create new file
$fp = @fopen($strPathname, "w");
if ($fp === false) {
throw new IOException("The file \"$strPathname\" could not be created");
}
@fclose($fp);
return true;
}
/**
* Delete the file or directory denoted by the given abstract pathname,
* returning true if and only if the operation succeeds.
*/
function delete(PhingFile $f, $recursive = false) {
if ($f->isDirectory()) {
return $this->rmdir($f->getPath(), $recursive);
} else {
return $this->unlink($f->getPath());
}
}
/**
* Arrange for the file or directory denoted by the given abstract
* pathname to be deleted when Phing::shutdown is called, returning
* true if and only if the operation succeeds.
*/
function deleteOnExit($f) {
throw new Exception("deleteOnExit() not implemented by local fs driver");
}
/**
* List the elements of the directory denoted by the given abstract
* pathname. Return an array of strings naming the elements of the
* directory if successful; otherwise, return <code>null</code>.
*/
function listDir(PhingFile $f) {
$strPath = (string) $f->getAbsolutePath();
$d = @dir($strPath);
if (!$d) {
return null;
}
$list = array();
while($entry = $d->read()) {
if ($entry != "." && $entry != "..") {
array_push($list, $entry);
}
}
$d->close();
unset($d);
return $list;
}
/**
* Create a new directory denoted by the given abstract pathname,
* returning true if and only if the operation succeeds.
*
* NOTE: umask() is reset to 0 while executing mkdir(), and restored afterwards
*/
function createDirectory(&$f, $mode = 0755) {
$old_umask = umask(0);
$return = @mkdir($f->getAbsolutePath(), $mode);
umask($old_umask);
return $return;
}
/**
* Rename the file or directory denoted by the first abstract pathname to
* the second abstract pathname, returning true if and only if
* the operation succeeds.
*
* @param PhingFile $f1 abstract source file
* @param PhingFile $f2 abstract destination file
* @return void
* @throws Exception if rename cannot be performed
*/
function rename(PhingFile $f1, PhingFile $f2) {
// get the canonical paths of the file to rename
$src = $f1->getAbsolutePath();
$dest = $f2->getAbsolutePath();
if (false === @rename($src, $dest)) {
$msg = "Rename FAILED. Cannot rename $src to $dest. $php_errormsg";
throw new Exception($msg);
}
}
/**
* Set the last-modified time of the file or directory denoted by the
* given abstract pathname returning true if and only if the
* operation succeeds.
* @return void
* @throws Exception
*/
function setLastModifiedTime(PhingFile $f, $time) {
$path = $f->getPath();
$success = @touch($path, $time);
if (!$success) {
throw new Exception("Could not touch '" . $path . "' due to: $php_errormsg");
}
}
/**
* Mark the file or directory denoted by the given abstract pathname as
* read-only, returning <code>true</code> if and only if the operation
* succeeds.
*/
function setReadOnly($f) {
throw new Exception("setReadonle() not implemented by local fs driver");
}
/* -- Filesystem interface -- */
/**
* List the available filesystem roots, return array of PhingFile objects
*/
function listRoots() {
throw new Exception("SYSTEM ERROR [listRoots() not implemented by local fs driver]");
}
/* -- Basic infrastructure -- */
/**
* Compare two abstract pathnames lexicographically.
*/
function compare($f1, $f2) {
throw new Exception("SYSTEM ERROR [compare() not implemented by local fs driver]");
}
/**
* Copy a file.
*
* @param PhingFile $src Source path and name file to copy.
* @param PhingFile $dest Destination path and name of new file.
*
* @return void
* @throws Exception if file cannot be copied.
*/
function copy(PhingFile $src, PhingFile $dest) {
global $php_errormsg;
// Recursively copy a directory
if($src->isDirectory()) {
return $this->copyr($src->getAbsolutePath(), $dest->getAbsolutePath());
}
$srcPath = $src->getAbsolutePath();
$destPath = $dest->getAbsolutePath();
if (false === @copy($srcPath, $destPath)) { // Copy FAILED. Log and return err.
// Add error from php to end of log message. $php_errormsg.
$msg = "FileSystem::copy() FAILED. Cannot copy $srcPath to $destPath. $php_errormsg";
throw new Exception($msg);
}
try {
$dest->setMode($src->getMode());
} catch(Exception $exc) {
// [MA] does chmod returns an error on systems that do not support it ?
// eat it up for now.
}
}
/**
* Copy a file, or recursively copy a folder and its contents
*
* @author Aidan Lister <aidan@php.net>
* @version 1.0.1
* @link http://aidanlister.com/repos/v/function.copyr.php
* @param string $source Source path
* @param string $dest Destination path
* @return bool Returns TRUE on success, FALSE on failure
*/
function copyr($source, $dest)
{
// Check for symlinks
if (is_link($source)) {
return symlink(readlink($source), $dest);
}
// Simple copy for a file
if (is_file($source)) {
return copy($source, $dest);
}
// Make destination directory
if (!is_dir($dest)) {
mkdir($dest);
}
// Loop through the folder
$dir = dir($source);
while (false !== $entry = $dir->read()) {
// Skip pointers
if ($entry == '.' || $entry == '..') {
continue;
}
// Deep copy directories
$this->copyr("$source/$entry", "$dest/$entry");
}
// Clean up
$dir->close();
return true;
}
/**
* Change the ownership on a file or directory.
*
* @param string $pathname Path and name of file or directory.
* @param string $user The user name or number of the file or directory. See http://us.php.net/chown
*
* @return void
* @throws Exception if operation failed.
*/
function chown($pathname, $user) {
if (false === @chown($pathname, $user)) {// FAILED.
$msg = "FileSystem::chown() FAILED. Cannot chown $pathname. User $user." . (isset($php_errormsg) ? ' ' . $php_errormsg : "");
throw new Exception($msg);
}
}
/**
* Change the group on a file or directory.
*
* @param string $pathname Path and name of file or directory.
* @param string $group The group of the file or directory. See http://us.php.net/chgrp
*
* @return void
* @throws Exception if operation failed.
*/
function chgrp($pathname, $group) {
if (false === @chgrp($pathname, $group)) {// FAILED.
$msg = "FileSystem::chgrp() FAILED. Cannot chown $pathname. Group $group." . (isset($php_errormsg) ? ' ' . $php_errormsg : "");
throw new Exception($msg);
}
}
/**
* Change the permissions on a file or directory.
*
* @param pathname String. Path and name of file or directory.
* @param mode Int. The mode (permissions) of the file or
* directory. If using octal add leading 0. eg. 0777.
* Mode is affected by the umask system setting.
*
* @return void
* @throws Exception if operation failed.
*/
function chmod($pathname, $mode) {
$str_mode = decoct($mode); // Show octal in messages.
if (false === @chmod($pathname, $mode)) {// FAILED.
$msg = "FileSystem::chmod() FAILED. Cannot chmod $pathname. Mode $str_mode." . (isset($php_errormsg) ? ' ' . $php_errormsg : "");
throw new Exception($msg);
}
}
/**
* Locks a file and throws an Exception if this is not possible.
* @return void
* @throws Exception
*/
function lock(PhingFile $f) {
$filename = $f->getPath();
$fp = @fopen($filename, "w");
$result = @flock($fp, LOCK_EX);
@fclose($fp);
if (!$result) {
throw new Exception("Could not lock file '$filename'");
}
}
/**
* Unlocks a file and throws an IO Error if this is not possible.
*
* @throws Exception
* @return void
*/
function unlock(PhingFile $f) {
$filename = $f->getPath();
$fp = @fopen($filename, "w");
$result = @flock($fp, LOCK_UN);
fclose($fp);
if (!$result) {
throw new Exception("Could not unlock file '$filename'");
}
}
/**
* Delete a file.
*
* @param file String. Path and/or name of file to delete.
*
* @return void
* @throws Exception - if an error is encountered.
*/
function unlink($file) {
global $php_errormsg;
if (false === @unlink($file)) {
$msg = "FileSystem::unlink() FAILED. Cannot unlink '$file'. $php_errormsg";
throw new Exception($msg);
}
}
/**
* Symbolically link a file to another name.
*
* Currently symlink is not implemented on Windows. Don't use if the application is to be portable.
*
* @param string $target Path and/or name of file to link.
* @param string $link Path and/or name of link to be created.
* @return void
*/
function symlink($target, $link) {
// If Windows OS then symlink() will report it is not supported in
// the build. Use this error instead of checking for Windows as the OS.
if (false === @symlink($target, $link)) {
// Add error from php to end of log message. $php_errormsg.
$msg = "FileSystem::Symlink() FAILED. Cannot symlink '$target' to '$link'. $php_errormsg";
throw new Exception($msg);
}
}
/**
* Set the modification and access time on a file to the present time.
*
* @param string $file Path and/or name of file to touch.
* @param int $time
* @return void
*/
function touch($file, $time = null) {
global $php_errormsg;
if (null === $time) {
$error = @touch($file);
} else {
$error = @touch($file, $time);
}
if (false === $error) { // FAILED.
// Add error from php to end of log message. $php_errormsg.
$msg = "FileSystem::touch() FAILED. Cannot touch '$file'. $php_errormsg";
throw new Exception($msg);
}
}
/**
* Delete an empty directory OR a directory and all of its contents.
*
* @param dir String. Path and/or name of directory to delete.
* @param children Boolean. False: don't delete directory contents.
* True: delete directory contents.
*
* @return void
*/
function rmdir($dir, $children = false) {
global $php_errormsg;
// If children=FALSE only delete dir if empty.
if (false === $children) {
if (false === @rmdir($dir)) { // FAILED.
// Add error from php to end of log message. $php_errormsg.
$msg = "FileSystem::rmdir() FAILED. Cannot rmdir $dir. $php_errormsg";
throw new Exception($msg);
}
} else { // delete contents and dir.
$handle = @opendir($dir);
if (false === $handle) { // Error.
$msg = "FileSystem::rmdir() FAILED. Cannot opendir() $dir. $php_errormsg";
throw new Exception($msg);
} else { // Read from handle.
// Don't error on readdir().
while (false !== ($entry = @readdir($handle))) {
if ($entry != '.' && $entry != '..') {
// Only add / if it isn't already the last char.
// This ONLY serves the purpose of making the Logger
// output look nice:)
if (strpos(strrev($dir), DIRECTORY_SEPARATOR) === 0) {// there is a /
$next_entry = $dir . $entry;
} else { // no /
$next_entry = $dir . DIRECTORY_SEPARATOR . $entry;
}
// NOTE: As of php 4.1.1 is_dir doesn't return FALSE it
// returns 0. So use == not ===.
// Don't error on is_dir()
if (false == @is_dir($next_entry)) { // Is file.
try {
self::unlink($next_entry); // Delete.
} catch (Exception $e) {
$msg = "FileSystem::Rmdir() FAILED. Cannot FileSystem::Unlink() $next_entry. ". $e->getMessage();
throw new Exception($msg);
}
} else { // Is directory.
try {
self::rmdir($next_entry, true); // Delete
} catch (Exception $e) {
$msg = "FileSystem::rmdir() FAILED. Cannot FileSystem::rmdir() $next_entry. ". $e->getMessage();
throw new Exception($msg);
}
} // end is_dir else
} // end .. if
} // end while
} // end handle if
// Don't error on closedir()
@closedir($handle);
if (false === @rmdir($dir)) { // FAILED.
// Add error from php to end of log message. $php_errormsg.
$msg = "FileSystem::rmdir() FAILED. Cannot rmdir $dir. $php_errormsg";
throw new Exception($msg);
}
}
}
/**
* Set the umask for file and directory creation.
*
* @param mode Int. Permissions ususally in ocatal. Use leading 0 for
* octal. Number between 0 and 0777.
*
* @return void
* @throws Exception if there is an error performing operation.
*/
function umask($mode) {
global $php_errormsg;
// CONSIDERME:
// Throw a warning if mode is 0. PHP converts illegal octal numbers to
// 0 so 0 might not be what the user intended.
$str_mode = decoct($mode); // Show octal in messages.
if (false === @umask($mode)) { // FAILED.
// Add error from php to end of log message. $php_errormsg.
$msg = "FileSystem::Umask() FAILED. Value $mode. $php_errormsg";
throw new Exception($msg);
}
}
/**
* Compare the modified time of two files.
*
* @param file1 String. Path and name of file1.
* @param file2 String. Path and name of file2.
*
* @return Int. 1 if file1 is newer.
* -1 if file2 is newer.
* 0 if files have the same time.
* Err object on failure.
*
* @throws Exception - if cannot get modified time of either file.
*/
function compareMTimes($file1, $file2) {
$mtime1 = filemtime($file1);
$mtime2 = filemtime($file2);
if ($mtime1 === false) { // FAILED. Log and return err.
// Add error from php to end of log message. $php_errormsg.
$msg = "FileSystem::compareMTimes() FAILED. Cannot can not get modified time of $file1.";
throw new Exception($msg);
} elseif ($mtime2 === false) { // FAILED. Log and return err.
// Add error from php to end of log message. $php_errormsg.
$msg = "FileSystem::compareMTimes() FAILED. Cannot can not get modified time of $file2.";
throw new Exception($msg);
} else { // Worked. Log and return compare.
// Compare mtimes.
if ($mtime1 == $mtime2) {
return 0;
} else {
return ($mtime1 < $mtime2) ? -1 : 1;
} // end compare
}
}
}

View file

@ -0,0 +1,42 @@
<?php
/*
* $Id: FileWriter.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>.
*/
require_once 'phing/system/io/OutputStreamWriter.php';
require_once 'phing/system/io/FileOutputStream.php';
/**
* Convenience class for performing file write operations.
*
* @package phing.system.io
*/
class FileWriter extends OutputStreamWriter {
/**
* Construct a new FileWriter.
* @param mixed $file PhingFile or string pathname.
* @param boolean $append Append to existing file?
*/
function __construct($file, $append = false) {
$out = new FileOutputStream($file, $append);
parent::__construct($out);
}
}

View file

@ -0,0 +1,68 @@
<?php
/*
* $Id: FilterReader.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>.
*/
require_once 'phing/system/io/Reader.php';
/**
* Wrapper class for readers, which can be used to apply filters.
* @package phing.system.io
*/
class FilterReader extends Reader {
/**
* @var Reader
*/
protected $in;
function __construct(Reader $in = null) {
$this->in = $in;
}
public function setReader(Reader $in) {
$this->in = $in;
}
public function skip($n) {
return $this->in->skip($n);
}
/**
* Read data from source.
* FIXME: Clean up this function signature, as it a) params aren't being used
* and b) it doesn't make much sense.
*/
public function read($len = null) {
return $this->in->read($len);
}
public function reset() {
return $this->in->reset();
}
public function close() {
return $this->in->close();
}
function getResource() {
return $this->in->getResource();
}
}

View file

@ -0,0 +1,27 @@
<?php
/*
* $Id: IOException.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>.
*/
/**
* Extends Exception to take advantage of methods therein.
*
* @package phing.system.io
*/
class IOException extends Exception {}

View file

@ -0,0 +1,178 @@
<?php
/*
* $Id: InputStream.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>.
*/
/**
* Wrapper class for PHP stream that supports read operations.
*
* @package phing.system.io
*/
class InputStream {
/**
* @var resource The attached PHP stream.
*/
protected $stream;
/**
* @var int Position of stream cursor.
*/
protected $currentPosition = 0;
/**
* @var int Marked position of stream cursor.
*/
protected $mark = 0;
/**
* Construct a new InputStream.
* @param resource $stream Configured PHP stream for writing.
*/
public function __construct($stream) {
if (!is_resource($stream)) {
throw new IOException("Passed argument is not a valid stream.");
}
$this->stream = $stream;
}
/**
* Skip over $n bytes.
* @param int $n
*/
public function skip($n) {
$start = $this->currentPosition;
$ret = @fseek($this->stream, $n, SEEK_CUR);
if ( $ret === -1 )
return -1;
$this->currentPosition = ftell($this->stream);
if ( $start > $this->currentPosition )
$skipped = $start - $this->currentPosition;
else
$skipped = $this->currentPosition - $start;
return $skipped;
}
/**
* Read data from stream until $len chars or EOF.
* @param int $len Num chars to read. If not specified this stream will read until EOF.
* @return string chars read or -1 if eof.
*/
public function read($len = null) {
if ($this->eof()) {
return -1;
}
if ($len === null) { // we want to keep reading until we get an eof
$out = "";
while(!$this->eof()) {
$out .= fread($this->stream, 8192);
$this->currentPosition = ftell($this->stream);
}
} else {
$out = fread($this->stream, $len); // adding 1 seems to ensure that next call to read() will return EOF (-1)
$this->currentPosition = ftell($this->stream);
}
return $out;
}
/**
* Marks the current position in this input stream.
* @throws IOException - if the underlying stream doesn't support this method.
*/
public function mark() {
if (!$this->markSupported()) {
throw new IOException(get_class($this) . " does not support mark() and reset() methods.");
}
$this->mark = $this->currentPosition;
}
/**
* Whether the input stream supports mark and reset methods.
* @return boolean
*/
public function markSupported() {
return false;
}
/**
* Repositions this stream to the position at the time the mark method was last called on this input stream.
* @throws IOException - if the underlying stream doesn't support this method.
*/
function reset() {
if (!$this->markSupported()) {
throw new IOException(get_class($this) . " does not support mark() and reset() methods.");
}
// goes back to last mark, by default this would be 0 (i.e. rewind file).
fseek($this->stream, SEEK_SET, $this->mark);
$this->mark = 0;
}
/**
* Closes stream.
* @throws IOException if stream cannot be closed (note that calling close() on an already-closed stream will not raise an exception)
*/
public function close() {
if ($this->stream === null) {
return;
}
if (false === @fclose($this->stream)) {
// FAILED.
$msg = "Cannot fclose " . $this->file->__toString() . " $php_errormsg";
throw new IOException($msg);
}
$this->stream = null;
}
/**
* Whether eof has been reached with stream.
* @return boolean
*/
public function eof() {
return feof($this->stream);
}
/**
* Reads a entire until EOF and places contents in passed-in variable. Stream is closed after read.
*
* @param string &$rBuffer String variable where read contents will be put.
* @return TRUE on success.
* @author Charlie Killian, charlie@tizac.com
* @throws IOException - if there is an error reading from stream.
* @deprecated - Instead, use the read() method or a BufferedReader.
*/
public function readInto(&$rBuffer) {
$rBuffer = $this->read();
$this->close();
}
/**
* Returns string representation of attached stream.
* @return string
*/
public function __toString() {
return (string) $this->stream;
}
}

View file

@ -0,0 +1,127 @@
<?php
/*
* $Id: InputStreamReader.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/system/io/Reader.php';
/**
* Writer class for OutputStream objects.
*
* Unlike the Java counterpart, this class does not (yet) handle
* character set transformations. This will be an important function
* of this class with move to supporting PHP6.
*
* @package phing.system.io
*/
class InputStreamReader extends Reader {
/**
* @var InputStream
*/
protected $inStream;
/**
* Construct a new InputStreamReader.
* @param InputStream $$inStream InputStream to read from
*/
public function __construct(InputStream $inStream) {
$this->inStream = $inStream;
}
/**
* Close the stream.
*/
public function close() {
return $this->inStream->close();
}
/**
* Skip over $n bytes.
* @param int $n
*/
public function skip($n) {
return $this->inStream->skip($n);
}
/**
* Read data from file.
* @param int $len Num chars to read.
* @return string chars read or -1 if eof.
*/
public function read($len = null) {
return $this->inStream->read($len);
}
/**
* Marks the current position in this input stream.
* @throws IOException - if the underlying stream doesn't support this method.
*/
public function mark() {
$this->inStream->mark();
}
/**
* Whether the attached stream supports mark/reset.
* @return boolean
*/
public function markSupported() {
return $this->inStream->markSupported();
}
/**
* Repositions this stream to the position at the time the mark method was last called on this input stream.
* @throws IOException - if the underlying stream doesn't support this method.
*/
public function reset() {
$this->inStream->reset();
}
/**
* Whether eof has been reached with stream.
* @return boolean
*/
public function eof() {
return $this->inStream->eof();
}
/**
* Reads a entire file and stores the data in the variable
* passed by reference.
*
* @param string $file String. Path and/or name of file to read.
* @param object &$rBuffer Reference. Variable of where to put contents.
*
* @return TRUE on success. Err object on failure.
* @author Charlie Killian, charlie@tizac.com
* @deprecated Use read() or BufferedReader instead.
*/
public function readInto(&$rBuffer) {
return $this->inStream->readInto($rBuffer);
}
/**
* Returns string representation of attached stream.
* @return string
*/
public function getResource() {
return $this->inStream->__toString();
}
}

View file

@ -0,0 +1,108 @@
<?php
/*
* $Id: OutputStream.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>.
*/
/**
* Wrapper class for PHP stream that supports write operations.
*
* @package phing.system.io
*/
class OutputStream {
/**
* @var resource The configured PHP stream.
*/
protected $stream;
/**
* Construct a new OutputStream.
* @param resource $stream Configured PHP stream for writing.
*/
public function __construct($stream) {
if (!is_resource($stream)) {
throw new IOException("Passed argument is not a valid stream.");
}
$this->stream = $stream;
}
/**
* Closes attached stream, flushing output first.
* @throws IOException if cannot close stream (note that attempting to close an already closed stream will not raise an IOException)
* @return void
*/
public function close() {
if ($this->stream === null) {
return;
}
$this->flush();
if (false === @fclose($this->stream)) {
$msg = "Cannot close " . $this->getResource() . ": $php_errormsg";
throw new IOException($msg);
}
$this->stream = null;
}
/**
* Flushes stream.
*
* @throws IOException if unable to flush data (e.g. stream is not open).
*/
public function flush() {
if (false === @fflush($this->stream)) {
throw new IOException("Could not flush stream: " . $php_errormsg);
}
}
/**
* Writes data to stream.
*
* @param string $buf Binary/character data to write.
* @param int $off (Optional) offset.
* @param int $len (Optional) number of bytes/chars to write.
* @return void
* @throws IOException - if there is an error writing to stream
*/
public function write($buf, $off = null, $len = null) {
if ( $off === null && $len === null ) {
$to_write = $buf;
} elseif ($off !== null && $len === null) {
$to_write = substr($buf, $off);
} elseif ($off === null && $len !== null) {
$to_write = substr($buf, 0, $len);
} else {
$to_write = substr($buf, $off, $len);
}
$result = @fwrite($this->stream, $to_write);
if ( $result === false ) {
throw new IOException("Error writing to stream.");
}
}
/**
* Returns a string representation of the attached PHP stream.
* @return string
*/
public function __toString() {
return (string) $this->stream;
}
}

View file

@ -0,0 +1,84 @@
<?php
/*
* $Id: OutputStreamWriter.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';
require_once 'phing/system/io/Writer.php';
/**
* Writer class for OutputStream objects.
*
* Unlike the Java counterpart, this class does not (yet) handle
* character set transformations. This will be an important function
* of this class with move to supporting PHP6.
*
* @package phing.system.io
*/
class OutputStreamWriter extends Writer {
/**
* @var OutputStream
*/
protected $outStream;
/**
* Construct a new OutputStreamWriter.
* @param OutputStream $outStream OutputStream to write to
*/
public function __construct(OutputStream $outStream) {
$this->outStream = $outStream;
}
/**
* Close the stream.
*/
public function close() {
return $this->outStream->close();
}
/**
* Write char data to stream.
*
* @param unknown_type $buf
* @param unknown_type $off
* @param unknown_type $len
* @return unknown
*/
public function write($buf, $off = null, $len = null) {
return $this->outStream->write($buf, $off, $len);
}
/**
* Flush output to the stream.
*/
public function flush() {
$this->outStream->flush();
}
/**
* Gets a string representation of attached stream resource.
*
* @return string String representation of output stream
*/
public function getResource() {
return $this->outStream->__toString();
}
}

View file

@ -0,0 +1,951 @@
<?php
/*
* $Id: PhingFile.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/FileSystem.php';
include_once 'phing/system/lang/NullPointerException.php';
/**
* An abstract representation of file and directory pathnames.
*
* @version $Revision: 905 $
* @package phing.system.io
*/
class PhingFile {
/** separator string, static, obtained from FileSystem */
public static $separator;
/** path separator string, static, obtained from FileSystem (; or :)*/
public static $pathSeparator;
/**
* This abstract pathname's normalized pathname string. A normalized
* pathname string uses the default name-separator character and does not
* contain any duplicate or redundant separators.
*/
private $path = null;
/** The length of this abstract pathname's prefix, or zero if it has no prefix. */
private $prefixLength = 0;
/** constructor */
function __construct($arg1 = null, $arg2 = null) {
if (self::$separator === null || self::$pathSeparator === null) {
$fs = FileSystem::getFileSystem();
self::$separator = $fs->getSeparator();
self::$pathSeparator = $fs->getPathSeparator();
}
/* simulate signature identified constructors */
if ($arg1 instanceof PhingFile && is_string($arg2)) {
$this->_constructFileParentStringChild($arg1, $arg2);
} elseif (is_string($arg1) && ($arg2 === null)) {
$this->_constructPathname($arg1);
} elseif(is_string($arg1) && is_string($arg2)) {
$this->_constructStringParentStringChild($arg1, $arg2);
} else {
if ($arg1 === null) {
throw new NullPointerException("Argument1 to function must not be null");
}
$this->path = (string) $arg1;
$this->prefixLength = (int) $arg2;
}
}
/** Returns the length of this abstract pathname's prefix. */
function getPrefixLength() {
return (int) $this->prefixLength;
}
/* -- constructors not called by signature match, so we need some helpers --*/
function _constructPathname($pathname) {
// obtain ref to the filesystem layer
$fs = FileSystem::getFileSystem();
if ($pathname === null) {
throw new NullPointerException("Argument to function must not be null");
}
$this->path = (string) $fs->normalize($pathname);
$this->prefixLength = (int) $fs->prefixLength($this->path);
}
function _constructStringParentStringChild($parent, $child = null) {
// obtain ref to the filesystem layer
$fs = FileSystem::getFileSystem();
if ($child === null) {
throw new NullPointerException("Argument to function must not be null");
}
if ($parent !== null) {
if ($parent === "") {
$this->path = $fs->resolve($fs->getDefaultParent(), $fs->normalize($child));
} else {
$this->path = $fs->resolve($fs->normalize($parent), $fs->normalize($child));
}
} else {
$this->path = (string) $fs->normalize($child);
}
$this->prefixLength = (int) $fs->prefixLength($this->path);
}
function _constructFileParentStringChild($parent, $child = null) {
// obtain ref to the filesystem layer
$fs = FileSystem::getFileSystem();
if ($child === null) {
throw new NullPointerException("Argument to function must not be null");
}
if ($parent !== null) {
if ($parent->path === "") {
$this->path = $fs->resolve($fs->getDefaultParent(), $fs->normalize($child));
} else {
$this->path = $fs->resolve($parent->path, $fs->normalize($child));
}
} else {
$this->path = $fs->normalize($child);
}
$this->prefixLength = $fs->prefixLength($this->path);
}
/* -- Path-component accessors -- */
/**
* Returns the name of the file or directory denoted by this abstract
* pathname. This is just the last name in the pathname's name
* sequence. If the pathname's name sequence is empty, then the empty
* string is returned.
*
* @return The name of the file or directory denoted by this abstract
* pathname, or the empty string if this pathname's name sequence
* is empty
*/
function getName() {
// that's a lastIndexOf
$index = ((($res = strrpos($this->path, self::$separator)) === false) ? -1 : $res);
if ($index < $this->prefixLength) {
return substr($this->path, $this->prefixLength);
}
return substr($this->path, $index + 1);
}
/**
* Returns the pathname string of this abstract pathname's parent, or
* null if this pathname does not name a parent directory.
*
* The parent of an abstract pathname consists of the pathname's prefix,
* if any, and each name in the pathname's name sequence except for the last.
* If the name sequence is empty then the pathname does not name a parent
* directory.
*
* @return The pathname string of the parent directory named by this
* abstract pathname, or null if this pathname does not name a parent
*/
function getParent() {
// that's a lastIndexOf
$index = ((($res = strrpos($this->path, self::$separator)) === false) ? -1 : $res);
if ($index < $this->prefixLength) {
if (($this->prefixLength > 0) && (strlen($this->path) > $this->prefixLength)) {
return substr($this->path, 0, $this->prefixLength);
}
return null;
}
return substr($this->path, 0, $index);
}
/**
* Returns the abstract pathname of this abstract pathname's parent,
* or null if this pathname does not name a parent directory.
*
* The parent of an abstract pathname consists of the pathname's prefix,
* if any, and each name in the pathname's name sequence except for the
* last. If the name sequence is empty then the pathname does not name
* a parent directory.
*
* @return The abstract pathname of the parent directory named by this
* abstract pathname, or null if this pathname
* does not name a parent
*/
function getParentFile() {
$p = $this->getParent();
if ($p === null) {
return null;
}
return new PhingFile((string) $p, (int) $this->prefixLength);
}
/**
* Converts this abstract pathname into a pathname string. The resulting
* string uses the default name-separator character to separate the names
* in the name sequence.
*
* @return The string form of this abstract pathname
*/
function getPath() {
return (string) $this->path;
}
/**
* Returns path without leading basedir.
*
* @param string $basedir Base directory to strip
*
* @return string Path without basedir
*
* @uses getPath()
*/
function getPathWithoutBase($basedir)
{
if (!StringHelper::endsWith(self::$separator, $basedir)) {
$basedir .= self::$separator;
}
$path = $this->getPath();
if (!substr($path, 0, strlen($basedir)) == $basedir) {
//path does not begin with basedir, we don't modify it
return $path;
}
return substr($path, strlen($basedir));
}
/**
* Tests whether this abstract pathname is absolute. The definition of
* absolute pathname is system dependent. On UNIX systems, a pathname is
* absolute if its prefix is "/". On Win32 systems, a pathname is absolute
* if its prefix is a drive specifier followed by "\\", or if its prefix
* is "\\".
*
* @return true if this abstract pathname is absolute, false otherwise
*/
function isAbsolute() {
return ($this->prefixLength !== 0);
}
/**
* Returns the absolute pathname string of this abstract pathname.
*
* If this abstract pathname is already absolute, then the pathname
* string is simply returned as if by the getPath method.
* If this abstract pathname is the empty abstract pathname then
* the pathname string of the current user directory, which is named by the
* system property user.dir, is returned. Otherwise this
* pathname is resolved in a system-dependent way. On UNIX systems, a
* relative pathname is made absolute by resolving it against the current
* user directory. On Win32 systems, a relative pathname is made absolute
* by resolving it against the current directory of the drive named by the
* pathname, if any; if not, it is resolved against the current user
* directory.
*
* @return The absolute pathname string denoting the same file or
* directory as this abstract pathname
* @see #isAbsolute()
*/
function getAbsolutePath() {
$fs = FileSystem::getFileSystem();
return $fs->resolveFile($this);
}
/**
* Returns the absolute form of this abstract pathname. Equivalent to
* getAbsolutePath.
*
* @return The absolute abstract pathname denoting the same file or
* directory as this abstract pathname
*/
function getAbsoluteFile() {
return new PhingFile((string) $this->getAbsolutePath());
}
/**
* Returns the canonical pathname string of this abstract pathname.
*
* A canonical pathname is both absolute and unique. The precise
* definition of canonical form is system-dependent. This method first
* converts this pathname to absolute form if necessary, as if by invoking the
* getAbsolutePath() method, and then maps it to its unique form in a
* system-dependent way. This typically involves removing redundant names
* such as "." and .. from the pathname, resolving symbolic links
* (on UNIX platforms), and converting drive letters to a standard case
* (on Win32 platforms).
*
* Every pathname that denotes an existing file or directory has a
* unique canonical form. Every pathname that denotes a nonexistent file
* or directory also has a unique canonical form. The canonical form of
* the pathname of a nonexistent file or directory may be different from
* the canonical form of the same pathname after the file or directory is
* created. Similarly, the canonical form of the pathname of an existing
* file or directory may be different from the canonical form of the same
* pathname after the file or directory is deleted.
*
* @return The canonical pathname string denoting the same file or
* directory as this abstract pathname
*/
function getCanonicalPath() {
$fs = FileSystem::getFileSystem();
return $fs->canonicalize($this->path);
}
/**
* Returns the canonical form of this abstract pathname. Equivalent to
* getCanonicalPath(.
*
* @return PhingFile The canonical pathname string denoting the same file or
* directory as this abstract pathname
*/
function getCanonicalFile() {
return new PhingFile($this->getCanonicalPath());
}
/**
* Converts this abstract pathname into a file: URL. The
* exact form of the URL is system-dependent. If it can be determined that
* the file denoted by this abstract pathname is a directory, then the
* resulting URL will end with a slash.
*
* Usage note: This method does not automatically escape
* characters that are illegal in URLs. It is recommended that new code
* convert an abstract pathname into a URL by first converting it into a
* URI, via the toURI() method, and then converting the URI
* into a URL via the URI::toURL()
*
* @return A URL object representing the equivalent file URL
*
*
*/
function toURL() {
/*
// URL class not implemented yet
return new URL("file", "", $this->_slashify($this->getAbsolutePath(), $this->isDirectory()));
*/
}
/**
* Constructs a file: URI that represents this abstract pathname.
* Not implemented yet
*/
function toURI() {
/*
$f = $this->getAbsoluteFile();
$sp = (string) $this->slashify($f->getPath(), $f->isDirectory());
if (StringHelper::startsWith('//', $sp))
$sp = '//' + sp;
return new URI('file', null, $sp, null);
*/
}
function _slashify($path, $isDirectory) {
$p = (string) $path;
if (self::$separator !== '/') {
$p = str_replace(self::$separator, '/', $p);
}
if (!StringHelper::startsWith('/', $p)) {
$p = '/'.$p;
}
if (!StringHelper::endsWith('/', $p) && $isDirectory) {
$p = $p.'/';
}
return $p;
}
/* -- Attribute accessors -- */
/**
* Tests whether the application can read the file denoted by this
* abstract pathname.
*
* @return true if and only if the file specified by this
* abstract pathname exists and can be read by the
* application; false otherwise
*/
function canRead() {
$fs = FileSystem::getFileSystem();
if ($fs->checkAccess($this)) {
return (boolean) @is_readable($this->getAbsolutePath());
}
return false;
}
/**
* Tests whether the application can modify to the file denoted by this
* abstract pathname.
*
* @return true if and only if the file system actually
* contains a file denoted by this abstract pathname and
* the application is allowed to write to the file;
* false otherwise.
*
*/
function canWrite() {
$fs = FileSystem::getFileSystem();
return $fs->checkAccess($this, true);
}
/**
* Tests whether the file denoted by this abstract pathname exists.
*
* @return true if and only if the file denoted by this
* abstract pathname exists; false otherwise
*
*/
function exists() {
clearstatcache();
if (is_link($this->path)) {
return true;
} else if ($this->isFile()) {
return @file_exists($this->path) || is_link($this->path);
} else {
return @is_dir($this->path);
}
}
/**
* Tests whether the file denoted by this abstract pathname is a
* directory.
*
* @return true if and only if the file denoted by this
* abstract pathname exists and is a directory;
* false otherwise
*
*/
function isDirectory() {
clearstatcache();
$fs = FileSystem::getFileSystem();
if ($fs->checkAccess($this) !== true) {
throw new IOException("No read access to ".$this->path);
}
return @is_dir($this->path) && !@is_link($this->path);
}
/**
* Tests whether the file denoted by this abstract pathname is a normal
* file. A file is normal if it is not a directory and, in
* addition, satisfies other system-dependent criteria. Any non-directory
* file created by a Java application is guaranteed to be a normal file.
*
* @return true if and only if the file denoted by this
* abstract pathname exists and is a normal file;
* false otherwise
*/
function isFile() {
clearstatcache();
//$fs = FileSystem::getFileSystem();
return @is_file($this->path);
}
/**
* Tests whether the file named by this abstract pathname is a hidden
* file. The exact definition of hidden is system-dependent. On
* UNIX systems, a file is considered to be hidden if its name begins with
* a period character ('.'). On Win32 systems, a file is considered to be
* hidden if it has been marked as such in the filesystem. Currently there
* seems to be no way to dermine isHidden on Win file systems via PHP
*
* @return true if and only if the file denoted by this
* abstract pathname is hidden according to the conventions of the
* underlying platform
*/
function isHidden() {
$fs = FileSystem::getFileSystem();
if ($fs->checkAccess($this) !== true) {
throw new IOException("No read access to ".$this->path);
}
return (($fs->getBooleanAttributes($this) & $fs->BA_HIDDEN) !== 0);
}
/**
* Tests whether the file denoted by this abstract pathname is a symbolic link.
*
* @return true if and only if the file denoted by this
* abstract pathname exists and is a symbolic link;
* false otherwise
*/
public function isLink()
{
clearstatcache();
$fs = FileSystem::getFileSystem();
if ($fs->checkAccess($this) !== true) {
throw new IOException("No read access to ".$this->path);
}
return @is_link($this->path);
}
/**
* Returns the target of the symbolic link denoted by this abstract pathname
*
* @return the target of the symbolic link denoted by this abstract pathname
*/
public function getLinkTarget()
{
return @readlink($this->path);
}
/**
* Returns the time that the file denoted by this abstract pathname was
* last modified.
*
* @return A integer value representing the time the file was
* last modified, measured in milliseconds since the epoch
* (00:00:00 GMT, January 1, 1970), or 0 if the
* file does not exist or if an I/O error occurs
*/
function lastModified() {
$fs = FileSystem::getFileSystem();
if ($fs->checkAccess($this) !== true) {
throw new IOException("No read access to " . $this->path);
}
return $fs->getLastModifiedTime($this);
}
/**
* Returns the length of the file denoted by this abstract pathname.
* The return value is unspecified if this pathname denotes a directory.
*
* @return The length, in bytes, of the file denoted by this abstract
* pathname, or 0 if the file does not exist
*/
function length() {
$fs = FileSystem::getFileSystem();
if ($fs->checkAccess($this) !== true) {
throw new IOException("No read access to ".$this->path."\n");
}
return $fs->getLength($this);
}
/**
* Convenience method for returning the contents of this file as a string.
* This method uses file_get_contents() to read file in an optimized way.
* @return string
* @throws Exception - if file cannot be read
*/
function contents() {
if (!$this->canRead() || !$this->isFile()) {
throw new IOException("Cannot read file contents!");
}
return file_get_contents($this->getAbsolutePath());
}
/* -- File operations -- */
/**
* Atomically creates a new, empty file named by this abstract pathname if
* and only if a file with this name does not yet exist. The check for the
* existence of the file and the creation of the file if it does not exist
* are a single operation that is atomic with respect to all other
* filesystem activities that might affect the file.
*
* @return true if the named file does not exist and was
* successfully created; <code>false</code> if the named file
* already exists
* @throws IOException if file can't be created
*/
function createNewFile($parents=true, $mode=0777) {
$file = FileSystem::getFileSystem()->createNewFile($this->path);
return $file;
}
/**
* Deletes the file or directory denoted by this abstract pathname. If
* this pathname denotes a directory, then the directory must be empty in
* order to be deleted.
*
* @return true if and only if the file or directory is
* successfully deleted; false otherwise
*/
function delete($recursive = false) {
$fs = FileSystem::getFileSystem();
if ($fs->canDelete($this) !== true) {
throw new IOException("Cannot delete " . $this->path . "\n");
}
return $fs->delete($this, $recursive);
}
/**
* Requests that the file or directory denoted by this abstract pathname
* be deleted when php terminates. Deletion will be attempted only for
* normal termination of php and if and if only Phing::shutdown() is
* called.
*
* Once deletion has been requested, it is not possible to cancel the
* request. This method should therefore be used with care.
*
*/
function deleteOnExit() {
$fs = FileSystem::getFileSystem();
$fs->deleteOnExit($this);
}
/**
* Returns an array of strings naming the files and directories in the
* directory denoted by this abstract pathname.
*
* If this abstract pathname does not denote a directory, then this
* method returns null Otherwise an array of strings is
* returned, one for each file or directory in the directory. Names
* denoting the directory itself and the directory's parent directory are
* not included in the result. Each string is a file name rather than a
* complete path.
*
* There is no guarantee that the name strings in the resulting array
* will appear in any specific order; they are not, in particular,
* guaranteed to appear in alphabetical order.
*
* @return An array of strings naming the files and directories in the
* directory denoted by this abstract pathname. The array will be
* empty if the directory is empty. Returns null if
* this abstract pathname does not denote a directory, or if an
* I/O error occurs.
*
*/
function listDir($filter = null) {
$fs = FileSystem::getFileSystem();
return $fs->lister($this, $filter);
}
function listFiles($filter = null) {
$ss = $this->listDir($filter);
if ($ss === null) {
return null;
}
$n = count($ss);
$fs = array();
for ($i = 0; $i < $n; $i++) {
$fs[$i] = new PhingFile((string)$this->path, (string)$ss[$i]);
}
return $fs;
}
/**
* Creates the directory named by this abstract pathname, including any
* necessary but nonexistent parent directories. Note that if this
* operation fails it may have succeeded in creating some of the necessary
* parent directories.
*
* @return true if and only if the directory was created,
* along with all necessary parent directories; false
* otherwise
* @throws IOException
*/
function mkdirs($mode = 0755) {
if ($this->exists()) {
return false;
}
try {
if ($this->mkdir($mode)) {
return true;
}
} catch (IOException $ioe) {
// IOException from mkdir() means that directory propbably didn't exist.
}
$parentFile = $this->getParentFile();
return (($parentFile !== null) && ($parentFile->mkdirs($mode) && $this->mkdir($mode)));
}
/**
* Creates the directory named by this abstract pathname.
*
* @return true if and only if the directory was created; false otherwise
* @throws IOException
*/
function mkdir($mode = 0755) {
$fs = FileSystem::getFileSystem();
if ($fs->checkAccess(new PhingFile($this->path), true) !== true) {
throw new IOException("No write access to " . $this->getPath());
}
return $fs->createDirectory($this, $mode);
}
/**
* Renames the file denoted by this abstract pathname.
*
* @param destFile The new abstract pathname for the named file
* @return true if and only if the renaming succeeded; false otherwise
*/
function renameTo(PhingFile $destFile) {
$fs = FileSystem::getFileSystem();
if ($fs->checkAccess($this) !== true) {
throw new IOException("No write access to ".$this->getPath());
}
return $fs->rename($this, $destFile);
}
/**
* Simple-copies file denoted by this abstract pathname into another
* PhingFile
*
* @param PhingFile $destFile The new abstract pathname for the named file
* @return true if and only if the renaming succeeded; false otherwise
*/
function copyTo(PhingFile $destFile) {
$fs = FileSystem::getFileSystem();
if ($fs->checkAccess($this) !== true) {
throw new IOException("No read access to ".$this->getPath()."\n");
}
if ($fs->checkAccess($destFile, true) !== true) {
throw new IOException("File::copyTo() No write access to ".$destFile->getPath());
}
return $fs->copy($this, $destFile);
}
/**
* Sets the last-modified time of the file or directory named by this
* abstract pathname.
*
* All platforms support file-modification times to the nearest second,
* but some provide more precision. The argument will be truncated to fit
* the supported precision. If the operation succeeds and no intervening
* operations on the file take place, then the next invocation of the
* lastModified method will return the (possibly truncated) time argument
* that was passed to this method.
*
* @param time The new last-modified time, measured in milliseconds since
* the epoch (00:00:00 GMT, January 1, 1970)
* @return true if and only if the operation succeeded; false otherwise
*/
function setLastModified($time) {
$time = (int) $time;
if ($time < 0) {
throw new Exception("IllegalArgumentException, Negative $time\n");
}
$fs = FileSystem::getFileSystem();
return $fs->setLastModifiedTime($this, $time);
}
/**
* Marks the file or directory named by this abstract pathname so that
* only read operations are allowed. After invoking this method the file
* or directory is guaranteed not to change until it is either deleted or
* marked to allow write access. Whether or not a read-only file or
* directory may be deleted depends upon the underlying system.
*
* @return true if and only if the operation succeeded; false otherwise
*/
function setReadOnly() {
$fs = FileSystem::getFileSystem();
if ($fs->checkAccess($this, true) !== true) {
// Error, no write access
throw new IOException("No write access to " . $this->getPath());
}
return $fs->setReadOnly($this);
}
/**
* Sets the owner of the file.
* @param mixed $user User name or number.
*/
public function setUser($user) {
$fs = FileSystem::getFileSystem();
return $fs->chown($this->getPath(), $user);
}
/**
* Retrieve the owner of this file.
* @return int User ID of the owner of this file.
*/
function getUser() {
return @fileowner($this->getPath());
}
/**
* Sets the group of the file.
* @param mixed $user User name or number.
*/
public function setGroup($group) {
$fs = FileSystem::getFileSystem();
return $fs->chgrp($this->getPath(), $group);
}
/**
* Retrieve the group of this file.
* @return int User ID of the owner of this file.
*/
function getGroup() {
return @filegroup($this->getPath());
}
/**
* Sets the mode of the file
* @param int $mode Ocatal mode.
*/
function setMode($mode) {
$fs = FileSystem::getFileSystem();
return $fs->chmod($this->getPath(), $mode);
}
/**
* Retrieve the mode of this file.
* @return int
*/
function getMode() {
return @fileperms($this->getPath());
}
/* -- Filesystem interface -- */
/**
* List the available filesystem roots.
*
* A particular platform may support zero or more hierarchically-organized
* file systems. Each file system has a root directory from which all
* other files in that file system can be reached.
* Windows platforms, for example, have a root directory for each active
* drive; UNIX platforms have a single root directory, namely "/".
* The set of available filesystem roots is affected by various system-level
* operations such the insertion or ejection of removable media and the
* disconnecting or unmounting of physical or virtual disk drives.
*
* This method returns an array of PhingFile objects that
* denote the root directories of the available filesystem roots. It is
* guaranteed that the canonical pathname of any file physically present on
* the local machine will begin with one of the roots returned by this
* method.
*
* The canonical pathname of a file that resides on some other machine
* and is accessed via a remote-filesystem protocol such as SMB or NFS may
* or may not begin with one of the roots returned by this method. If the
* pathname of a remote file is syntactically indistinguishable from the
* pathname of a local file then it will begin with one of the roots
* returned by this method. Thus, for example, PhingFile objects
* denoting the root directories of the mapped network drives of a Windows
* platform will be returned by this method, while PhingFile
* objects containing UNC pathnames will not be returned by this method.
*
* @return An array of PhingFile objects denoting the available
* filesystem roots, or null if the set of roots
* could not be determined. The array will be empty if there are
* no filesystem roots.
*/
function listRoots() {
$fs = FileSystem::getFileSystem();
return (array) $fs->listRoots();
}
/* -- Tempfile management -- */
/**
* Returns the path to the temp directory.
*/
function getTempDir() {
return Phing::getProperty('php.tmpdir');
}
/**
* Static method that creates a unique filename whose name begins with
* $prefix and ends with $suffix in the directory $directory. $directory
* is a reference to a PhingFile Object.
* Then, the file is locked for exclusive reading/writing.
*
* @author manuel holtgrewe, grin@gmx.net
* @throws IOException
* @access public
*/
function createTempFile($prefix, $suffix, PhingFile $directory) {
// quick but efficient hack to create a unique filename ;-)
$result = null;
do {
$result = new PhingFile($directory, $prefix . substr(md5(time()), 0, 8) . $suffix);
} while (file_exists($result->getPath()));
$fs = FileSystem::getFileSystem();
$fs->createNewFile($result->getPath());
$fs->lock($result);
return $result;
}
/**
* If necessary, $File the lock on $File is removed and then the file is
* deleted
*
* @access public
*/
function removeTempFile() {
$fs = FileSystem::getFileSystem();
// catch IO Exception
$fs->unlock($this);
$this->delete();
}
/* -- Basic infrastructure -- */
/**
* Compares two abstract pathnames lexicographically. The ordering
* defined by this method depends upon the underlying system. On UNIX
* systems, alphabetic case is significant in comparing pathnames; on Win32
* systems it is not.
*
* @param PhingFile $file Th file whose pathname sould be compared to the pathname of this file.
*
* @return int Zero if the argument is equal to this abstract pathname, a
* value less than zero if this abstract pathname is
* lexicographically less than the argument, or a value greater
* than zero if this abstract pathname is lexicographically
* greater than the argument
*/
function compareTo(PhingFile $file) {
$fs = FileSystem::getFileSystem();
return $fs->compare($this, $file);
}
/**
* Tests this abstract pathname for equality with the given object.
* Returns <code>true</code> if and only if the argument is not
* <code>null</code> and is an abstract pathname that denotes the same file
* or directory as this abstract pathname. Whether or not two abstract
* pathnames are equal depends upon the underlying system. On UNIX
* systems, alphabetic case is significant in comparing pathnames; on Win32
* systems it is not.
* @return boolean
*/
function equals($obj) {
if (($obj !== null) && ($obj instanceof PhingFile)) {
return ($this->compareTo($obj) === 0);
}
return false;
}
/** Backwards compatibility -- use PHP5's native __tostring method. */
function toString() {
return $this->getPath();
}
/** PHP5's native method. */
function __toString() {
return $this->getPath();
}
}

View file

@ -0,0 +1,91 @@
<?php
/*
* $Id: Reader.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>.
*/
/**
* Abstract class for reading character streams.
*
* @author Hans Lellelid <hans@xmpl.org>
* @author Yannick Lecaillez <yl@seasonfive.com>
* @version $Revision: 905 $
* @package phing.system.io
*/
abstract class Reader {
/**
* Read data from source.
*
* If length is specified, then only that number of chars is read,
* otherwise stream is read until EOF.
*
* @param int $len
*/
abstract public function read($len = null);
/**
* Close stream.
* @throws IOException if there is an error closing stream
*/
abstract public function close();
/**
* Returns the filename, url, etc. that is being read from.
* This is critical for, e.g., ExpatParser's ability to know
* the filename that is throwing an ExpatParserException, etc.
* @return string
*/
abstract function getResource();
/**
* Move stream position relative to current pos.
* @param int $n
*/
public function skip($n) {}
/**
* Reset the current position in stream to beginning or last mark (if supported).
*/
public function reset() {}
/**
* If supported, places a "marker" (like a bookmark) at current stream position.
* A subsequent call to reset() will move stream position back
* to last marker (if supported).
*/
public function mark() {}
/**
* Whether marking is supported.
* @return boolean
*/
public function markSupported() {
return false;
}
/**
* Is stream ready for reading.
* @return boolean
*/
public function ready() {
return true;
}
}

View file

@ -0,0 +1,84 @@
<?php
/*
* $Id: StringReader.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>.
*/
/**
* Dummy class for reading from string of characters.
* @package phing.system.io
*/
class StringReader extends Reader {
/**
* @var string
*/
private $_string;
/**
* @var int
*/
private $mark = 0;
/**
* @var int
*/
private $currPos = 0;
function __construct($string) {
$this->_string = $string;
}
function skip($n) {}
function read($len = null) {
if ($len === null) {
return $this->_string;
} else {
if ($this->currPos >= strlen($this->_string)) {
return -1;
}
$out = substr($this->_string, $this->currPos, $len);
$this->currPos += $len;
return $out;
}
}
function mark() {
$this->mark = $this->currPos;
}
function reset() {
$this->currPos = $this->mark;
}
function close() {}
function open() {}
function ready() {}
function markSupported() {
return true;
}
function getResource() {
return '(string) "'.$this->_string . '"';
}
}

View file

@ -0,0 +1,306 @@
<?php
/*
* $Id: UnixFileSystem.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/FileSystem.php';
/**
* UnixFileSystem class. This class encapsulates the basic file system functions
* for platforms using the unix (posix)-stylish filesystem. It wraps php native
* functions suppressing normal PHP error reporting and instead uses Exception
* to report and error.
*
* This class is part of a oop based filesystem abstraction and targeted to run
* on all supported php platforms.
*
* Note: For debugging turn track_errors on in the php.ini. The error messages
* and log messages from this class will then be clearer because $php_errormsg
* is passed as part of the message.
*
* FIXME:
* - Comments
* - Error handling reduced to min, error are handled by PhingFile mainly
*
* @author Andreas Aderhold, andi@binarycloud.com
* @version $Revision: 905 $
* @package phing.system.io
*/
class UnixFileSystem extends FileSystem {
/**
* returns OS dependant path separator char
*/
function getSeparator() {
return '/';
}
/**
* returns OS dependant directory separator char
*/
function getPathSeparator() {
return ':';
}
/**
* A normal Unix pathname contains no duplicate slashes and does not end
* with a slash. It may be the empty string.
*
* Check that the given pathname is normal. If not, invoke the real
* normalizer on the part of the pathname that requires normalization.
* This way we iterate through the whole pathname string only once.
*/
function normalize($strPathname) {
if (!strlen($strPathname)) {
return;
}
// Resolve home directories. We assume /home is where all home
// directories reside, b/c there is no other way to do this with
// PHP AFAIK.
if ($strPathname{0} === "~") {
if ($strPathname{1} === "/") { // like ~/foo => /home/user/foo
$strPathname = "/home/" . get_current_user() . substr($strPathname, 1);
} else { // like ~foo => /home/foo
$pos = strpos($strPathname, "/");
$name = substr($strPathname, 1, $pos - 2);
$strPathname = "/home/" . $name . substr($strPathname, $pos);
}
}
$n = strlen($strPathname);
$prevChar = 0;
for ($i=0; $i < $n; $i++) {
$c = $strPathname{$i};
if (($prevChar === '/') && ($c === '/')) {
return self::normalizer($strPathname, $n, $i - 1);
}
$prevChar = $c;
}
if ($prevChar === '/') {
return self::normalizer($strPathname, $n, $n - 1);
}
return $strPathname;
}
/**
* Normalize the given pathname, whose length is $len, starting at the given
* $offset; everything before this offset is already normal.
*/
protected function normalizer($pathname, $len, $offset) {
if ($len === 0) {
return $pathname;
}
$n = (int) $len;
while (($n > 0) && ($pathname{$n-1} === '/')) {
$n--;
}
if ($n === 0) {
return '/';
}
$sb = "";
if ($offset > 0) {
$sb .= substr($pathname, 0, $offset);
}
$prevChar = 0;
for ($i = $offset; $i < $n; $i++) {
$c = $pathname{$i};
if (($prevChar === '/') && ($c === '/')) {
continue;
}
$sb .= $c;
$prevChar = $c;
}
return $sb;
}
/**
* Compute the length of the pathname string's prefix. The pathname
* string must be in normal form.
*/
function prefixLength($pathname) {
if (strlen($pathname === 0)) {
return 0;
}
return (($pathname{0} === '/') ? 1 : 0);
}
/**
* Resolve the child pathname string against the parent.
* Both strings must be in normal form, and the result
* will be in normal form.
*/
function resolve($parent, $child) {
if ($child === "") {
return $parent;
}
if ($child{0} === '/') {
if ($parent === '/') {
return $child;
}
return $parent.$child;
}
if ($parent === '/') {
return $parent.$child;
}
return $parent.'/'.$child;
}
function getDefaultParent() {
return '/';
}
function isAbsolute(PhingFile $f) {
return ($f->getPrefixLength() !== 0);
}
/**
* the file resolver
*/
function resolveFile(PhingFile $f) {
// resolve if parent is a file oject only
if ($this->isAbsolute($f)) {
return $f->getPath();
} else {
return $this->resolve(Phing::getProperty("user.dir"), $f->getPath());
}
}
/* -- most of the following is mapped to the php natives wrapped by FileSystem */
/* -- Attribute accessors -- */
function getBooleanAttributes(&$f) {
//$rv = getBooleanAttributes0($f);
$name = $f->getName();
$hidden = (strlen($name) > 0) && ($name{0} == '.');
return ($hidden ? $this->BA_HIDDEN : 0);
}
/**
* set file readonly on unix
*/
function setReadOnly($f) {
if ($f instanceof File) {
$strPath = (string) $f->getPath();
$perms = (int) (@fileperms($strPath) & 0444);
return FileSystem::Chmod($strPath, $perms);
} else {
throw new Exception("IllegalArgutmentType: Argument is not File");
}
}
/**
* compares file paths lexicographically
*/
function compare($f1, $f2) {
if ( ($f1 instanceof PhingFile) && ($f2 instanceof PhingFile) ) {
$f1Path = $f1->getPath();
$f2Path = $f2->getPath();
return (boolean) strcmp((string) $f1Path, (string) $f2Path);
} else {
throw new Exception("IllegalArgutmentType: Argument is not PhingFile");
}
}
/**
* Copy a file, takes care of symbolic links
*
* @param PhingFile $src Source path and name file to copy.
* @param PhingFile $dest Destination path and name of new file.
*
* @return void
* @throws Exception if file cannot be copied.
*/
function copy(PhingFile $src, PhingFile $dest) {
global $php_errormsg;
if (!$src->isLink())
{
return parent::copy($src, $dest);
}
$srcPath = $src->getAbsolutePath();
$destPath = $dest->getAbsolutePath();
$linkTarget = $src->getLinkTarget();
if (false === @symlink($linkTarget, $destPath))
{
$msg = "FileSystem::copy() FAILED. Cannot create symlink from $destPath to $linkTarget.";
throw new Exception($msg);
}
}
/* -- fs interface --*/
function listRoots() {
if (!$this->checkAccess('/', false)) {
die ("Can not access root");
}
return array(new PhingFile("/"));
}
/**
* returns the contents of a directory in an array
*/
function lister($f) {
$dir = @opendir($f->getAbsolutePath());
if (!$dir) {
throw new Exception("Can't open directory " . $f->__toString());
}
$vv = array();
while (($file = @readdir($dir)) !== false) {
if ($file == "." || $file == "..") {
continue;
}
$vv[] = (string) $file;
}
@closedir($dir);
return $vv;
}
function fromURIPath($p) {
if (StringHelper::endsWith("/", $p) && (strlen($p) > 1)) {
// "/foo/" --> "/foo", but "/" --> "/"
$p = substr($p, 0, strlen($p) - 1);
}
return $p;
}
/**
* Whether file can be deleted.
* @param PhingFile $f
* @return boolean
*/
function canDelete(PhingFile $f)
{
@clearstatcache();
$dir = dirname($f->getAbsolutePath());
return (bool) @is_writable($dir);
}
}

View file

@ -0,0 +1,477 @@
<?php
/*
* $Id: Win32FileSystem.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/FileSystem.php';
/**
* @package phing.system.io
*/
class Win32FileSystem extends FileSystem {
protected $slash;
protected $altSlash;
protected $semicolon;
private static $driveDirCache = array();
function __construct() {
$this->slash = self::getSeparator();
$this->semicolon = self::getPathSeparator();
$this->altSlash = ($this->slash === '\\') ? '/' : '\\';
}
function isSlash($c) {
return ($c == '\\') || ($c == '/');
}
function isLetter($c) {
return ((ord($c) >= ord('a')) && (ord($c) <= ord('z')))
|| ((ord($c) >= ord('A')) && (ord($c) <= ord('Z')));
}
function slashify($p) {
if ((strlen($p) > 0) && ($p{0} != $this->slash)) {
return $this->slash.$p;
}
else {
return $p;
}
}
/* -- Normalization and construction -- */
function getSeparator() {
// the ascii value of is the \
return chr(92);
}
function getPathSeparator() {
return ';';
}
/**
* A normal Win32 pathname contains no duplicate slashes, except possibly
* for a UNC prefix, and does not end with a slash. It may be the empty
* string. Normalized Win32 pathnames have the convenient property that
* the length of the prefix almost uniquely identifies the type of the path
* and whether it is absolute or relative:
*
* 0 relative to both drive and directory
* 1 drive-relative (begins with '\\')
* 2 absolute UNC (if first char is '\\'), else directory-relative (has form "z:foo")
* 3 absolute local pathname (begins with "z:\\")
*/
function normalizePrefix($strPath, $len, &$sb) {
$src = 0;
while (($src < $len) && $this->isSlash($strPath{$src})) {
$src++;
}
$c = "";
if (($len - $src >= 2)
&& $this->isLetter($c = $strPath{$src})
&& $strPath{$src + 1} === ':') {
/* Remove leading slashes if followed by drive specifier.
* This hack is necessary to support file URLs containing drive
* specifiers (e.g., "file://c:/path"). As a side effect,
* "/c:/path" can be used as an alternative to "c:/path". */
$sb .= $c;
$sb .= ':';
$src += 2;
}
else {
$src = 0;
if (($len >= 2)
&& $this->isSlash($strPath{0})
&& $this->isSlash($strPath{1})) {
/* UNC pathname: Retain first slash; leave src pointed at
* second slash so that further slashes will be collapsed
* into the second slash. The result will be a pathname
* beginning with "\\\\" followed (most likely) by a host
* name. */
$src = 1;
$sb.=$this->slash;
}
}
return $src;
}
/** Normalize the given pathname, whose length is len, starting at the given
offset; everything before this offset is already normal. */
protected function normalizer($strPath, $len, $offset) {
if ($len == 0) {
return $strPath;
}
if ($offset < 3) {
$offset = 0; //Avoid fencepost cases with UNC pathnames
}
$src = 0;
$slash = $this->slash;
$sb = "";
if ($offset == 0) {
// Complete normalization, including prefix
$src = $this->normalizePrefix($strPath, $len, $sb);
} else {
// Partial normalization
$src = $offset;
$sb .= substr($strPath, 0, $offset);
}
// Remove redundant slashes from the remainder of the path, forcing all
// slashes into the preferred slash
while ($src < $len) {
$c = $strPath{$src++};
if ($this->isSlash($c)) {
while (($src < $len) && $this->isSlash($strPath{$src})) {
$src++;
}
if ($src === $len) {
/* Check for trailing separator */
$sn = (int) strlen($sb);
if (($sn == 2) && ($sb{1} === ':')) {
// "z:\\"
$sb .= $slash;
break;
}
if ($sn === 0) {
// "\\"
$sb .= $slash;
break;
}
if (($sn === 1) && ($this->isSlash($sb{0}))) {
/* "\\\\" is not collapsed to "\\" because "\\\\" marks
the beginning of a UNC pathname. Even though it is
not, by itself, a valid UNC pathname, we leave it as
is in order to be consistent with the win32 APIs,
which treat this case as an invalid UNC pathname
rather than as an alias for the root directory of
the current drive. */
$sb .= $slash;
break;
}
// Path does not denote a root directory, so do not append
// trailing slash
break;
} else {
$sb .= $slash;
}
} else {
$sb.=$c;
}
}
$rv = (string) $sb;
return $rv;
}
/**
* Check that the given pathname is normal. If not, invoke the real
* normalizer on the part of the pathname that requires normalization.
* This way we iterate through the whole pathname string only once.
* @param string $strPath
* @return string
*/
function normalize($strPath) {
$n = strlen($strPath);
$slash = $this->slash;
$altSlash = $this->altSlash;
$prev = 0;
for ($i = 0; $i < $n; $i++) {
$c = $strPath{$i};
if ($c === $altSlash) {
return $this->normalizer($strPath, $n, ($prev === $slash) ? $i - 1 : $i);
}
if (($c === $slash) && ($prev === $slash) && ($i > 1)) {
return $this->normalizer($strPath, $n, $i - 1);
}
if (($c === ':') && ($i > 1)) {
return $this->normalizer($strPath, $n, 0);
}
$prev = $c;
}
if ($prev === $slash) {
return $this->normalizer($strPath, $n, $n - 1);
}
return $strPath;
}
function prefixLength($strPath) {
$path = (string) $strPath;
$slash = (string) $this->slash;
$n = (int) strlen($path);
if ($n === 0) {
return 0;
}
$c0 = $path{0};
$c1 = ($n > 1) ? $path{1} :
0;
if ($c0 === $slash) {
if ($c1 === $slash) {
return 2; // absolute UNC pathname "\\\\foo"
}
return 1; // drive-relative "\\foo"
}
if ($this->isLetter($c0) && ($c1 === ':')) {
if (($n > 2) && ($path{2}) === $slash) {
return 3; // Absolute local pathname "z:\\foo" */
}
return 2; // Directory-relative "z:foo"
}
return 0; // Completely relative
}
function resolve($parent, $child) {
$parent = (string) $parent;
$child = (string) $child;
$slash = (string) $this->slash;
$pn = (int) strlen($parent);
if ($pn === 0) {
return $child;
}
$cn = (int) strlen($child);
if ($cn === 0) {
return $parent;
}
$c = $child;
if (($cn > 1) && ($c{0} === $slash)) {
if ($c{1} === $slash) {
// drop prefix when child is a UNC pathname
$c = substr($c, 2);
}
else {
//Drop prefix when child is drive-relative */
$c = substr($c, 1);
}
}
$p = $parent;
if ($p{$pn - 1} === $slash) {
$p = substr($p, 0, $pn - 1);
}
return $p.$this->slashify($c);
}
function getDefaultParent() {
return (string) ("".$this->slash);
}
function fromURIPath($strPath) {
$p = (string) $strPath;
if ((strlen($p) > 2) && ($p{2} === ':')) {
// "/c:/foo" --> "c:/foo"
$p = substr($p,1);
// "c:/foo/" --> "c:/foo", but "c:/" --> "c:/"
if ((strlen($p) > 3) && StringHelper::endsWith('/', $p)) {
$p = substr($p, 0, strlen($p) - 1);
}
} elseif ((strlen($p) > 1) && StringHelper::endsWith('/', $p)) {
// "/foo/" --> "/foo"
$p = substr($p, 0, strlen($p) - 1);
}
return (string) $p;
}
/* -- Path operations -- */
function isAbsolute(PhingFile $f) {
$pl = (int) $f->getPrefixLength();
$p = (string) $f->getPath();
return ((($pl === 2) && ($p{0} === $this->slash)) || ($pl === 3) || ($pl === 1 && $p{0} === $this->slash));
}
/** private */
function _driveIndex($d) {
$d = (string) $d{0};
if ((ord($d) >= ord('a')) && (ord($d) <= ord('z'))) {
return ord($d) - ord('a');
}
if ((ord($d) >= ord('A')) && (ord($d) <= ord('Z'))) {
return ord($d) - ord('A');
}
return -1;
}
/** private */
function _getDriveDirectory($drive) {
$drive = (string) $drive{0};
$i = (int) $this->_driveIndex($drive);
if ($i < 0) {
return null;
}
$s = (isset(self::$driveDirCache[$i]) ? self::$driveDirCache[$i] : null);
if ($s !== null) {
return $s;
}
$s = $this->_getDriveDirectory($i + 1);
self::$driveDirCache[$i] = $s;
return $s;
}
function _getUserPath() {
//For both compatibility and security, we must look this up every time
return (string) $this->normalize(Phing::getProperty("user.dir"));
}
function _getDrive($path) {
$path = (string) $path;
$pl = $this->prefixLength($path);
return ($pl === 3) ? substr($path, 0, 2) : null;
}
function resolveFile(PhingFile $f) {
$path = $f->getPath();
$pl = (int) $f->getPrefixLength();
if (($pl === 2) && ($path{0} === $this->slash)) {
return $path; // UNC
}
if ($pl === 3) {
return $path; // Absolute local
}
if ($pl === 0) {
return (string) ($this->_getUserPath().$this->slashify($path)); //Completely relative
}
if ($pl === 1) { // Drive-relative
$up = (string) $this->_getUserPath();
$ud = (string) $this->_getDrive($up);
if ($ud !== null) {
return (string) $ud.$path;
}
return (string) $up.$path; //User dir is a UNC path
}
if ($pl === 2) { // Directory-relative
$up = (string) $this->_getUserPath();
$ud = (string) $this->_getDrive($up);
if (($ud !== null) && StringHelper::startsWith($ud, $path)) {
return (string) ($up . $this->slashify(substr($path,2)));
}
$drive = (string) $path{0};
$dir = (string) $this->_getDriveDirectory($drive);
$np = (string) "";
if ($dir !== null) {
/* When resolving a directory-relative path that refers to a
drive other than the current drive, insist that the caller
have read permission on the result */
$p = (string) $drive . (':'.$dir.$this->slashify(substr($path,2)));
if (!$this->checkAccess($p, false)) {
// FIXME
// throw security error
die("Can't resolve path $p");
}
return $p;
}
return (string) $drive.':'.$this->slashify(substr($path,2)); //fake it
}
throw new Exception("Unresolvable path: " . $path);
}
/* -- most of the following is mapped to the functions mapped th php natives in FileSystem */
/* -- Attribute accessors -- */
function setReadOnly($f) {
// dunno how to do this on win
throw new Exception("WIN32FileSystem doesn't support read-only yet.");
}
/* -- Filesystem interface -- */
protected function _access($path) {
if (!$this->checkAccess($path, false)) {
throw new Exception("Can't resolve path $p");
}
return true;
}
function _nativeListRoots() {
// FIXME
}
function listRoots() {
$ds = _nativeListRoots();
$n = 0;
for ($i = 0; $i < 26; $i++) {
if ((($ds >> $i) & 1) !== 0) {
if (!$this->access((string)( chr(ord('A') + $i) . ':' . $this->slash))) {
$ds &= ~(1 << $i);
} else {
$n++;
}
}
}
$fs = array();
$j = (int) 0;
$slash = (string) $this->slash;
for ($i = 0; $i < 26; $i++) {
if ((($ds >> $i) & 1) !== 0) {
$fs[$j++] = new PhingFile(chr(ord('A') + $i) . ':' . $this->slash);
}
}
return $fs;
}
/* -- Basic infrastructure -- */
/** compares file paths lexicographically */
function compare(PhingFile $f1, PhingFile $f2) {
$f1Path = $f1->getPath();
$f2Path = $f2->getPath();
return (boolean) strcasecmp((string) $f1Path, (string) $f2Path);
}
/**
* returns the contents of a directory in an array
*/
function lister($f) {
$dir = @opendir($f->getAbsolutePath());
if (!$dir) {
throw new Exception("Can't open directory " . $f->__toString());
}
$vv = array();
while (($file = @readdir($dir)) !== false) {
if ($file == "." || $file == "..") {
continue;
}
$vv[] = (string) $file;
}
@closedir($dir);
return $vv;
}
}

View file

@ -0,0 +1,35 @@
<?php
/*
* $Id: WinNTFileSystem.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/Win32FileSystem.php';
/**
* FileSystem for Windows NT/2000.
* @package phing.system.io
*/
class WinNTFileSystem extends Win32FileSystem {
/* -- class only for convenience and future use everything is inherinted --*/
}

View file

@ -0,0 +1,53 @@
<?php
/*
* $Id: Writer.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>.
*/
/**
* Abstract class for writing character streams.
*
* @package phing.system.io
*/
abstract class Writer {
/**
* Writes data to output stream.
* @param string $buf
* @param int $off
* @param int $len
*/
abstract public function write($buf, $off = null, $len = null);
/**
* Close the stream.
* @throws IOException - if there is an error closing stream.
*/
abstract public function close();
/**
* Flush the stream, if supported by the stream.
*/
public function flush() {}
/**
* Returns a string representation of resource filename, url, etc. that is being written to.
* @return string
*/
abstract public function getResource();
}

View file

@ -0,0 +1,49 @@
<?php
/*
* $Id: Character.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>.
*/
/**
* @package phing.system.lang
*/
class Character {
// this class might be extended with plenty of ordinal char constants
// and the like to support the multibyte aware datatype (char) in php
// in form of an object.
// anyway just a thought
public static function isLetter($char) {
if (strlen($char) !== 1)
$char = 0;
$char = (int) ord($char);
if ($char >= ord('A') && $char <= ord('Z'))
return true;
if ($char >= ord('a') && $char <= ord('z'))
return true;
return false;
}
}

View file

@ -0,0 +1,52 @@
<?php
/*
* $Id: EventObject.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>.
*/
/**
* @package phing.system.lang
*/
class EventObject {
/** The object on which the Event initially occurred. */
protected $source;
/** Constructs a prototypical Event. */
function __construct($source) {
if ($source === null) {
throw new Exception("Null source");
}
$this->source = $source;
}
/** The object on which the Event initially occurred. */
function getSource() {
return $this->source;
}
/** Returns a String representation of this EventObject.*/
function toString() {
if (method_exists($this->source, "toString")) {
return get_class($this)."[source=".$this->source->toString()."]";
} else {
return get_class($this)."[source=".get_class($this->source)."]";
}
}
}

View file

@ -0,0 +1,26 @@
<?php
/*
* $Id: FileNotFoundException.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>.
*/
/**
* @package phing.system.lang
*/
class FileNotFoundException extends Exception {}

View file

@ -0,0 +1,26 @@
<?php
/*
* $Id: NullPointerException.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>.
*/
/**
* @package phing.system.lang
*/
class NullPointerException extends Exception {}

View file

@ -0,0 +1,26 @@
<?php
/*
* $Id: SecurityException.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>.
*/
/**
* @package phing.system.lang
*/
class SecurityException extends Exception {}

View file

@ -0,0 +1,289 @@
<?php
/*
* $Id: Properties.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/system/io/FileWriter.php';
/**
* Convenience class for reading and writing property files.
*
* FIXME
* - Add support for arrays (separated by ',')
*
* @package phing.system.util
* @version $Revision: 905 $
*/
class Properties {
private $properties = array();
/**
* Load properties from a file.
*
* @param PhingFile $file
* @return void
* @throws IOException - if unable to read file.
*/
function load(PhingFile $file) {
if ($file->canRead()) {
$this->parse($file->getPath(), false);
} else {
throw new IOException("Can not read file ".$file->getPath());
}
}
/**
* Replaces parse_ini_file() or better_parse_ini_file().
* Saves a step since we don't have to parse and then check return value
* before throwing an error or setting class properties.
*
* @param string $filePath
* @param boolean $processSections Whether to honor [SectionName] sections in INI file.
* @return array Properties loaded from file (no prop replacements done yet).
*/
protected function parse($filePath) {
// load() already made sure that file is readable
// but we'll double check that when reading the file into
// an array
if (($lines = @file($filePath)) === false) {
throw new IOException("Unable to parse contents of $filePath");
}
$this->properties = array();
$sec_name = "";
foreach($lines as $line) {
$line = trim($line);
if($line == "")
continue;
if ($line{0} == '#' or $line{0} == ';') {
// it's a comment, so continue to next line
continue;
} else {
$pos = strpos($line, '=');
$property = trim(substr($line, 0, $pos));
$value = trim(substr($line, $pos + 1));
$this->properties[$property] = $this->inVal($value);
}
} // for each line
}
/**
* Process values when being read in from properties file.
* does things like convert "true" => true
* @param string $val Trimmed value.
* @return mixed The new property value (may be boolean, etc.)
*/
protected function inVal($val) {
if ($val === "true") {
$val = true;
} elseif ($val === "false") {
$val = false;
}
return $val;
}
/**
* Process values when being written out to properties file.
* does things like convert true => "true"
* @param mixed $val The property value (may be boolean, etc.)
* @return string
*/
protected function outVal($val) {
if ($val === true) {
$val = "true";
} elseif ($val === false) {
$val = "false";
}
return $val;
}
/**
* Create string representation that can be written to file and would be loadable using load() method.
*
* Essentially this function creates a string representation of properties that is ready to
* write back out to a properties file. This is used by store() method.
*
* @return string
*/
public function toString() {
$buf = "";
foreach($this->properties as $key => $item) {
$buf .= $key . "=" . $this->outVal($item) . PHP_EOL;
}
return $buf;
}
/**
* Stores current properties to specified file.
*
* @param PhingFile $file File to create/overwrite with properties.
* @param string $header Header text that will be placed (within comments) at the top of properties file.
* @return void
* @throws IOException - on error writing properties file.
*/
function store(PhingFile $file, $header = null) {
// stores the properties in this object in the file denoted
// if file is not given and the properties were loaded from a
// file prior, this method stores them in the file used by load()
try {
$fw = new FileWriter($file);
if ($header !== null) {
$fw->write( "# " . $header . PHP_EOL );
}
$fw->write($this->toString());
$fw->close();
} catch (IOException $e) {
throw new IOException("Error writing property file: " . $e->getMessage());
}
}
/**
* Returns copy of internal properties hash.
* Mostly for performance reasons, property hashes are often
* preferable to passing around objects.
*
* @return array
*/
function getProperties() {
return $this->properties;
}
/**
* Get value for specified property.
* This is the same as get() method.
*
* @param string $prop The property name (key).
* @return mixed
* @see get()
*/
function getProperty($prop) {
if (!isset($this->properties[$prop])) {
return null;
}
return $this->properties[$prop];
}
/**
* Get value for specified property.
* This function exists to provide a hashtable-like interface for
* properties.
*
* @param string $prop The property name (key).
* @return mixed
* @see getProperty()
*/
function get($prop) {
if (!isset($this->properties[$prop])) {
return null;
}
return $this->properties[$prop];
}
/**
* Set the value for a property.
*
* @param string $key
* @param mixed $value
* @return mixed Old property value or NULL if none was set.
*/
function setProperty($key, $value) {
$oldValue = null;
if (isset($this->properties[$key])) {
$oldValue = $this->properties[$key];
}
$this->properties[$key] = $value;
return $oldValue;
}
/**
* Set the value for a property.
* This function exists to provide hashtable-lie
* interface for properties.
*
* @param string $key
* @param mixed $value
*/
function put($key, $value) {
return $this->setProperty($key, $value);
}
/**
* Appends a value to a property if it already exists with a delimiter
*
* If the property does not, it just adds it.
*
* @param string $key
* @param mixed $value
* @param string $delimiter
*/
function append($key, $value, $delimiter = ',') {
$newValue = $value;
if (isset($this->properties[$key]) && !empty($this->properties[$key]) ) {
$newValue = $this->properties[$key] . $delimiter . $value;
}
$this->properties[$key] = $newValue;
}
/**
* Same as keys() function, returns an array of property names.
* @return array
*/
function propertyNames() {
return $this->keys();
}
/**
* Whether loaded properties array contains specified property name.
* @return boolean
*/
function containsKey($key) {
return isset($this->properties[$key]);
}
/**
* Returns properties keys.
* Use this for foreach() {} iterations, as this is
* faster than looping through property values.
* @return array
*/
function keys() {
return array_keys($this->properties);
}
/**
* Whether properties list is empty.
* @return boolean
*/
function isEmpty() {
return empty($this->properties);
}
}

View file

@ -0,0 +1,115 @@
<?php
/**
* Static class to handle a slot-listening system.
*
* Unlike the slots/signals Qt model, this class manages something that is
* more like a simple hashtable, where each slot has only one value. For that
* reason "Registers" makes more sense, the reference being to CPU registers.
*
* This could be used for anything, but it's been built for a pretty specific phing
* need, and that is to allow access to dynamic values that are set by logic
* that is not represented in a build file. For exampe, we need a system for getting
* the current resource (file) that is being processed by a filterchain in a fileset.
*
* Each slot corresponds to only one read-only, dynamic-value RegisterSlot object. In
* a build.xml register slots are expressed using a syntax similar to variables:
*
* <replaceregexp>
* <regexp pattern="\n" replace="%{task.current_file}"/>
* </replaceregexp>
*
* The task/type must provide a supporting setter for the attribute:
*
* <code>
* function setListeningReplace(RegisterSlot $slot) {
* $this->replace = $slot;
* }
*
* // in main()
* if ($this->replace instanceof RegisterSlot) {
* $this->regexp->setReplace($this->replace->getValue());
* } else {
* $this->regexp->setReplace($this->replace);
* }
* </code>
*
* @author Hans Lellelid <hans@xmpl.org>
* @version $Revision: 905 $
* @package phing.system.util
*/
class Register {
/** Slots that have been registered */
private static $slots = array();
/**
* Returns RegisterSlot for specified key.
*
* If not slot exists a new one is created for key.
*
* @param string $key
* @return RegisterSlot
*/
public static function getSlot($key) {
if (!isset(self::$slots[$key])) {
self::$slots[$key] = new RegisterSlot($key);
}
return self::$slots[$key];
}
}
/**
* Represents a slot in the register.
*/
class RegisterSlot {
/** The name of this slot. */
private $key;
/** The value for this slot. */
private $value;
/**
* Constructs a new RegisterSlot, setting the key to passed param.
* @param string $key
*/
public function __construct($key) {
$this->key = (string) $key;
}
/**
* Sets the key / name for this slot.
* @param string $k
*/
public function setKey($k) {
$this->key = (string) $k;
}
/**
* Gets the key / name for this slot.
* @return string
*/
public function getKey() {
return $this->key;
}
/**
* Sets the value for this slot.
* @param mixed
*/
public function setValue($v) {
$this->value = $v;
}
/**
* Returns the value at this slot.
* @return mixed
*/
public function getValue() {
return $this->value;
}
}

View file

@ -0,0 +1,96 @@
<?php
/*
* $Id: Timer.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>.
*/
/**
* This class can be used to obtain the execution time of all of the scripts
* that are executed in the process of building a page.
*
* Example:
* To be done before any scripts execute:
*
* $Timer = new Timer;
* $Timer->Start_Timer();
*
* To be done after all scripts have executed:
*
* $timer->Stop_Timer();
* $timer->Get_Elapsed_Time(int number_of_places);
*
* @author Charles Killian
* @author Hans Lellelid <hans@xmpl.org>
* @package phing.system.util
* @version $Revision: 905 $ $Date: 2010-10-05 18:28:03 +0200 (Tue, 05 Oct 2010) $
*/
class Timer {
/** start time */
protected $stime;
/** end time */
protected $etime;
/**
* This function sets the class variable $stime to the current time in
* microseconds.
* @return void
*/
public function start() {
$this->stime = $this->getMicrotime();
}
/**
* This function sets the class variable $etime to the current time in
* microseconds.
* @return void
*/
function stop() {
$this->etime = $this->getMicrotime();
}
/**
* This function returns the elapsed time in seconds.
*
* Call start_time() at the beginning of script execution and end_time() at
* the end of script execution. Then, call elapsed_time() to obtain the
* difference between start_time() and end_time().
*
* @param $places decimal place precision of elapsed time (default is 5)
* @return string Properly formatted time.
*/
function getElapsedTime($places=5) {
$etime = $this->etime - $this->stime;
$format = "%0.".$places."f";
return (sprintf ($format, $etime));
}
/**
* This function returns the current time in microseconds.
*
* @author Everett Michaud, Zend.com
* @return current time in microseconds
* @access private
*/
function getMicrotime() {
list($usec, $sec) = explode(" ", microtime());
return ((float)$usec + (float)$sec);
}
}

View file

@ -0,0 +1,480 @@
<?php
/*
* $Id: CapsuleTask.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/Task.php';
include_once 'phing/BuildException.php';
include_once 'phing/lib/Capsule.php';
include_once 'phing/util/StringHelper.php';
/**
* A phing task for generating output by using Capsule.
*
* This is based on the interface to TexenTask from Apache's Velocity engine.
*
* @author Hans Lellelid <hans@xmpl.org>
* @version $Id: CapsuleTask.php 905 2010-10-05 16:28:03Z mrook $
* @package phing.tasks.ext
*/
class CapsuleTask extends Task {
/**
* Capsule "template" engine.
* @var Capsule
*/
protected $context;
/**
* Any vars assigned via the build file.
* @var array AssignedVar[]
*/
protected $assignedVars = array();
/**
* This is the control template that governs the output.
* It may or may not invoke the services of worker
* templates.
* @var string
*/
protected $controlTemplate;
/**
* This is where Velocity will look for templates
* using the file template loader.
* @var string
*/
protected $templatePath;
/**
* This is where texen will place all the output
* that is a product of the generation process.
* @var string
*/
protected $outputDirectory;
/**
* This is the file where the generated text
* will be placed.
* @var string
*/
protected $outputFile;
/**
* <p>
* These are properties that are fed into the
* initial context from a properties file. This
* is simply a convenient way to set some values
* that you wish to make available in the context.
* </p>
* <p>
* These values are not critical, like the template path
* or output path, but allow a convenient way to
* set a value that may be specific to a particular
* generation task.
* </p>
* <p>
* For example, if you are generating scripts to allow
* user to automatically create a database, then
* you might want the <code>$databaseName</code>
* to be placed
* in the initial context so that it is available
* in a script that might look something like the
* following:
* <code><pre>
* #!bin/sh
*
* echo y | mysqladmin create $databaseName
* </pre></code>
* The value of <code>$databaseName</code> isn't critical to
* output, and you obviously don't want to change
* the ant task to simply take a database name.
* So initial context values can be set with
* properties file.
*
* @var array
*/
protected $contextProperties;
// -----------------------------------------------------------------------
// The following getters & setters are used by phing to set properties
// specified in the XML for the capsule task.
// -----------------------------------------------------------------------
/**
* [REQUIRED] Set the control template for the
* generating process.
* @param string $controlTemplate
* @return void
*/
public function setControlTemplate ($controlTemplate) {
$this->controlTemplate = $controlTemplate;
}
/**
* Get the control template for the
* generating process.
* @return string
*/
public function getControlTemplate() {
return $this->controlTemplate;
}
/**
* [REQUIRED] Set the path where Velocity will look
* for templates using the file template
* loader.
* @return void
* @throws Exception
*/
public function setTemplatePath($templatePath) {
$resolvedPath = "";
$tok = strtok($templatePath, ",");
while ( $tok ) {
// resolve relative path from basedir and leave
// absolute path untouched.
$fullPath = $this->project->resolveFile($tok);
$cpath = $fullPath->getCanonicalPath();
if ($cpath === false) {
$this->log("Template directory does not exist: " . $fullPath->getAbsolutePath());
} else {
$resolvedPath .= $cpath;
}
$tok = strtok(",");
if ( $tok ) {
$resolvedPath .= ",";
}
}
$this->templatePath = $resolvedPath;
}
/**
* Get the path where Velocity will look
* for templates using the file template
* loader.
* @return string
*/
public function getTemplatePath() {
return $this->templatePath;
}
/**
* [REQUIRED] Set the output directory. It will be
* created if it doesn't exist.
* @param PhingFile $outputDirectory
* @return void
* @throws Exception
*/
public function setOutputDirectory(PhingFile $outputDirectory) {
try {
if (!$outputDirectory->exists()) {
$this->log("Output directory does not exist, creating: " . $outputDirectory->getPath(),Project::MSG_VERBOSE);
if (!$outputDirectory->mkdirs()) {
throw new IOException("Unable to create Ouptut directory: " . $outputDirectory->getAbsolutePath());
}
}
$this->outputDirectory = $outputDirectory->getCanonicalPath();
} catch (IOException $ioe) {
throw new BuildException($ioe);
}
}
/**
* Get the output directory.
* @return string
*/
public function getOutputDirectory() {
return $this->outputDirectory;
}
/**
* [REQUIRED] Set the output file for the
* generation process.
* @param string $outputFile (TODO: change this to File)
* @return void
*/
public function setOutputFile($outputFile) {
$this->outputFile = $outputFile;
}
/**
* Get the output file for the
* generation process.
* @return string
*/
public function getOutputFile() {
return $this->outputFile;
}
/**
* Set the context properties that will be
* fed into the initial context be the
* generating process starts.
* @param string $file
* @return void
*/
public function setContextProperties($file) {
$sources = explode(",", $file);
$this->contextProperties = new Properties();
// Always try to get the context properties resource
// from a file first. Templates may be taken from a JAR
// file but the context properties resource may be a
// resource in the filesystem. If this fails than attempt
// to get the context properties resource from the
// classpath.
for ($i=0, $sourcesLength=count($sources); $i < $sourcesLength; $i++) {
$source = new Properties();
try {
// resolve relative path from basedir and leave
// absolute path untouched.
$fullPath = $this->project->resolveFile($sources[$i]);
$this->log("Using contextProperties file: " . $fullPath->toString());
$source->load($fullPath);
} catch (Exception $e) {
throw new BuildException("Context properties file " . $sources[$i] .
" could not be found in the file system!");
}
$keys = $source->keys();
foreach ($keys as $key) {
$name = $key;
$value = $this->project->replaceProperties($source->getProperty($name));
$this->contextProperties->setProperty($name, $value);
}
}
}
/**
* Get the context properties that will be
* fed into the initial context be the
* generating process starts.
* @return Properties
*/
public function getContextProperties() {
return $this->contextProperties;
}
/**
* Creates an "AssignedVar" class.
*/
public function createAssign() {
$a = new AssignedVar();
$this->assignedVars[] = $a;
return $a;
}
// ---------------------------------------------------------------
// End of XML setters & getters
// ---------------------------------------------------------------
/**
* Creates a Smarty object.
*
* @return Smarty initialized (cleared) Smarty context.
* @throws Exception the execute method will catch
* and rethrow as a <code>BuildException</code>
*/
public function initControlContext() {
$this->context->clear();
foreach($this->assignedVars as $var) {
$this->context->put($var->getName(), $var->getValue());
}
return $this->context;
}
/**
* Execute the input script with Velocity
*
* @throws BuildException
* BuildExceptions are thrown when required attributes are missing.
* Exceptions thrown by Velocity are rethrown as BuildExceptions.
*/
public function main() {
// Make sure the template path is set.
if (empty($this->templatePath)) {
throw new BuildException("The template path needs to be defined!");
}
// Make sure the control template is set.
if ($this->controlTemplate === null) {
throw new BuildException("The control template needs to be defined!");
}
// Make sure the output directory is set.
if ($this->outputDirectory === null) {
throw new BuildException("The output directory needs to be defined!");
}
// Make sure there is an output file.
if ($this->outputFile === null) {
throw new BuildException("The output file needs to be defined!");
}
// Setup Smarty runtime.
// Smarty uses one object to store properties and to store
// the context for the template (unlike Velocity). We setup this object, calling it
// $this->context, and then initControlContext simply zeros out
// any assigned variables.
$this->context = new Capsule();
if ($this->templatePath !== null) {
$this->log("Using templatePath: " . $this->templatePath);
$this->context->setTemplatePath($this->templatePath);
}
// Make sure the output directory exists, if it doesn't
// then create it.
$outputDir = new PhingFile($this->outputDirectory);
if (!$outputDir->exists()) {
$this->log("Output directory does not exist, creating: " . $outputDir->getAbsolutePath());
$outputDir->mkdirs();
}
$this->context->setOutputDirectory($outputDir->getAbsolutePath());
$path = $this->outputDirectory . DIRECTORY_SEPARATOR . $this->outputFile;
$this->log("Generating to file " . $path);
//$writer = new FileWriter($path);
// The generator and the output path should
// be placed in the init context here and
// not in the generator class itself.
$c = $this->initControlContext();
// Set any variables that need to always
// be loaded
$this->populateInitialContext($c);
// Feed all the options into the initial
// control context so they are available
// in the control/worker templates.
if ($this->contextProperties !== null) {
foreach($this->contextProperties->keys() as $property) {
$value = $this->contextProperties->getProperty($property);
// Special exception (from Texen)
// for properties ending in file.contents:
// in that case we dump the contents of the file
// as the "value" for the Property.
if (preg_match('/file\.contents$/', $property)) {
// pull in contents of file specified
$property = substr($property, 0, strpos($property, "file.contents") - 1);
// reset value, and then
// read in teh contents of the file into that var
$value = "";
$f = new PhingFile($project->resolveFile($value)->getCanonicalPath());
if ($f->exists()) {
$fr = new FileReader($f);
$fr->readInto($value);
}
} // if ends with file.contents
if (StringHelper::isBoolean($value)) {
$value = StringHelper::booleanValue($value);
}
$c->put($property, $value);
} // foreach property
} // if contextProperties !== null
try {
$this->log("Parsing control template: " . $this->controlTemplate);
$c->parse($this->controlTemplate, $path);
} catch (Exception $ioe) {
throw new BuildException("Cannot write parsed template: ". $ioe->getMessage());
}
$this->cleanup();
}
/**
* Place useful objects into the initial context.
*
*
* @param Capsule $context The context to populate, as retrieved from
* {@link #initControlContext()}.
* @return void
* @throws Exception Error while populating context. The {@link
* #main()} method will catch and rethrow as a
* <code>BuildException</code>.
*/
protected function populateInitialContext(Capsule $context) {
$this->context->put("now", strftime("%c", time()));
$this->context->put("task", $this);
}
/**
* A hook method called at the end of {@link #execute()} which can
* be overridden to perform any necessary cleanup activities (such
* as the release of database connections, etc.). By default,
* does nothing.
* @return void
* @throws Exception Problem cleaning up.
*/
protected function cleanup() {
}
}
/**
* An "inner" class for holding assigned var values.
* May be need to expand beyond name/value in the future.
*
* @package phing.tasks.ext
*/
class AssignedVar {
private $name;
private $value;
function setName($v) {
$this->name = $v;
}
function setValue($v) {
$this->value = $v;
}
function getName() {
return $this->name;
}
function getValue() {
return $this->value;
}
}

View file

@ -0,0 +1,143 @@
<?php
/*
* $Id: ExportPropertiesTask.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>.
*/
require_once "phing/Task.php";
/**
* Saves currently defined properties into a specified file
*
* @author Andrei Serdeliuc
* @extends Task
* @version $Id: ExportPropertiesTask.php 905 2010-10-05 16:28:03Z mrook $
* @package phing.tasks.ext
*/
class ExportPropertiesTask extends Task
{
/**
* Array of project properties
*
* (default value: null)
*
* @var array
* @access private
*/
private $_properties = null;
/**
* Target file for saved properties
*
* (default value: null)
*
* @var string
* @access private
*/
private $_targetFile = null;
/**
* Exclude properties starting with these prefixes
*
* @var array
* @access private
*/
private $_disallowedPropertyPrefixes = array(
'host.',
'phing.',
'os.',
'php.',
'line.',
'env.',
'user.'
);
/**
* setter for _targetFile
*
* @access public
* @param string $file
* @return bool
*/
public function setTargetFile($file)
{
if(!is_dir(dirname($file))) {
throw new BuildException("Parent directory of target file doesn't exist");
}
if(!is_writable(dirname($file)) && (file_exists($file) && !is_writable($file))) {
throw new BuildException("Target file isn't writable");
}
$this->_targetFile = $file;
return true;
}
/**
* setter for _disallowedPropertyPrefixes
*
* @access public
* @param string $file
* @return bool
*/
public function setDisallowedPropertyPrefixes($prefixes)
{
$this->_disallowedPropertyPrefixes = explode(",", $prefixes);
return true;
}
public function main()
{
// Sets the currently declared properties
$this->_properties = $this->getProject()->getProperties();
if(is_array($this->_properties) && !empty($this->_properties) && null !== $this->_targetFile) {
$propertiesString = '';
foreach($this->_properties as $propertyName => $propertyValue) {
if(!$this->isDisallowedPropery($propertyName)) {
$propertiesString .= $propertyName . "=" . $propertyValue . PHP_EOL;
}
}
if(!file_put_contents($this->_targetFile, $propertiesString)) {
throw new BuildException('Failed writing to ' . $this->_targetFile);
}
}
}
/**
* Checks if a property name is disallowed
*
* @access protected
* @param string $propertyName
* @return bool
*/
protected function isDisallowedPropery($propertyName)
{
foreach($this->_disallowedPropertyPrefixes as $property) {
if(substr($propertyName, 0, strlen($property)) == $property) {
return true;
}
}
return false;
}
}
?>

Some files were not shown because too many files have changed in this diff Show more