[ Index ]
 

Code source de Symfony 1.0.0

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

title

Body

[fermer]

/lib/vendor/phing/ -> Phing.php (source)

   1  <?php
   2  /*
   3   * $Id: Phing.php 3076 2006-12-18 08:52:12Z fabien $
   4   *
   5   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   6   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   7   * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
   8   * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
   9   * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  10   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  11   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  12   * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  13   * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  14   * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  15   * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  16   *
  17   * This software consists of voluntary contributions made by many individuals
  18   * and is licensed under the LGPL. For more information please see
  19   * <http://phing.info>.
  20   */
  21   
  22  require_once 'phing/Project.php';
  23  require_once 'phing/ProjectComponent.php';
  24  require_once 'phing/Target.php';
  25  require_once 'phing/Task.php';
  26  
  27  include_once 'phing/BuildException.php';
  28  include_once 'phing/BuildEvent.php';
  29  
  30  include_once 'phing/parser/Location.php';
  31  include_once 'phing/parser/ExpatParser.php';
  32  include_once 'phing/parser/AbstractHandler.php';
  33  include_once 'phing/parser/ProjectConfigurator.php';
  34  include_once 'phing/parser/RootHandler.php';
  35  include_once 'phing/parser/ProjectHandler.php';
  36  include_once 'phing/parser/TaskHandler.php';
  37  include_once 'phing/parser/TargetHandler.php';
  38  include_once 'phing/parser/DataTypeHandler.php';
  39  include_once 'phing/parser/NestedElementHandler.php';
  40  
  41  include_once 'phing/system/util/Properties.php';
  42  include_once 'phing/util/StringHelper.php';
  43  include_once 'phing/system/io/PhingFile.php';
  44  include_once 'phing/system/io/FileReader.php';
  45  include_once 'phing/system/util/Register.php';
  46  
  47  /**
  48   * Entry point into Phing.  This class handles the full lifecycle of a build -- from 
  49   * parsing & handling commandline arguments to assembling the project to shutting down
  50   * and cleaning up in the end.
  51   *
  52   * If you are invoking Phing from an external application, this is still
  53   * the class to use.  Your applicaiton can invoke the start() method, passing
  54   * any commandline arguments or additional properties.
  55   *
  56   * @author    Andreas Aderhold <andi@binarycloud.com>
  57   * @author    Hans Lellelid <hans@xmpl.org>
  58   * @version   $Revision: 1.51 $
  59   * @package   phing
  60   */
  61  class Phing {
  62  
  63      /** The default build file name */
  64      const DEFAULT_BUILD_FILENAME = "build.xml";
  65  
  66      /** Our current message output status. Follows PROJECT_MSG_XXX */
  67      private static $msgOutputLevel = PROJECT_MSG_INFO;
  68  
  69      /** PhingFile that we are using for configuration */
  70      private $buildFile = null;
  71  
  72      /** The build targets */
  73      private $targets = array();
  74  
  75      /**
  76       * Set of properties that are passed in from commandline or invoking code.
  77       * @var Properties
  78       */
  79      private static $definedProps;
  80  
  81      /** Names of classes to add as listeners to project */
  82      private $listeners = array();
  83  
  84      private $loggerClassname = null;
  85  
  86      /** The class to handle input (can be only one). */
  87      private $inputHandlerClassname;
  88      
  89      /** Indicates if this phing should be run */
  90      private $readyToRun = false;
  91  
  92      /** Indicates we should only parse and display the project help information */
  93      private $projectHelp = false;
  94      
  95      /** Used by utility function getResourcePath() */
  96      private static $importPaths;
  97      
  98      /** System-wide static properties (moved from System) */
  99      private static $properties = array();
 100      
 101      /** Static system timer. */
 102      private static $timer;
 103      
 104      /** The current Project */
 105      private static $currentProject;
 106      
 107      /** Whether to capture PHP errors to buffer. */
 108      private static $phpErrorCapture = false;
 109      
 110      /** Array of captured PHP errors */
 111      private static $capturedPhpErrors = array();
 112      
 113      /**
 114       * Prints the message of the Exception if it's not null.
 115       */
 116      function printMessage(Exception $t) {
 117          print($t->getMessage() . "\n");
 118          if (self::getMsgOutputLevel() === PROJECT_MSG_DEBUG) {
 119              print($t->getTraceAsString()."\n");
 120              if ($t instanceof Exception) {                
 121                  $c = $t->getCause();
 122                  if ($c !== null) {
 123                      print("Wrapped exception trace:\n");
 124                      print($c->getTraceAsString() . "\n");
 125                  }
 126              }
 127          } // if output level is DEBUG
 128      }
 129  
 130      /** 
 131       * Entry point allowing for more options from other front ends.
 132       * 
 133       * This method encapsulates the complete build lifecycle.
 134       * 
 135       * @param array &$args The commandline args passed to phing shell script.
 136       * @param array $additionalUserProperties   Any additional properties to be passed to Phing (alternative front-end might implement this).
 137       *                                          These additional properties will be available using the getDefinedProperty() method and will
 138       *                                          be added to the project's "user" properties.
 139       * @return void
 140       * @see execute()
 141       * @see runBuild()
 142       */
 143      public static function start(&$args, $additionalUserProperties = null) {
 144  
 145          try {
 146              $m = new Phing();
 147              $m->execute($args);
 148          } catch (Exception $exc) {
 149              $m->printMessage($exc);
 150              self::halt(-1); // Parameter error
 151          }
 152  
 153          if ($additionalUserProperties !== null) {
 154              $keys = $m->additionalUserProperties->keys();
 155              while(count($keys)) {
 156                  $key = array_shift($keys);
 157                  $property = $m->additionalUserProperties->getProperty($key);
 158                  $m->setDefinedProperty($key, $property);
 159              }
 160          }
 161  
 162          try {
 163              $m->runBuild();
 164          } catch(Exception $exc) {
 165              self::halt(1); // Errors occured
 166          }
 167          
 168          // everything fine, shutdown
 169          self::halt(0); // no errors, everything is cake
 170      }
 171      
 172      /**
 173       * Making output level a static property so that this property
 174       * can be accessed by other parts of the system, enabling
 175       * us to display more information -- e.g. backtraces -- for "debug" level.
 176       * @return int
 177       */
 178      public static function getMsgOutputLevel() {
 179          return self::$msgOutputLevel;
 180      }        
 181      
 182      /**
 183       * Command line entry point. This method kicks off the building
 184       * of a project object and executes a build using either a given
 185       * target or the default target.
 186       *
 187       * @param array $args Command line args.
 188       * @return void
 189       */
 190      public static function fire($args) {
 191          self::start($args, null);
 192      }
 193      
 194      /**
 195       * Setup/initialize Phing environment from commandline args.
 196       * @param array $args commandline args passed to phing shell.
 197       * @return void
 198       */
 199      public function execute($args) {
 200      
 201          self::$definedProps = new Properties();
 202          $this->searchForThis = null;
 203  
 204          // cycle through given args
 205          for ($i = 0, $argcount = count($args); $i < $argcount; ++$i) { 
 206                              // ++$i intentional here, as first param is script name
 207              $arg = $args[$i];
 208  
 209              if ($arg == "-help" || $arg == "-h") {
 210                  $this->printUsage();
 211                  return;
 212              } elseif ($arg == "-version" || $arg == "-v") {
 213                  $this->printVersion();
 214                  return;
 215              } elseif ($arg == "-quiet" || $arg == "-q") {
 216                  self::$msgOutputLevel = PROJECT_MSG_WARN;
 217              } elseif ($arg == "-verbose") {
 218                  $this->printVersion();
 219                  self::$msgOutputLevel = PROJECT_MSG_VERBOSE;
 220              } elseif ($arg == "-debug") {
 221                  $this->printVersion();
 222                  self::$msgOutputLevel = PROJECT_MSG_DEBUG;
 223              } elseif ($arg == "-logfile") {
 224                  try { // try to set logfile
 225                      if (!isset($args[$i+1])) {
 226                          print("You must specify a log file when using the -logfile argument\n");
 227                          return;
 228                      } else {
 229                          $logFile = new PhingFile($args[++$i]);
 230                          $this->loggerClassname = 'phing.listener.PearLogger';
 231                          $this->setDefinedProperty('pear.log.name', $logFile->getAbsolutePath());
 232                      }
 233                  } catch (IOException $ioe) {
 234                      print("Cannot write on the specified log file. Make sure the path exists and you have write permissions.\n");
 235                      throw $ioe;
 236                  }
 237              } elseif ($arg == "-buildfile" || $arg == "-file" || $arg == "-f") {
 238                  if (!isset($args[$i+1])) {
 239                      print("You must specify a buildfile when using the -buildfile argument\n");
 240                      return;
 241                  } else {
 242                      $this->buildFile = new PhingFile($args[++$i]);
 243                  }
 244              } elseif ($arg == "-listener") {
 245                  if (!isset($args[$i+1])) {
 246                      print("You must specify a listener class when using the -listener argument\n");
 247                      return;
 248                  } else {
 249                      $this->listeners[] = $args[++$i];
 250                  }
 251                  
 252              } elseif (StringHelper::startsWith("-D", $arg)) {
 253                  $name = substr($arg, 2);
 254                  $value = null;
 255                  $posEq = strpos($name, "=");
 256                  if ($posEq !== false) {
 257                      $value = substr($name, $posEq+1);
 258                      $name  = substr($name, 0, $posEq);
 259                  } elseif ($i < count($args)-1) {
 260                      $value = $args[++$i];
 261                  }
 262                  self::$definedProps->setProperty($name, $value);
 263              } elseif ($arg == "-logger") {
 264                  if (!isset($args[$i+1])) {
 265                      print("You must specify a classname when using the -logger argument\n");
 266                      return;
 267                  } else {
 268                      $this->loggerClassname = $args[++$i];
 269                  }
 270              } elseif ($arg == "-inputhandler") {
 271                  if ($this->inputHandlerClassname !== null) {
 272                      throw new BuildException("Only one input handler class may be specified.");
 273                  }
 274                  if (!isset($args[$i+1])) {
 275                      print("You must specify a classname when using the -inputhandler argument\n");
 276                      return;
 277                  } else {
 278                      $this->inputHandlerClassname = $args[++$i];
 279                  }
 280              } elseif ($arg == "-projecthelp" || $arg == "-targets" || $arg == "-list" || $arg == "-l") {
 281                  // set the flag to display the targets and quit
 282                  $this->projectHelp = true;
 283              } elseif ($arg == "-find") {
 284                  // eat up next arg if present, default to build.xml
 285                  if ($i < count($args)-1) {
 286                      $this->searchForThis = $args[++$i];
 287                  } else {
 288                      $this->searchForThis = self::DEFAULT_BUILD_FILENAME;
 289                  }
 290              } elseif (substr($arg,0,1) == "-") {
 291                  // we don't have any more args
 292                  print("Unknown argument: $arg\n");
 293                  $this->printUsage();
 294                  return;
 295              } else {
 296                  // if it's no other arg, it may be the target
 297                  array_push($this->targets, $arg);
 298              }
 299          }
 300  
 301          // if buildFile was not specified on the command line,
 302          if ($this->buildFile === null) {
 303              // but -find then search for it
 304              if ($this->searchForThis !== null) {
 305                  $this->buildFile = $this->_findBuildFile(self::getProperty("user.dir"), $this->searchForThis);
 306              } else {
 307                  $this->buildFile = new PhingFile(self::DEFAULT_BUILD_FILENAME);
 308              }
 309          }
 310          // make sure buildfile exists
 311          if (!$this->buildFile->exists()) {
 312              throw new BuildException("Buildfile: " . $this->buildFile->__toString() . " does not exist!");
 313          }
 314  
 315          // make sure it's not a directory
 316          if ($this->buildFile->isDirectory()) {   
 317              throw new BuildException("Buildfile: " . $this->buildFile->__toString() . " is a dir!");
 318          }
 319  
 320          $this->readyToRun = true;
 321      }
 322  
 323      /**
 324       * Helper to get the parent file for a given file.
 325       *
 326       * @param PhingFile $file
 327       * @return PhingFile Parent file or null if none
 328       */
 329      function _getParentFile(PhingFile $file) {
 330          $filename = $file->getAbsolutePath();
 331          $file     = new PhingFile($filename);
 332          $filename = $file->getParent();
 333  
 334          if ($filename !== null && self::$msgOutputLevel >= PROJECT_MSG_VERBOSE) {
 335              print("Searching in $filename\n");
 336          }
 337  
 338          return ($filename === null) ? null : new PhingFile($filename);
 339      }
 340  
 341      /**
 342       * Search parent directories for the build file.
 343       *
 344       * Takes the given target as a suffix to append to each
 345       * parent directory in search of a build file.  Once the
 346       * root of the file-system has been reached an exception
 347       * is thrown.
 348       * 
 349       * @param string $start Start file path.
 350       * @param string $suffix Suffix filename to look for in parents.
 351       * @return PhingFile A handle to the build file
 352       *
 353       * @throws BuildException    Failed to locate a build file
 354       */
 355      function _findBuildFile($start, $suffix) {
 356          if (self::$msgOutputLevel >= PROJECT_MSG_INFO) {
 357              print("Searching for $suffix ...\n");
 358          }
 359          $startf = new PhingFile($start);
 360          $parent = new PhingFile($startf->getAbsolutePath());
 361          $file   = new PhingFile($parent, $suffix);
 362  
 363          // check if the target file exists in the current directory
 364          while (!$file->exists()) {
 365              // change to parent directory
 366              $parent = $this->_getParentFile($parent);
 367  
 368              // if parent is null, then we are at the root of the fs,
 369              // complain that we can't find the build file.
 370              if ($parent === null) {
 371                  throw new BuildException("Could not locate a build file!");
 372              }
 373              // refresh our file handle
 374              $file = new PhingFile($parent, $suffix);
 375          }
 376          return $file;
 377      }
 378  
 379      /**
 380       * Executes the build.
 381       * @return void
 382       */
 383      function runBuild() {
 384  
 385          if (!$this->readyToRun) {
 386              return;
 387          }
 388          
 389          $project = new Project();
 390          
 391          self::setCurrentProject($project);
 392          set_error_handler(array('Phing', 'handlePhpError'));
 393          
 394          $error = null;
 395  
 396          $this->addBuildListeners($project);
 397          $this->addInputHandler($project);
 398          
 399          // set this right away, so that it can be used in logging.
 400          $project->setUserProperty("phing.file", $this->buildFile->getAbsolutePath());
 401  
 402          try {
 403              $project->fireBuildStarted();
 404              $project->init();
 405          } catch (Exception $exc) {
 406              $project->fireBuildFinished($exc);
 407              throw $exc;        
 408          }
 409  
 410          $project->setUserProperty("phing.version", $this->getPhingVersion());
 411  
 412          $e = self::$definedProps->keys();
 413          while (count($e)) {
 414              $arg   = (string) array_shift($e);
 415              $value = (string) self::$definedProps->getProperty($arg);
 416              $project->setUserProperty($arg, $value);
 417          }
 418          unset($e);
 419  
 420          $project->setUserProperty("phing.file", $this->buildFile->getAbsolutePath());
 421  
 422          // first use the Configurator to create the project object
 423          // from the given build file.
 424                  
 425          try {
 426              ProjectConfigurator::configureProject($project, $this->buildFile);
 427          } catch (Exception $exc) {
 428              $project->fireBuildFinished($exc);
 429              restore_error_handler();
 430              self::unsetCurrentProject();
 431              throw $exc;
 432          }         
 433  
 434          // make sure that we have a target to execute
 435          if (count($this->targets) === 0) {
 436              $this->targets[] = $project->getDefaultTarget();
 437          }
 438  
 439          // execute targets if help param was not given
 440          if (!$this->projectHelp) {
 441              
 442              try { 
 443                  $project->executeTargets($this->targets);
 444              } catch (Exception $exc) {
 445                  $project->fireBuildFinished($exc);
 446                  restore_error_handler();
 447                  self::unsetCurrentProject();
 448                  throw $exc;
 449              }
 450          }
 451          // if help is requested print it
 452          if ($this->projectHelp) {
 453              try {
 454                  $this->printDescription($project);
 455                  $this->printTargets($project);
 456              } catch (Exception $exc) {
 457                  $project->fireBuildFinished($exc);
 458                  restore_error_handler();
 459                  self::unsetCurrentProject();
 460                  throw $exc;
 461              }
 462          }
 463                  
 464          // finally {
 465          if (!$this->projectHelp) {
 466              $project->fireBuildFinished(null);
 467          }
 468          
 469          restore_error_handler();
 470          self::unsetCurrentProject();
 471      }
 472      
 473      /**
 474       * Bind any default build listeners to this project.
 475       * Currently this means adding the logger.
 476       * @param Project $project
 477       * @return void
 478       */
 479      private function addBuildListeners(Project $project) {
 480          // Add the default listener
 481          $project->addBuildListener($this->createLogger());
 482      }
 483      
 484      /**
 485       * Creates the InputHandler and adds it to the project.
 486       *
 487       * @param Project $project the project instance.
 488       *
 489       * @throws BuildException if a specified InputHandler
 490       *                           class could not be loaded.
 491       */
 492      private function addInputHandler(Project $project) {
 493          if ($this->inputHandlerClassname === null) {
 494              $handler = new DefaultInputHandler();
 495          } else {
 496              try {
 497                  $clz = Phing::import($this->inputHandlerClassname);
 498                  $handler = new $clz();
 499                  if ($project !== null && method_exists($handler, 'setProject')) {
 500                      $handler->setProject($project);
 501                  } 
 502              } catch (Exception $e) {
 503                  $msg = "Unable to instantiate specified input handler "
 504                      . "class " . $this->inputHandlerClassname . " : "
 505                      . $e->getMessage();
 506                  throw new BuildException($msg);
 507              }
 508          }
 509          $project->setInputHandler($handler);
 510      }
 511  
 512      /**
 513       * Creates the default build logger for sending build events to the log.
 514       * @return BuildListener The created Logger
 515       */
 516      private function createLogger() {
 517          if ($this->loggerClassname !== null) {
 518              self::import($this->loggerClassname);
 519              // get class name part            
 520              $classname = self::import($this->loggerClassname);
 521              $logger = new $classname;
 522          } else {
 523              require_once 'phing/listener/DefaultLogger.php';
 524              $logger = new DefaultLogger();
 525          }
 526          $logger->setMessageOutputLevel(self::$msgOutputLevel);
 527          return $logger;
 528      }
 529      
 530      /**
 531       * Sets the current Project
 532       * @param Project $p
 533       */
 534  	public static function setCurrentProject($p) {
 535          self::$currentProject = $p;
 536      }
 537      
 538      /**
 539       * Unsets the current Project
 540       */
 541  	public static function unsetCurrentProject() {
 542          self::$currentProject = null;
 543      }
 544      
 545      /**
 546       * Gets the current Project.
 547       * @return Project Current Project or NULL if none is set yet/still.
 548       */
 549  	public static function getCurrentProject() {
 550          return self::$currentProject;
 551      }
 552      
 553      /**
 554       * A static convenience method to send a log to the current (last-setup) Project.
 555       * If there is no currently-configured Project, then this will do nothing.
 556       * @param string $message
 557       * @param int $priority PROJECT_MSG_INFO, etc.
 558       */
 559  	public static function log($message, $priority = PROJECT_MSG_INFO) {
 560          $p = self::getCurrentProject();
 561          if ($p) {
 562              $p->log($message, $priority);
 563          }
 564      }
 565      
 566      /**
 567       * Error handler for PHP errors encountered during the build.
 568       * This uses the logging for the currently configured project.
 569       */
 570  	public static function handlePhpError($level, $message, $file, $line) {
 571          
 572          // don't want to print supressed errors
 573          if (error_reporting() > 0) {
 574          
 575              if (self::$phpErrorCapture) {
 576              
 577                  self::$capturedPhpErrors[] = array('message' => $message, 'level' => $level, 'line' => $line, 'file' => $file);
 578                  
 579              } else {
 580              
 581                  $message = '[PHP Error] ' . $message;
 582                  $message .= ' [line ' . $line . ' of ' . $file . ']';
 583          
 584                  switch ($level) {
 585                  
 586                      case E_STRICT:
 587                      case E_NOTICE:
 588                      case E_USER_NOTICE:
 589                          self::log($message, PROJECT_MSG_VERBOSE);
 590                          break;
 591                      case E_WARNING:
 592                      case E_USER_WARNING:
 593                          self::log($message, PROJECT_MSG_WARN);
 594                          break;
 595                      case E_ERROR:
 596                      case E_USER_ERROR:
 597                      default:
 598                          self::log($message, PROJECT_MSG_ERR);
 599      
 600                  } // switch
 601                  
 602              } // if phpErrorCapture
 603              
 604          } // if not @
 605          
 606      }
 607      
 608      /**
 609       * Begins capturing PHP errors to a buffer.
 610       * While errors are being captured, they are not logged.
 611       */
 612  	public static function startPhpErrorCapture() {
 613          self::$phpErrorCapture = true;
 614          self::$capturedPhpErrors = array();
 615      }
 616      
 617      /**
 618       * Stops capturing PHP errors to a buffer.
 619       * The errors will once again be logged after calling this method.
 620       */
 621  	public static function stopPhpErrorCapture() {
 622          self::$phpErrorCapture = false;
 623      }
 624      
 625      /**
 626       * Clears the captured errors without affecting the starting/stopping of the capture.
 627       */
 628  	public static function clearCapturedPhpErrors() {
 629          self::$capturedPhpErrors = array();
 630      }
 631      
 632      /**
 633       * Gets any PHP errors that were captured to buffer.
 634       * @return array array('message' => message, 'line' => line number, 'file' => file name, 'level' => error level)
 635       */
 636  	public static function getCapturedPhpErrors() {
 637          return self::$capturedPhpErrors;
 638      }
 639      
 640      /**  Prints the usage of how to use this class */
 641      function printUsage() {
 642          $lSep = self::getProperty("line.separator");
 643          $msg = "";
 644          $msg .= "phing [options] [target [target2 [target3] ...]]" . $lSep;
 645          $msg .= "Options: " . $lSep;
 646          $msg .= "  -h -help               print this message" . $lSep;
 647          $msg .= "  -l -list               list available targets in this project" . $lSep;
 648          $msg .= "  -v -version            print the version information and exit" . $lSep;
 649          $msg .= "  -q -quiet              be extra quiet" . $lSep;
 650          $msg .= "  -verbose               be extra verbose" . $lSep;
 651          $msg .= "  -debug                 print debugging information" . $lSep;
 652          $msg .= "  -logfile <file>        use given file for log" . $lSep;
 653          $msg .= "  -logger <classname>    the class which is to perform logging" . $lSep;
 654          $msg .= "  -f -buildfile <file>   use given buildfile" . $lSep;
 655          $msg .= "  -D<property>=<value>   use value for given property" . $lSep;
 656          $msg .= "  -find <file>           search for buildfile towards the root of the" . $lSep;
 657          $msg .= "                         filesystem and use it" . $lSep;
 658          //$msg .= "  -recursive <file>      search for buildfile downwards and use it" . $lSep;
 659          $msg .= $lSep;
 660          $msg .= "Report bugs to <dev@phing.tigris.org>".$lSep;
 661          print($msg);
 662      }
 663  
 664      function printVersion() {
 665          print(self::getPhingVersion()."\n");
 666      }
 667  
 668      function getPhingVersion() {
 669          $versionPath = self::getResourcePath("phing/etc/VERSION.TXT");
 670          if ($versionPath === null) {
 671              $versionPath = self::getResourcePath("etc/VERSION.TXT");
 672          }
 673          try { // try to read file
 674              $buffer = null;
 675              $file = new PhingFile($versionPath);
 676              $reader = new FileReader($file);
 677              $reader->readInto($buffer);
 678              $buffer = trim($buffer);
 679              //$buffer = "PHING version 1.0, Released 2002-??-??";
 680              $phingVersion = $buffer;
 681          } catch (IOException $iox) {
 682              print("Can't read version information file\n");
 683              throw new BuildException("Build failed");
 684          }        
 685          return $phingVersion;
 686      }
 687  
 688      /**  Print the project description, if any */
 689      function printDescription(Project $project) {
 690          if ($project->getDescription() !== null) {
 691              print($project->getDescription()."\n");
 692          }
 693      }
 694  
 695      /** Print out a list of all targets in the current buildfile */
 696      function printTargets($project) {
 697          // find the target with the longest name
 698          $maxLength = 0;
 699          $targets = $project->getTargets();
 700          $targetNames = array_keys($targets);
 701          $targetName = null;
 702          $targetDescription = null;
 703          $currentTarget = null;
 704  
 705          // split the targets in top-level and sub-targets depending
 706          // on the presence of a description
 707          
 708          $subNames = array();
 709          $topNameDescMap = array();
 710          
 711          foreach($targets as $currentTarget) {        
 712              $targetName = $currentTarget->getName();
 713              $targetDescription = $currentTarget->getDescription();            
 714              
 715              // subtargets are targets w/o descriptions
 716              if ($targetDescription === null) {
 717                  $subNames[] = $targetName;
 718              } else {
 719                  // topNames and topDescriptions are handled later
 720                  // here we store in hash map (for sorting purposes)
 721                  $topNameDescMap[$targetName] = $targetDescription;               
 722                  if (strlen($targetName) > $maxLength) {
 723                      $maxLength = strlen($targetName);
 724                  }
 725              }
 726          }
 727          
 728          // Sort the arrays
 729          sort($subNames); // sort array values, resetting keys (which are numeric)        
 730          ksort($topNameDescMap); // sort the keys (targetName) keeping key=>val associations
 731          
 732          $topNames = array_keys($topNameDescMap);
 733          $topDescriptions = array_values($topNameDescMap);
 734  
 735          $defaultTarget = $project->getDefaultTarget();
 736  
 737          if ($defaultTarget !== null && $defaultTarget !== "") {
 738              $defaultName = array();
 739              $defaultDesc = array();
 740              $defaultName[] = $defaultTarget;
 741  
 742              $indexOfDefDesc = array_search($defaultTarget, $topNames, true);
 743              if ($indexOfDefDesc !== false && $indexOfDefDesc >= 0) {
 744                  $defaultDesc = array();
 745                  $defaultDesc[] = $topDescriptions[$indexOfDefDesc];
 746              }
 747  
 748              $this->_printTargets($defaultName, $defaultDesc, "Default target:", $maxLength);
 749  
 750          }
 751          $this->_printTargets($topNames, $topDescriptions, "Main targets:", $maxLength);
 752          $this->_printTargets($subNames, null, "Subtargets:", 0);
 753      }    
 754  
 755      /**
 756       * Writes a formatted list of target names with an optional description.
 757       *
 758       * @param array $names The names to be printed.
 759       *              Must not be <code>null</code>.
 760       * @param array $descriptions The associated target descriptions.
 761       *                     May be <code>null</code>, in which case
 762       *                     no descriptions are displayed.
 763       *                     If non-<code>null</code>, this should have
 764       *                     as many elements as <code>names</code>.
 765       * @param string $heading The heading to display.
 766       *                Should not be <code>null</code>.
 767       * @param int $maxlen The maximum length of the names of the targets.
 768       *               If descriptions are given, they are padded to this
 769       *               position so they line up (so long as the names really
 770       *               <i>are</i> shorter than this).
 771       */
 772      private function _printTargets($names, $descriptions, $heading, $maxlen) {
 773          $lSep = self::getProperty("line.separator");
 774          $spaces = '  ';
 775          while (strlen($spaces) < $maxlen) {
 776              $spaces .= $spaces;
 777          }
 778          $msg = "";
 779          $msg .= $heading . $lSep;
 780          $msg .= str_repeat("-",79) . $lSep;
 781  
 782          $total = count($names);
 783          for($i=0; $i < $total; $i++) {
 784              $msg .= " ";
 785              $msg .= $names[$i];
 786              if (!empty($descriptions)) {
 787                  $msg .= substr($spaces, 0, $maxlen - strlen($names[$i]) + 2);
 788                  $msg .= $descriptions[$i];
 789              }
 790              $msg .= $lSep;
 791          }
 792          if ($total > 0) {
 793            print $msg . $lSep;
 794          } 
 795     }
 796     
 797     /**
 798      * Import a dot-path notation class path.
 799      * @param string $dotPath
 800      * @param mixed $classpath String or object supporting __toString()
 801      * @return string The unqualified classname (which can be instantiated).
 802      * @throws BuildException - if cannot find the specified file
 803      */
 804     public static function import($dotPath, $classpath = null) {
 805          
 806          // first check to see that the class specified hasn't already been included.
 807          // (this also handles case where this method is called w/ a classname rather than dotpath)
 808          $classname = StringHelper::unqualify($dotPath);
 809          if (class_exists($classname, false)) {
 810              return $classname;
 811          }
 812          
 813          $dotClassname = basename($dotPath);
 814          $dotClassnamePos = strlen($dotPath) - strlen($dotClassname);
 815          $classFile = strtr($dotClassname, '.', DIRECTORY_SEPARATOR) . ".php";
 816          $path = substr_replace($dotPath, $classFile, $dotClassnamePos);
 817          
 818          Phing::__import($path, $classpath);
 819          
 820          return $classname;
 821     }
 822  
 823     /**
 824      * Import a PHP file
 825      * @param string $path Path to the PHP file
 826      * @param mixed $classpath String or object supporting __toString()
 827      * @throws BuildException - if cannot find the specified file
 828      */
 829     public static function __import($path, $classpath = null) {
 830          
 831          if ($classpath) {
 832          
 833              // Apparently casting to (string) no longer invokes __toString() automatically.
 834              if (is_object($classpath)) {
 835                  $classpath = $classpath->__toString();
 836              }
 837              
 838              // classpaths are currently additive, but we also don't want to just
 839              // indiscriminantly prepand/append stuff to the include_path.  This means
 840              // we need to parse current incldue_path, and prepend any
 841              // specified classpath locations that are not already in the include_path.              
 842              //
 843              // NOTE:  the reason why we do it this way instead of just changing include_path
 844              // and then changing it back, is that in many cases applications (e.g. Propel) will
 845              // include/require class files from within method calls.  This means that not all
 846              // necessary files will be included in this import() call, and hence we can't
 847              // change the include_path back without breaking those apps.  While this method could
 848              // be more expensive than switching & switching back (not sure, but maybe), it makes it
 849              // possible to write far less expensive run-time applications (e.g. using Propel), which is
 850              // really where speed matters more.
 851              
 852              $curr_parts = explode(PATH_SEPARATOR, ini_get('include_path'));
 853              $add_parts = explode(PATH_SEPARATOR, $classpath);
 854              $new_parts = array_diff($add_parts, $curr_parts);
 855              if ($new_parts) {
 856                  if (self::getMsgOutputLevel() === PROJECT_MSG_DEBUG) {
 857                      print("Phing::import() prepending new include_path components: " . implode(PATH_SEPARATOR, $new_parts) . "\n");
 858                  }
 859                  ini_set('include_path', implode(PATH_SEPARATOR, array_merge($new_parts, $curr_parts)));
 860              }
 861          }
 862          
 863          $ret = include_once($path);        
 864          
 865          if ($ret === false) {
 866              $e = new BuildException("Error importing $path");
 867              if (self::getMsgOutputLevel() === PROJECT_MSG_DEBUG) {
 868                  // We can't log this because listeners belong
 869                  // to projects.  We'll just print it -- of course
 870                  // that isn't very compatible w/ other frontends (but
 871                  // there aren't any right now, so I'm not stressing)
 872                  print("Error importing $path\n");
 873                  print($e->getTraceAsString()."\n");
 874              }        
 875              throw $e;
 876          }
 877          
 878          return;
 879     }
 880     
 881     /**
 882      * Looks on include path for specified file.
 883      * @return string File found (null if no file found).
 884      */
 885     public static function getResourcePath($path) {
 886          
 887          if (self::$importPaths === null) {
 888              $paths = ini_get("include_path");            
 889              self::$importPaths = explode(PATH_SEPARATOR, ini_get("include_path"));
 890          }
 891          
 892          $path = str_replace('\\', DIRECTORY_SEPARATOR, $path);
 893          $path = str_replace('/', DIRECTORY_SEPARATOR, $path);
 894  
 895          foreach (self::$importPaths as $prefix) {
 896              $foo_path = $prefix . DIRECTORY_SEPARATOR . $path;
 897              if (file_exists($foo_path)) {
 898                  return $foo_path;
 899              }
 900          }
 901          
 902          // Check for the property phing.home
 903          $home_dir = self::getProperty('phing.home');
 904          
 905          if ($home_dir)
 906          {
 907              $home_path = $home_dir . DIRECTORY_SEPARATOR . $path;
 908              
 909              if (file_exists($home_path))
 910              {
 911                  return $home_path;
 912              }
 913          }
 914          
 915          // If we are using this via PEAR then check for the file in the data dir
 916          // This is a bit of a hack, but works better than previous solution of assuming
 917          // data_dir is on the include_path.
 918          $data_dir = '@DATA-DIR@';
 919          if ($data_dir{0} != '@') { // if we're using PEAR then the @ DATA-DIR @ token will have been substituted.
 920              $data_path = $data_dir . DIRECTORY_SEPARATOR . $path;
 921              if (file_exists($data_path)) {
 922                     return $data_path;
 923                 }
 924          }
 925          
 926          return null;
 927     }
 928     
 929     // -------------------------------------------------------------------------------------------
 930     // System-wide methods (moved from System class, which had namespace conflicts w/ PEAR System)
 931     // -------------------------------------------------------------------------------------------
 932               
 933      /**
 934       * Set System constants which can be retrieved by calling Phing::getProperty($propName).
 935       * @return void
 936       */
 937      private static function setSystemConstants() {
 938  
 939          /*
 940           * PHP_OS returns on
 941           *   WindowsNT4.0sp6  => WINNT
 942           *   Windows2000      => WINNT
 943           *   Windows ME       => WIN32
 944           *   Windows 98SE     => WIN32
 945           *   FreeBSD 4.5p7    => FreeBSD
 946           *   Redhat Linux     => Linux
 947           *   Mac OS X          => Darwin
 948           */
 949          self::setProperty('host.os', PHP_OS);
 950          
 951          // this is used by some tasks too
 952          self::setProperty('os.name', PHP_OS);
 953          
 954          // it's still possible this won't be defined,
 955          // e.g. if Phing is being included in another app w/o
 956          // using the phing.php script.
 957          if (!defined('PHP_CLASSPATH')) {
 958              define('PHP_CLASSPATH', get_include_path());
 959          }
 960          
 961          self::setProperty('php.classpath', PHP_CLASSPATH);
 962  
 963          // try to determine the host filesystem and set system property
 964          // used by Fileself::getFileSystem to instantiate the correct
 965          // abstraction layer
 966  
 967          switch (strtoupper(PHP_OS)) {
 968              case 'WINNT':
 969                  self::setProperty('host.fstype', 'WINNT');
 970                  break;
 971              case 'WIN32':
 972                  self::setProperty('host.fstype', 'WIN32');
 973                  break;
 974              default:
 975                  self::setProperty('host.fstype', 'UNIX');
 976                  break;
 977          }
 978  
 979          self::setProperty('php.version', PHP_VERSION);
 980          self::setProperty('user.home', getenv('HOME'));
 981          self::setProperty('application.startdir', getcwd());
 982          self::setProperty('line.separator', "\n");
 983  
 984          // try to detect machine dependent information
 985          $sysInfo = array();
 986          if (strtoupper(substr(PHP_OS, 0, 3)) !== 'WIN' && function_exists("posix_uname")) {
 987                $sysInfo = posix_uname();
 988          } else {
 989                $sysInfo['nodename'] = php_uname('n');
 990                $sysInfo['machine']= php_uname('m') ;
 991                //this is a not so ideal substition, but maybe better than nothing
 992                $sysInfo['domain'] = isset($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] : "unknown";
 993                $sysInfo['release'] = php_uname('r');
 994                $sysInfo['version'] = php_uname('v');
 995          }              
 996       
 997  
 998          self::setProperty("host.name", isset($sysInfo['nodename']) ? $sysInfo['nodename'] : "unknown");
 999          self::setProperty("host.arch", isset($sysInfo['machine']) ? $sysInfo['machine'] : "unknown");
1000          self::setProperty("host.domain",isset($sysInfo['domain']) ? $sysInfo['domain'] : "unknown");
1001          self::setProperty("host.os.release", isset($sysInfo['release']) ? $sysInfo['release'] : "unknown");
1002          self::setProperty("host.os.version", isset($sysInfo['version']) ? $sysInfo['version'] : "unknown");
1003          unset($sysInfo);
1004      }
1005      
1006      /**
1007       * This gets a property that was set via command line or otherwise passed into Phing.
1008       * "Defined" in this case means "externally defined".  The reason this method exists is to
1009       * provide a public means of accessing commandline properties for (e.g.) logger or listener 
1010       * scripts.  E.g. to specify which logfile to use, PearLogger needs to be able to access
1011       * the pear.log.name property.
1012       * 
1013       * @param string $name
1014       * @return string value of found property (or null, if none found).
1015       */
1016      public static function getDefinedProperty($name) {
1017          return self::$definedProps->getProperty($name);
1018      }
1019      
1020      /**
1021       * This sets a property that was set via command line or otherwise passed into Phing.
1022       * 
1023       * @param string $name
1024       * @return string value of found property (or null, if none found).
1025       */
1026      public static function setDefinedProperty($name, $value) {
1027          return self::$definedProps->setProperty($name, $value);
1028      }
1029      
1030      /**
1031       * Returns property value for a System property.
1032       * System properties are "global" properties like line.separator,
1033       * and user.dir.  Many of these correspond to similar properties in Java
1034       * or Ant.
1035       * 
1036       * @param string $paramName
1037       * @return string Value of found property (or null, if none found).
1038       */
1039      public static function getProperty($propName) {
1040      
1041          // some properties are detemined on each access
1042          // some are cached, see below
1043  
1044          // default is the cached value:
1045          $val = isset(self::$properties[$propName]) ? self::$properties[$propName] : null;
1046      
1047          // special exceptions        
1048          switch($propName) {
1049              case 'user.dir':
1050                  $val = getcwd();
1051              break;            
1052          }
1053          
1054          return $val;
1055      }
1056  
1057      /** Retuns reference to all properties*/
1058      public static function &getProperties() {
1059          return self::$properties;
1060      }
1061  
1062      public static function setProperty($propName, $propValue) {    
1063          $propName = (string) $propName;
1064          $oldValue = self::getProperty($propName);
1065          self::$properties[$propName] = $propValue;
1066          return $oldValue;
1067      }
1068      
1069      public static function currentTimeMillis() {
1070          list($usec, $sec) = explode(" ",microtime());
1071          return ((float)$usec + (float)$sec);
1072      }
1073      
1074      /**
1075       * Sets the include path based on PHP_CLASSPATH constant (set in phing.php).
1076       * @return void
1077       */
1078      private static function setIncludePaths() {
1079          $success = false;
1080          
1081          if (defined('PHP_CLASSPATH')) {
1082              $success = ini_set('include_path', PHP_CLASSPATH);
1083          } else {
1084              // don't do anything, just assume that include_path has been properly set.
1085              $success = true;
1086          }
1087          
1088          if ($success === false) {
1089              print("SYSTEM FAILURE: Could not set PHP include path\n");
1090              self::halt(-1);
1091          }
1092      }
1093      
1094      /**
1095       * Sets PHP INI values that Phing needs.
1096       * @return void
1097       */
1098      private static function setIni() {
1099          error_reporting(E_ALL);
1100          set_time_limit(0);
1101          ini_set('magic_quotes_gpc', 'off');
1102          ini_set('short_open_tag', 'off');
1103          ini_set('default_charset', 'iso-8859-1');
1104          ini_set('register_globals', 'off');
1105          ini_set('allow_call_time_pass_reference', 'on');
1106          
1107          // should return memory limit in MB  
1108          $mem_limit = (int) ini_get('memory_limit');
1109          if ($mem_limit < 32) {
1110              ini_set('memory_limit', '32M'); // nore: this may need to be higher for many projects
1111          }        
1112      }
1113  
1114      /**
1115       * Returns reference to Timer object.
1116       * @return Timer
1117       */
1118      public static function getTimer() {
1119          if (self::$timer === null) {
1120              include_once 'phing/system/util/Timer.php';
1121              self::$timer= new Timer();
1122          }
1123          return self::$timer;
1124      }
1125          
1126       /**
1127       * Start up Phing.
1128       * Sets up the Phing environment -- does NOT initiate the build process.
1129       * @return void
1130       */
1131      public static function startup() {
1132         
1133          register_shutdown_function(array('Phing', 'shutdown'));
1134  
1135          // some init stuff
1136          self::getTimer()->start();
1137  
1138          self::setSystemConstants();
1139          self::setIncludePaths();
1140          self::setIni();
1141      }
1142      
1143      /**
1144       * Halts the system.
1145       * @see shutdown()
1146       */
1147      public static function halt($code=0) {        
1148          self::shutdown($code);        
1149      }
1150  
1151      /**
1152       * Stops timers & exits.
1153       * @return void
1154       */
1155      public static function shutdown($exitcode = 0) {
1156          //print("[AUTOMATIC SYSTEM SHUTDOWN]\n");
1157          self::getTimer()->stop();
1158          exit($exitcode); // final point where everything stops
1159      }
1160      
1161  }


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