Spaces:
Sleeping
Sleeping
| /* | |
| * $Id: CapsuleTask.php 3076 2006-12-18 08:52:12Z fabien $ | |
| * | |
| * 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/TaskPhing.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 $Revision: 1.17 $ | |
| * @package phing.tasks.ext | |
| */ | |
| class CapsuleTask extends TaskPhing { | |
| /** | |
| * 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. | |
| */ | |
| 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; | |
| } | |
| } |