home *** CD-ROM | disk | FTP | other *** search
/ Cricao de Sites - 650 Layouts Prontos / WebMasters.iso / Servidores / xampp-win32-1.6.7-installer.exe / php / PEAR / phing / tasks / ext / CapsuleTask.php next >
Encoding:
PHP Script  |  2007-02-05  |  15.5 KB  |  478 lines

  1. <?php
  2.  
  3. /*
  4.  *  $Id: CapsuleTask.php 144 2007-02-05 15:19:00Z hans $
  5.  *
  6.  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  7.  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  8.  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  9.  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  10.  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  11.  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  12.  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  13.  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  14.  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  15.  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  16.  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  17.  *
  18.  * This software consists of voluntary contributions made by many individuals
  19.  * and is licensed under the LGPL. For more information please see
  20.  * <http://phing.info>. 
  21.  */
  22.  
  23. include_once 'phing/Task.php';
  24. include_once 'phing/BuildException.php';
  25. include_once 'phing/lib/Capsule.php';
  26. include_once 'phing/util/StringHelper.php';
  27.  
  28. /**
  29.  * A phing task for generating output by using Capsule.
  30.  *
  31.  * This is based on the interface to TexenTask from Apache's Velocity engine. 
  32.  *
  33.  * @author    Hans Lellelid <hans@xmpl.org>
  34.  * @version   $Revision: 1.17 $
  35.  * @package   phing.tasks.ext
  36.  */
  37. class CapsuleTask extends Task {
  38.  
  39.     /**
  40.      * Capsule "template" engine.
  41.      * @var Capsule
  42.      */
  43.     protected $context;
  44.        
  45.     /**
  46.      * Any vars assigned via the build file.
  47.      * @var array AssignedVar[]
  48.      */
  49.     protected $assignedVars = array();
  50.     
  51.     /**
  52.      * This is the control template that governs the output.
  53.      * It may or may not invoke the services of worker
  54.      * templates.
  55.      * @var string
  56.      */
  57.     protected $controlTemplate;
  58.     
  59.     /**
  60.      * This is where Velocity will look for templates
  61.      * using the file template loader.
  62.      * @var string
  63.      */
  64.     protected $templatePath;
  65.     
  66.     /**
  67.      * This is where texen will place all the output
  68.      * that is a product of the generation process.
  69.      * @var string
  70.      */
  71.     protected $outputDirectory;
  72.     
  73.     /**
  74.      * This is the file where the generated text
  75.      * will be placed.
  76.      * @var string
  77.      */
  78.     protected $outputFile;
  79.  
  80.     /**
  81.      * <p>
  82.      * These are properties that are fed into the
  83.      * initial context from a properties file. This
  84.      * is simply a convenient way to set some values
  85.      * that you wish to make available in the context.
  86.      * </p>
  87.      * <p>
  88.      * These values are not critical, like the template path
  89.      * or output path, but allow a convenient way to
  90.      * set a value that may be specific to a particular
  91.      * generation task.
  92.      * </p>
  93.      * <p>
  94.      * For example, if you are generating scripts to allow
  95.      * user to automatically create a database, then
  96.      * you might want the <code>$databaseName</code> 
  97.      * to be placed
  98.      * in the initial context so that it is available
  99.      * in a script that might look something like the
  100.      * following:
  101.      * <code><pre>
  102.      * #!bin/sh
  103.      * 
  104.      * echo y | mysqladmin create $databaseName
  105.      * </pre></code>
  106.      * The value of <code>$databaseName</code> isn't critical to
  107.      * output, and you obviously don't want to change
  108.      * the ant task to simply take a database name.
  109.      * So initial context values can be set with
  110.      * properties file.
  111.      *
  112.      * @var array
  113.      */
  114.     protected $contextProperties;
  115.         
  116.     // -----------------------------------------------------------------------
  117.     // The following getters & setters are used by phing to set properties
  118.     // specified in the XML for the capsule task.
  119.     // -----------------------------------------------------------------------
  120.     
  121.     /**
  122.      * [REQUIRED] Set the control template for the
  123.      * generating process.
  124.      * @param string $controlTemplate
  125.      * @return void
  126.      */
  127.     public function setControlTemplate ($controlTemplate) {
  128.         $this->controlTemplate = $controlTemplate;
  129.     }
  130.  
  131.     /**
  132.      * Get the control template for the
  133.      * generating process.
  134.      * @return string
  135.      */
  136.     public function getControlTemplate() {
  137.         return $this->controlTemplate;
  138.     }
  139.  
  140.     /**
  141.      * [REQUIRED] Set the path where Velocity will look
  142.      * for templates using the file template
  143.      * loader.
  144.      * @return void
  145.      * @throws Exception 
  146.      */
  147.     public function setTemplatePath($templatePath) {
  148.         $resolvedPath = "";        
  149.         $tok = strtok($templatePath, ",");
  150.         while ( $tok ) {            
  151.             // resolve relative path from basedir and leave
  152.             // absolute path untouched.
  153.             $fullPath = $this->project->resolveFile($tok);
  154.             $cpath = $fullPath->getCanonicalPath();
  155.             if ($cpath === false) {
  156.                 $this->log("Template directory does not exist: " . $fullPath->getAbsolutePath());
  157.             } else {
  158.                 $resolvedPath .= $cpath;
  159.             }
  160.             $tok = strtok(",");
  161.             if ( $tok ) {
  162.                 $resolvedPath .= ",";
  163.             }
  164.         }
  165.         $this->templatePath = $resolvedPath;
  166.      }
  167.  
  168.     /**
  169.      * Get the path where Velocity will look
  170.      * for templates using the file template
  171.      * loader.
  172.      * @return string
  173.      */
  174.     public function getTemplatePath() {
  175.         return $this->templatePath;
  176.     }        
  177.  
  178.     /**
  179.      * [REQUIRED] Set the output directory. It will be
  180.      * created if it doesn't exist.
  181.      * @param PhingFile $outputDirectory
  182.      * @return void
  183.      * @throws Exception
  184.      */
  185.     public function setOutputDirectory(PhingFile $outputDirectory) {
  186.         try {
  187.             if (!$outputDirectory->exists()) {
  188.                 $this->log("Output directory does not exist, creating: " . $outputDirectory->getPath(),Project::MSG_VERBOSE);
  189.                 if (!$outputDirectory->mkdirs()) {
  190.                     throw new IOException("Unable to create Ouptut directory: " . $outputDirectory->getAbsolutePath());
  191.                 }
  192.             }
  193.             $this->outputDirectory = $outputDirectory->getCanonicalPath();
  194.         } catch (IOException $ioe) {
  195.             throw new BuildException($ioe);
  196.         }
  197.     }
  198.       
  199.     /**
  200.      * Get the output directory.
  201.      * @return string
  202.      */
  203.     public function getOutputDirectory() {
  204.         return $this->outputDirectory;
  205.     }        
  206.  
  207.     /**
  208.      * [REQUIRED] Set the output file for the
  209.      * generation process.
  210.      * @param string $outputFile (TODO: change this to File)
  211.      * @return void
  212.      */
  213.     public function setOutputFile($outputFile) {
  214.         $this->outputFile = $outputFile;
  215.     }
  216.  
  217.     /**
  218.      * Get the output file for the
  219.      * generation process.
  220.      * @return string
  221.      */
  222.     public function getOutputFile() {
  223.         return $this->outputFile;
  224.     }        
  225.     
  226.     /**
  227.      * Set the context properties that will be
  228.      * fed into the initial context be the
  229.      * generating process starts.
  230.      * @param string $file
  231.      * @return void
  232.      */
  233.     public function setContextProperties($file) {
  234.         $sources = explode(",", $file);
  235.         $this->contextProperties = new Properties();
  236.         
  237.         // Always try to get the context properties resource
  238.         // from a file first. Templates may be taken from a JAR
  239.         // file but the context properties resource may be a 
  240.         // resource in the filesystem. If this fails than attempt
  241.         // to get the context properties resource from the
  242.         // classpath.
  243.         for ($i=0, $sourcesLength=count($sources); $i < $sourcesLength; $i++) {
  244.             $source = new Properties();
  245.             
  246.             try {
  247.             
  248.                 // resolve relative path from basedir and leave
  249.                 // absolute path untouched.
  250.                 $fullPath = $this->project->resolveFile($sources[$i]);
  251.                 $this->log("Using contextProperties file: " . $fullPath->toString());
  252.                 $source->load($fullPath);
  253.                 
  254.             } catch (Exception $e) {
  255.               
  256.               throw new BuildException("Context properties file " . $sources[$i] .
  257.                             " could not be found in the file system!");
  258.                      
  259.             }
  260.         
  261.             $keys = $source->keys();
  262.             
  263.             foreach ($keys as $key) {
  264.                 $name = $key;
  265.                 $value = $this->project->replaceProperties($source->getProperty($name));
  266.                 $this->contextProperties->setProperty($name, $value);
  267.             }
  268.         }
  269.     }
  270.  
  271.     /**
  272.      * Get the context properties that will be
  273.      * fed into the initial context be the
  274.      * generating process starts.
  275.      * @return Properties
  276.      */
  277.     public function getContextProperties() {
  278.         return $this->contextProperties;
  279.     }     
  280.  
  281.     /** 
  282.      * Creates an "AssignedVar" class.
  283.      */
  284.     public function createAssign() {
  285.         $a = new AssignedVar();
  286.         $this->assignedVars[] = $a;
  287.         return $a;
  288.     }
  289.     
  290.     // ---------------------------------------------------------------
  291.     // End of XML setters & getters
  292.     // ---------------------------------------------------------------
  293.    
  294.     /**
  295.      * Creates a Smarty object.
  296.      *
  297.      * @return Smarty initialized (cleared) Smarty context.
  298.      * @throws Exception the execute method will catch 
  299.      *         and rethrow as a <code>BuildException</code>
  300.      */
  301.     public function initControlContext() {
  302.         $this->context->clear();
  303.         foreach($this->assignedVars as $var) {
  304.             $this->context->put($var->getName(), $var->getValue());
  305.         }
  306.         return $this->context;
  307.     }
  308.     
  309.     /**
  310.      * Execute the input script with Velocity
  311.      *
  312.      * @throws BuildException  
  313.      * BuildExceptions are thrown when required attributes are missing.
  314.      * Exceptions thrown by Velocity are rethrown as BuildExceptions.
  315.      */
  316.     public function main() {
  317.     
  318.         // Make sure the template path is set.
  319.         if (empty($this->templatePath)) {
  320.             throw new BuildException("The template path needs to be defined!");
  321.         }            
  322.     
  323.         // Make sure the control template is set.
  324.         if ($this->controlTemplate === null) {
  325.             throw new BuildException("The control template needs to be defined!");
  326.         }            
  327.  
  328.         // Make sure the output directory is set.
  329.         if ($this->outputDirectory === null) {
  330.             throw new BuildException("The output directory needs to be defined!");
  331.         }            
  332.         
  333.         // Make sure there is an output file.
  334.         if ($this->outputFile === null) {
  335.             throw new BuildException("The output file needs to be defined!");
  336.         }            
  337.         
  338.         // Setup Smarty runtime.
  339.         
  340.         // Smarty uses one object to store properties and to store
  341.         // the context for the template (unlike Velocity).  We setup this object, calling it
  342.         // $this->context, and then initControlContext simply zeros out
  343.         // any assigned variables.
  344.         $this->context = new Capsule();
  345.                 
  346.         if ($this->templatePath !== null) {
  347.             $this->log("Using templatePath: " . $this->templatePath);
  348.             $this->context->setTemplatePath($this->templatePath);
  349.         }                                                        
  350.                 
  351.         // Make sure the output directory exists, if it doesn't
  352.         // then create it.
  353.         $outputDir = new PhingFile($this->outputDirectory);
  354.         if (!$outputDir->exists()) {
  355.             $this->log("Output directory does not exist, creating: " . $outputDir->getAbsolutePath());
  356.             $outputDir->mkdirs();
  357.         }
  358.         
  359.         $this->context->setOutputDirectory($outputDir->getAbsolutePath());
  360.         
  361.         $path = $this->outputDirectory . DIRECTORY_SEPARATOR . $this->outputFile;
  362.         $this->log("Generating to file " . $path);
  363.         
  364.         //$writer = new FileWriter($path);
  365.                 
  366.         // The generator and the output path should
  367.         // be placed in the init context here and
  368.         // not in the generator class itself.
  369.         $c = $this->initControlContext();
  370.         
  371.         // Set any variables that need to always
  372.         // be loaded
  373.         $this->populateInitialContext($c);
  374.         
  375.         // Feed all the options into the initial
  376.         // control context so they are available
  377.         // in the control/worker templates.
  378.         if ($this->contextProperties !== null) {
  379.             
  380.             foreach($this->contextProperties->keys() as $property) {
  381.                     
  382.             $value = $this->contextProperties->getProperty($property);
  383.             
  384.             // Special exception (from Texen)
  385.             // for properties ending in file.contents:
  386.             // in that case we dump the contents of the file
  387.             // as the "value" for the Property.
  388.             if (preg_match('/file\.contents$/', $property)) {
  389.                 // pull in contents of file specified 
  390.                                         
  391.                 $property = substr($property, 0, strpos($property, "file.contents") - 1);
  392.                 
  393.                 // reset value, and then 
  394.                 // read in teh contents of the file into that var
  395.                 $value = "";
  396.                 $f = new PhingFile($project->resolveFile($value)->getCanonicalPath());                        
  397.                 if ($f->exists()) {
  398.                     $fr = new FileReader($f);
  399.                     $fr->readInto($value);
  400.                 }
  401.                                                                 
  402.             } // if ends with file.contents
  403.             
  404.             if (StringHelper::isBoolean($value)) {
  405.                 $value = StringHelper::booleanValue($value);
  406.             }
  407.                                                             
  408.             $c->put($property, $value); 
  409.                  
  410.             } // foreach property
  411.                 
  412.         } // if contextProperties !== null
  413.         
  414.         try {
  415.             $this->log("Parsing control template: " . $this->controlTemplate);
  416.             $c->parse($this->controlTemplate, $path);
  417.         } catch (Exception $ioe) {
  418.             throw new BuildException("Cannot write parsed template: ". $ioe->getMessage());
  419.         }        
  420.         
  421.         $this->cleanup();    
  422.     }
  423.  
  424.     /**
  425.      * Place useful objects into the initial context.
  426.      *
  427.      *
  428.      * @param Capsule $context The context to populate, as retrieved from
  429.      * {@link #initControlContext()}.
  430.      * @return void
  431.      * @throws Exception Error while populating context.  The {@link
  432.      * #main()} method will catch and rethrow as a
  433.      * <code>BuildException</code>.
  434.      */
  435.     protected function populateInitialContext(Capsule $context) {
  436.         $this->context->put("now", strftime("%c", time()));
  437.         $this->context->put("task", $this);
  438.     }
  439.  
  440.     /**
  441.      * A hook method called at the end of {@link #execute()} which can
  442.      * be overridden to perform any necessary cleanup activities (such
  443.      * as the release of database connections, etc.).  By default,
  444.      * does nothing.
  445.      * @return void
  446.      * @throws Exception Problem cleaning up.
  447.      */
  448.     protected function cleanup() {
  449.     }
  450. }
  451.  
  452.  
  453. /**
  454.  * An "inner" class for holding assigned var values.
  455.  * May be need to expand beyond name/value in the future.
  456.  */
  457. class AssignedVar {
  458.     
  459.     private $name;
  460.     private $value;
  461.     
  462.     function setName($v) {
  463.         $this->name = $v;
  464.     }
  465.     
  466.     function setValue($v) {
  467.         $this->value = $v;
  468.     }
  469.     
  470.     function getName() {
  471.         return $this->name;
  472.     }
  473.     
  474.     function getValue() {
  475.         return $this->value;
  476.     }
  477.  
  478. }