| [ Index ] |
|
Code source de Symfony 1.0.0 |
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 }
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
| Généré le : Fri Mar 16 22:42:14 2007 | par Balluche grâce à PHPXref 0.7 |