[ Index ]
 

Code source de Symfony 1.0.0

Accédez au Source d'autres logiciels libresSoutenez Angelica Josefina !

title

Body

[fermer]

/lib/vendor/phing/tasks/system/ -> PhingTask.php (source)

   1  <?php
   2  
   3  /*
   4   *  $Id: PhingTask.php 3076 2006-12-18 08:52:12Z fabien $  
   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/util/FileUtils.php';
  25  include_once 'phing/types/Reference.php';
  26  include_once 'phing/tasks/system/PropertyTask.php';
  27  
  28  /**
  29   * Task that invokes phing on another build file.
  30   * 
  31   * Use this task, for example, if you have nested buildfiles in your project. Unlike
  32   * AntTask, PhingTask can even support filesets:
  33   * 
  34   * <pre>
  35   *   <phing>
  36   *    <fileset dir="${srcdir}">
  37   *      <include name="** /build.xml" /> <!-- space added after ** is there because of PHP comment syntax -->
  38   *      <exclude name="build.xml" />
  39   *    </fileset>
  40   *   </phing>
  41   * </pre>
  42   * 
  43   * @author    Hans Lellelid <hans@xmpl.org>
  44   * @version   $Revision: 1.20 $
  45   * @package   phing.tasks.system
  46   */
  47  class PhingTask extends Task {
  48  
  49      /** the basedir where is executed the build file */
  50      private $dir;
  51      
  52      /** build.xml (can be absolute) in this case dir will be ignored */
  53      private $phingFile;
  54      
  55      /** the target to call if any */
  56      protected $newTarget;
  57      
  58      /** should we inherit properties from the parent ? */
  59      private $inheritAll = true;
  60      
  61      /** should we inherit references from the parent ? */
  62      private $inheritRefs = false;
  63  
  64      /** the properties to pass to the new project */
  65      private $properties = array();
  66  
  67      /** the references to pass to the new project */
  68      private $references = array();
  69  
  70      /** The filesets that contain the files PhingTask is to be run on. */
  71      private $filesets = array();
  72  
  73      /** the temporary project created to run the build file */
  74      private $newProject;
  75  
  76      /** Fail the build process when the called build fails? */
  77      private $haltOnFailure = false;
  78  
  79      /**
  80       *  If true, abort the build process if there is a problem with or in the target build file.
  81       *  Defaults to false.
  82       *
  83       *  @param boolean new value
  84       */
  85      public function setHaltOnFailure($hof) {
  86          $this->haltOnFailure = (boolean) $hof;
  87      }
  88  
  89      /**
  90       * Creates a Project instance for the project to call.
  91       * @return void
  92       */
  93      public function init() {
  94          $this->newProject = new Project();
  95          $tdf = $this->project->getTaskDefinitions();
  96          $this->newProject->addTaskDefinition("property", $tdf["property"]);
  97      }
  98  
  99      /**
 100       * Called in execute or createProperty if newProject is null.
 101       *
 102       * <p>This can happen if the same instance of this task is run
 103       * twice as newProject is set to null at the end of execute (to
 104       * save memory and help the GC).</p>
 105       *
 106       * <p>Sets all properties that have been defined as nested
 107       * property elements.</p>
 108       */
 109      private function reinit() {
 110          $this->init();
 111          $count = count($this->properties);
 112          for ($i = 0; $i < $count; $i++) {
 113              $p = $this->properties[$i];
 114              $newP = $this->newProject->createTask("property");
 115              $newP->setName($p->getName());
 116              if ($p->getValue() !== null) {
 117                  $newP->setValue($p->getValue());
 118              }
 119              if ($p->getFile() !== null) {
 120                  $newP->setFile($p->getFile());
 121              }            
 122              if ($p->getPrefix() !== null) {
 123                  $newP->setPrefix($p->getPrefix());
 124              }
 125              if ($p->getRefid() !== null) {
 126                  $newP->setRefid($p->getRefid());
 127              }
 128              if ($p->getEnvironment() !== null) {
 129                  $newP->setEnvironment($p->getEnvironment());
 130              }
 131              if ($p->getUserProperty() !== null) {
 132                  $newP->setUserProperty($p->getUserProperty());
 133              }
 134              if ($p->getOverride() !== null) {
 135                  $newP->setOverride($p->getOverride());
 136              }
 137              $this->properties[$i] = $newP;
 138          }
 139      }
 140  
 141      /**
 142       * Main entry point for the task.
 143       *
 144       * @return void
 145       */
 146      public function main() {
 147      
 148          // Call Phing on the file set with the attribute "phingfile"
 149          if ($this->phingFile !== null or $this->dir !== null) {
 150              $this->processFile();
 151          }
 152  
 153          // if no filesets are given stop here; else process filesets
 154          if (empty($this->filesets)) { 
 155              return;
 156          }
 157          
 158          // preserve old settings
 159          $savedDir = $this->dir;
 160          $savedPhingFile = $this->phingFile;
 161          $savedTarget = $this->newTarget;
 162          $buildFailed = false;
 163  
 164          // set no specific target for files in filesets
 165          // [HL] I'm commenting this out; I don't know why this should not be supported!
 166          // $this->newTarget = null;
 167          
 168          foreach($this->filesets as $fs) {
 169  
 170              $ds = $fs->getDirectoryScanner($this->project);
 171  
 172              $fromDir  = $fs->getDir($this->project);
 173              $srcFiles = $ds->getIncludedFiles();
 174  
 175              foreach($srcFiles as $fname) {            
 176                  $f = new PhingFile($ds->getbasedir(), $fname);
 177                  $f = $f->getAbsoluteFile();
 178                  $this->phingFile = $f->getAbsolutePath();
 179                  $this->dir = $f->getParentFile();
 180                  $this->processFile();    // run Phing!
 181              }
 182          }        
 183          
 184          // side effect free programming ;-)
 185          $this->dir = $savedDir;        
 186          $this->phingFile = $savedPhingFile;
 187          $this->newTarget = $savedTarget;
 188          
 189          // [HL] change back to correct dir
 190          if ($this->dir !== null) {
 191              chdir($this->dir->getAbsolutePath());
 192          }
 193          
 194      }
 195      
 196      /**
 197       * Execute phing file.
 198       * 
 199       * @return void
 200       */
 201      private function processFile()  {
 202              
 203          $savedDir = $this->dir;
 204          $savedPhingFile = $this->phingFile;
 205          $savedTarget = $this->newTarget;
 206          
 207          $savedBasedirAbsPath = null; // this is used to save the basedir *if* we change it
 208          
 209          try {
 210          
 211              if ($this->newProject === null) {
 212                  $this->reinit();
 213              }
 214  
 215              $this->initializeProject();
 216              
 217              if ($this->dir !== null) {
 218                  
 219                  $dirAbsPath = $this->dir->getAbsolutePath();
 220                  
 221                  // BE CAREFUL! -- when the basedir is changed for a project,
 222                  // all calls to getAbsolutePath() on a relative-path dir will
 223                  // be made relative to the project's basedir!  This means
 224                  // that subsequent calls to $this->dir->getAbsolutePath() will be WRONG!
 225                  
 226                  // We need to save the current project's basedir first.
 227                  $savedBasedirAbsPath = $this->getProject()->getBasedir()->getAbsolutePath();
 228                   
 229                  $this->newProject->setBasedir($this->dir);
 230                  
 231                  // Now we must reset $this->dir so that it continues to resolve to the same
 232                  // path.
 233                  $this->dir = new PhingFile($dirAbsPath);
 234                  
 235                  if ($savedDir !== null) { // has been set explicitly
 236                      $this->newProject->setInheritedProperty("project.basedir", $this->dir->getAbsolutePath());
 237                  }
 238                  
 239              } else {
 240                  
 241                  // Since we're not changing the basedir here (for file resolution),
 242                  // we don't need to worry about any side-effects in this scanrio.
 243                  $this->dir = $this->getProject()->getBasedir();   
 244              }
 245  
 246              $this->overrideProperties();
 247              if ($this->phingFile === null) {
 248                  $this->phingFile = "build.xml";
 249              }
 250              
 251              $fu = new FileUtils();
 252              $file = $fu->resolveFile($this->dir, $this->phingFile);
 253              $this->phingFile = $file->getAbsolutePath();
 254              
 255              $this->log("Calling Buildfile '" . $this->phingFile . "' with target '" . $this->newTarget . "'");
 256                          
 257              $this->newProject->setUserProperty("phing.file", $this->phingFile);
 258                         
 259              ProjectConfigurator::configureProject($this->newProject, new PhingFile($this->phingFile));
 260  
 261              if ($this->newTarget === null) {
 262                  $this->newTarget = $this->newProject->getDefaultTarget();
 263              }
 264  
 265              // Are we trying to call the target in which we are defined?
 266              if ($this->newProject->getBaseDir() == $this->project->getBaseDir() &&
 267                  $this->newProject->getProperty("phing.file") == $this->project->getProperty("phing.file") &&
 268                  $this->getOwningTarget() !== null &&
 269                  $this->newTarget == $this->getOwningTarget()->getName()) {
 270  
 271                  throw new BuildException("phing task calling its own parent target");
 272              }
 273  
 274              $this->addReferences();
 275              $this->newProject->executeTarget($this->newTarget);
 276              
 277          } catch (Exception $e) {
 278              $buildFailed = true;
 279              $this->log($e->getMessage(), PROJECT_MSG_ERR);
 280              
 281              // important!!! continue on to perform cleanup tasks.    
 282          }
 283          
 284          
 285          // reset environment values to prevent side-effects.
 286          
 287          $this->newProject = null;
 288          $pkeys = array_keys($this->properties);
 289          foreach($pkeys as $k) {
 290              $this->properties[$k]->setProject(null);
 291          }
 292          
 293          $this->dir = $savedDir;        
 294          $this->phingFile = $savedPhingFile;
 295          $this->newTarget = $savedTarget;
 296          
 297          // If the basedir for any project was changed, we need to set that back here.
 298          if ($savedBasedirAbsPath !== null) {
 299              chdir($savedBasedirAbsPath);
 300          }
 301  
 302          if ($this->haltOnFailure && $buildFailed) {
 303              throw new BuildException("Execution of the target buildfile failed. Aborting.");
 304          }
 305      }
 306  
 307      /**
 308       * Configure the Project, i.e. make intance, attach build listeners
 309       * (copy from father project), add Task and Datatype definitions,
 310       * copy properties and references from old project if these options
 311       * are set via the attributes of the XML tag.
 312       *
 313       * Developer note:
 314       * This function replaces the old methods "init", "_reinit" and 
 315       * "_initializeProject".
 316       *
 317       * @access      protected
 318       */
 319      private function initializeProject() {
 320          
 321          $this->newProject->setInputHandler($this->project->getInputHandler());
 322          
 323          foreach($this->project->getBuildListeners() as $listener) {
 324              $this->newProject->addBuildListener($listener);
 325          }
 326          
 327          /* Copy things from old project. Datatypes and Tasks are always
 328           * copied, properties and references only if specified so/not
 329           * specified otherwise in the XML definition.
 330           */
 331          // Add Datatype definitions
 332          foreach ($this->project->getDataTypeDefinitions() as $typeName => $typeClass) {
 333              $this->newProject->addDataTypeDefinition($typeName, $typeClass);
 334          }
 335          
 336          // Add Task definitions
 337          foreach ($this->project->getTaskDefinitions() as $taskName => $taskClass) {
 338              if ($taskClass == "propertytask") {
 339                  // we have already added this taskdef in init()
 340                  continue;
 341              }
 342              $this->newProject->addTaskDefinition($taskName, $taskClass);
 343          }
 344  
 345          // set user-defined properties
 346          $this->project->copyUserProperties($this->newProject);
 347  
 348          if (!$this->inheritAll) {
 349             // set System built-in properties separately,
 350             // b/c we won't inherit them.
 351             $this->newProject->setSystemProperties();
 352  
 353          } else {
 354              // set all properties from calling project
 355              $properties = $this->project->getProperties();
 356              foreach ($properties as $name => $value) {                
 357                  if ($name == "basedir" || $name == "phing.file" || $name == "phing.version") {
 358                      // basedir and phing.file get special treatment in main()
 359                      continue;
 360                  }
 361                     // don't re-set user properties, avoid the warning message
 362                  if ($this->newProject->getProperty($name) === null){
 363                      // no user property
 364                      $this->newProject->setNewProperty($name, $value);
 365                  }
 366              }
 367              
 368          }
 369      
 370      }
 371  
 372      /**
 373       * Override the properties in the new project with the one
 374       * explicitly defined as nested elements here.
 375       * @return void
 376       * @throws BuildException 
 377       */
 378      private function overrideProperties() {     
 379          foreach(array_keys($this->properties) as $i) {
 380              $p = $this->properties[$i];
 381              $p->setProject($this->newProject);
 382              $p->main();
 383          }
 384          $this->project->copyInheritedProperties($this->newProject);
 385      }
 386  
 387      /**
 388       * Add the references explicitly defined as nested elements to the
 389       * new project.  Also copy over all references that don't override
 390       * existing references in the new project if inheritrefs has been
 391       * requested.
 392       * 
 393       * @return void
 394       * @throws BuildException 
 395       */
 396      private function addReferences() {
 397      
 398          // parent project references
 399          $projReferences = $this->project->getReferences();
 400          
 401          $newReferences = $this->newProject->getReferences();
 402          
 403          $subprojRefKeys = array();
 404          
 405          if (count($this->references) > 0) {
 406              for ($i=0, $count=count($this->references); $i < $count; $i++) {
 407                  $ref = $this->references[$i];            
 408                  $refid = $ref->getRefId();
 409                  
 410                  if ($refid === null) {
 411                      throw new BuildException("the refid attribute is required"
 412                                               . " for reference elements");
 413                  }
 414                  if (!isset($projReferences[$refid])) {
 415                      $this->log("Parent project doesn't contain any reference '"
 416                          . $refid . "'",
 417                          PROJECT_MSG_WARN);
 418                      continue;
 419                  }
 420                  
 421                  $subprojRefKeys[] = $refid;
 422                  //thisReferences.remove(refid);
 423                  $toRefid = $ref->getToRefid();
 424                  if ($toRefid === null) {
 425                      $toRefid = $refid;
 426                  }
 427                  $this->copyReference($refid, $toRefid);
 428              }
 429          }
 430  
 431          // Now add all references that are not defined in the
 432          // subproject, if inheritRefs is true
 433          if ($this->inheritRefs) {
 434          
 435              // get the keys that are were not used by the subproject
 436              $unusedRefKeys = array_diff(array_keys($projReferences), $subprojRefKeys);
 437              
 438              foreach($unusedRefKeys as $key) {
 439                  if (isset($newReferences[$key])) {
 440                      continue;
 441                  }
 442                  $this->copyReference($key, $key);
 443              }
 444          }
 445      }
 446  
 447      /**
 448       * Try to clone and reconfigure the object referenced by oldkey in
 449       * the parent project and add it to the new project with the key
 450       * newkey.
 451       *
 452       * <p>If we cannot clone it, copy the referenced object itself and
 453       * keep our fingers crossed.</p>
 454       *
 455       * @param string $oldKey
 456       * @param string $newKey
 457       * @return void
 458       */
 459      private function copyReference($oldKey, $newKey) {
 460          $orig = $this->project->getReference($oldKey);
 461          if ($orig === null) {
 462              $this->log("No object referenced by " . $oldKey . ". Can't copy to " 
 463                  .$newKey, 
 464                  PROJECT_SG_WARN);
 465              return;
 466          }
 467  
 468          $copy = clone $orig;
 469  
 470          if ($copy instanceof ProjectComponent) {
 471              $copy->setProject($this->newProject);
 472          } elseif (in_array('setProject', get_class_methods(get_class($copy)))) {
 473              $copy->setProject($this->newProject);
 474          } elseif ($copy instanceof Project) {
 475              // don't copy the old "Project" itself
 476          } else {
 477              $msg = "Error setting new project instance for "
 478                  . "reference with id " . $oldKey;
 479              throw new BuildException($msg);
 480          }
 481          
 482          $this->newProject->addReference($newKey, $copy);
 483      }
 484  
 485      /**
 486       * If true, pass all properties to the new phing project.
 487       * Defaults to true.
 488       *
 489       * @access      public
 490       */
 491      function setInheritAll($value) {
 492          $this->inheritAll = (boolean) $value;
 493      }
 494  
 495      /**
 496       * If true, pass all references to the new phing project.
 497       * Defaults to false.
 498       *
 499       * @access      public
 500       */
 501      function setInheritRefs($value) {
 502          $this->inheritRefs = (boolean)$value;
 503      }
 504  
 505      /**
 506       * The directory to use as a base directory for the new phing project.
 507       * Defaults to the current project's basedir, unless inheritall
 508       * has been set to false, in which case it doesn't have a default
 509       * value. This will override the basedir setting of the called project.
 510       *
 511       * @access      public
 512       */
 513      function setDir($d) {
 514          if ( is_string($d) )
 515              $this->dir = new PhingFile($d);
 516          else
 517              $this->dir = $d;
 518      }
 519  
 520      /**
 521       * The build file to use.
 522       * Defaults to "build.xml". This file is expected to be a filename relative
 523       * to the dir attribute given.
 524       *
 525       * @access      public
 526       */
 527      function setPhingfile($s) {
 528          // it is a string and not a file to handle relative/absolute
 529          // otherwise a relative file will be resolved based on the current
 530          // basedir.
 531          $this->phingFile = $s;
 532      }
 533  
 534     /**
 535      * Alias function for setPhingfile
 536      *
 537      * @access       public
 538      */
 539      function setBuildfile($s) {
 540          $this->setPhingFile($s);
 541      }
 542  
 543      /**
 544       * The target of the new Phing project to execute.
 545       * Defaults to the new project's default target.
 546       *
 547       * @access      public
 548       */
 549      function setTarget($s) {
 550          $this->newTarget = $s;
 551      }
 552  
 553      /**
 554       * Support for filesets; This method returns a reference to an instance
 555       * of a FileSet object.
 556       *
 557       * @return FileSet
 558       */
 559      function createFileSet() {
 560          $num = array_push($this->filesets, new FileSet());
 561          return $this->filesets[$num-1];
 562      }
 563  
 564      /**
 565       * Property to pass to the new project.
 566       * The property is passed as a 'user property'
 567       *
 568       * @access      public
 569       */
 570      function createProperty() {
 571          $p = new PropertyTask();
 572          $p->setFallback($this->newProject);
 573          $p->setUserProperty(true);
 574          $this->properties[] = $p;
 575          return $p;
 576      }
 577  
 578      /**
 579       * Reference element identifying a data type to carry
 580       * over to the new project.
 581       *
 582       * @access      public
 583       */
 584      function createReference() {
 585          $num = array_push($this->references, new PhingReference());
 586          return $this->references[$num-1];
 587      }
 588  
 589  }
 590  
 591  /**
 592   * Helper class that implements the nested <reference>
 593   * element of <phing> and <phingcall>.
 594   */
 595  class PhingReference extends Reference {
 596  
 597      private $targetid = null;
 598  
 599      /**
 600       * Set the id that this reference to be stored under in the
 601       * new project.
 602       *
 603       * @param targetid the id under which this reference will be passed to
 604       *        the new project */
 605      public function setToRefid($targetid) {
 606          $this->targetid = $targetid;
 607      }
 608  
 609      /**
 610       * Get the id under which this reference will be stored in the new
 611       * project
 612       *
 613       * @return the id of the reference in the new project.
 614       */
 615      public function getToRefid() {
 616          return $this->targetid;
 617      }
 618  }


Généré le : Fri Mar 16 22:42:14 2007 par Balluche grâce à PHPXref 0.7