Changeset 280

Show
Ignore:
Timestamp:
11/01/07 20:18:43 (1 year ago)
Author:
hans
Message:

Adding new interface for BuildLoggers that require explicit streams to be set and modified DefaultLogger to extend this new interface. (#174)

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • branches/2.3/classes/phing/Phing.php

    r230 r280  
    1919 * <http://phing.info>. 
    2020 */ 
    21   
     21 
    2222require_once 'phing/Project.php'; 
    2323require_once 'phing/ProjectComponent.php'; 
     
    4848 
    4949/** 
    50  * Entry point into Phing.  This class handles the full lifecycle of a build -- from  
     50 * Entry point into Phing.  This class handles the full lifecycle of a build -- from 
    5151 * parsing & handling commandline arguments to assembling the project to shutting down 
    5252 * and cleaning up in the end. 
     
    6363class Phing { 
    6464 
    65     /** The default build file name */ 
    66     const DEFAULT_BUILD_FILENAME = "build.xml"; 
    67          
    68     /** Our current message output status. Follows Project::MSG_XXX */ 
    69     private static $msgOutputLevel = Project::MSG_INFO; 
    70  
    71     /** PhingFile that we are using for configuration */ 
    72     private $buildFile = null; 
    73  
    74     /** The build targets */ 
    75     private $targets = array(); 
    76  
    77     /** 
    78     * Set of properties that are passed in from commandline or invoking code. 
    79     * @var Properties 
    80     */ 
    81     private static $definedProps; 
    82  
    83     /** Names of classes to add as listeners to project */ 
    84     private $listeners = array(); 
    85  
    86     private $loggerClassname = null; 
    87  
    88     /** The class to handle input (can be only one). */ 
    89     private $inputHandlerClassname; 
    90      
    91     /** Indicates if this phing should be run */ 
    92     private $readyToRun = false; 
    93  
    94     /** Indicates we should only parse and display the project help information */ 
    95     private $projectHelp = false; 
    96          
    97     /** Used by utility function getResourcePath() */ 
    98     private static $importPaths; 
    99      
    100     /** System-wide static properties (moved from System) */ 
    101     private static $properties = array(); 
    102      
    103     /** Static system timer. */ 
    104     private static $timer; 
    105      
     65       /** The default build file name */ 
     66       const DEFAULT_BUILD_FILENAME = "build.xml"; 
     67 
     68       /** Our current message output status. Follows Project::MSG_XXX */ 
     69       private static $msgOutputLevel = Project::MSG_INFO; 
     70 
     71       /** PhingFile that we are using for configuration */ 
     72       private $buildFile = null; 
     73 
     74       /** The build targets */ 
     75       private $targets = array(); 
     76 
     77       /** 
     78        * Set of properties that are passed in from commandline or invoking code. 
     79        * @var Properties 
     80        */ 
     81       private static $definedProps; 
     82 
     83       /** Names of classes to add as listeners to project */ 
     84       private $listeners = array(); 
     85 
     86       private $loggerClassname = null; 
     87 
     88       /** The class to handle input (can be only one). */ 
     89       private $inputHandlerClassname; 
     90 
     91       /** Indicates if this phing should be run */ 
     92       private $readyToRun = false; 
     93 
     94       /** Indicates we should only parse and display the project help information */ 
     95       private $projectHelp = false; 
     96 
     97       /** Used by utility function getResourcePath() */ 
     98       private static $importPaths; 
     99 
     100       /** System-wide static properties (moved from System) */ 
     101       private static $properties = array(); 
     102 
     103       /** Static system timer. */ 
     104       private static $timer; 
     105 
    106106        /** The current Project */ 
    107107        private static $currentProject; 
    108          
     108 
    109109        /** Whether to capture PHP errors to buffer. */ 
    110110        private static $phpErrorCapture = false; 
    111          
     111 
    112112        /** Array of captured PHP errors */ 
    113113        private static $capturedPhpErrors = array(); 
     
    117117         */ 
    118118        private static $out; 
    119          
     119 
    120120        /** 
    121121         * @var OutputStream Stream for error output. 
    122122         */ 
    123123        private static $err; 
    124          
     124 
    125125        /** 
    126126         * @var boolean Whether we are using a logfile. 
    127127         */ 
    128128        private static $isLogFileUsed = false; 
    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                 self::handleLogfile(); // clean up log file before attempting to print message 
    150             $m->printMessage($exc); 
    151             self::halt(-1); // Parameter error 
    152         } 
    153  
    154         if ($additionalUserProperties !== null) { 
    155             $keys = $m->additionalUserProperties->keys(); 
    156             while(count($keys)) { 
    157                 $key = array_shift($keys); 
    158                 $property = $m->additionalUserProperties->getProperty($key); 
    159                 $m->setDefinedProperty($key, $property); 
    160             } 
    161         } 
    162  
    163         try { 
    164             $m->runBuild(); 
    165         } catch(Exception $exc) { 
    166                 self::handleLogfile(); 
    167             self::halt(1); // Errors occured 
    168         } 
    169          
    170         // everything fine, shutdown 
     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                        self::handleLogfile(); // clean up log file before attempting to print message 
     150                        $m->printMessage($exc); 
     151                        self::halt(-1); // Parameter error 
     152                } 
     153 
     154                if ($additionalUserProperties !== null) { 
     155                        $keys = $m->additionalUserProperties->keys(); 
     156                        while(count($keys)) { 
     157                                $key = array_shift($keys); 
     158                                $property = $m->additionalUserProperties->getProperty($key); 
     159                                $m->setDefinedProperty($key, $property); 
     160                        } 
     161                } 
     162 
     163                try { 
     164                        $m->runBuild(); 
     165                } catch(Exception $exc) { 
     166                        if (self::$msgOutputLevel >= Project::MSG_VERBOSE) { 
     167                                self::$out->write($exc->__toString() . PHP_EOL); 
     168                        } else { 
     169                                self::$out->write($exc->getMessage() . PHP_EOL); 
     170                        } 
     171                        self::handleLogfile(); 
     172                        self::halt(1); // Errors occured 
     173                } 
     174 
     175                // everything fine, shutdown 
    171176                self::handleLogfile(); 
    172         self::halt(0); 
    173    
    174  
    175     /** 
    176     * Prints the message of the Exception if it's not null. 
    177     * @param Exception $t 
    178     */ 
    179     public static function printMessage(Exception $t) { 
    180               if (self::getMsgOutputLevel() <= Project::MSG_DEBUG) { 
    181                       self::$err->write($t->__toString()); 
    182               } else { 
    183                       self::$err->write($t->getMessage()); 
    184               } 
    185    
    186      
    187     /** 
    188     * Sets the stdout and stderr streams if they are not already set. 
    189     */ 
    190     private static function initializeOutputStreams() { 
    191         if (self::$out === null) { 
    192               self::$out = new OutputStream(fopen("php://stdout", "w")); 
    193        
    194         if (self::$err === null) { 
    195               self::$err = new OutputStream(fopen("php://stderr", "w")); 
    196        
    197    
    198      
    199     /** 
    200     * Sets the stream to use for standard (non-error) output. 
    201     * @param OutputStream $stream The stream to use for standard output. 
    202     */ 
    203     public static function setOutputStream(OutputStream $stream) { 
    204       self::$out = $stream; 
    205    
    206      
    207     /** 
    208     * Gets the stream to use for standard (non-error) output. 
    209     * @return OutputStream 
    210     */ 
    211       public static function getOutputStream() { 
    212               return self::$out; 
    213       } 
    214      
    215     /** 
    216     * Sets the stream to use for error output. 
    217     * @param OutputStream $stream The stream to use for error output. 
    218     */ 
    219     public static function setErrorStream(OutputStream $stream) { 
    220       self::$err = $stream; 
    221    
    222      
    223     /** 
    224     * Gets the stream to use for error output. 
    225     * @return OutputStream 
    226     */ 
    227       public static function getErrorStream() { 
    228               return self::$err; 
    229       } 
    230      
    231     /** 
    232     * Close logfiles, if we have been writing to them. 
    233    
    234     * @since Phing 2.3.0 
    235     */ 
    236     private static function handleLogfile() { 
    237         if (self::$isLogFileUsed) { 
    238               self::$err->close(); 
    239               self::$out->close(); 
    240        
    241    
    242      
    243     /** 
    244     * Making output level a static property so that this property 
    245     * can be accessed by other parts of the system, enabling 
    246     * us to display more information -- e.g. backtraces -- for "debug" level. 
    247     * @return int 
    248     */ 
    249     public static function getMsgOutputLevel() { 
    250         return self::$msgOutputLevel; 
    251     }         
    252      
    253     /** 
    254     * Command line entry point. This method kicks off the building 
    255     * of a project object and executes a build using either a given 
    256     * target or the default target. 
    257    
    258     * @param array $args Command line args. 
    259     * @return void 
    260     */ 
    261     public static function fire($args) { 
    262         self::start($args, null); 
    263    
    264      
    265     /** 
    266     * Setup/initialize Phing environment from commandline args. 
    267     * @param array $args commandline args passed to phing shell. 
    268     * @return void 
    269     */ 
    270     public function execute($args) { 
    271      
    272         self::$definedProps = new Properties(); 
    273         $this->searchForThis = null; 
    274  
    275         // cycle through given args 
    276         for ($i = 0, $argcount = count($args); $i < $argcount; ++$i) {  
    277                             // ++$i intentional here, as first param is script name 
    278             $arg = $args[$i]; 
    279  
    280             if ($arg == "-help" || $arg == "-h") { 
    281                 $this->printUsage(); 
    282                 return; 
    283             } elseif ($arg == "-version" || $arg == "-v") { 
    284                 $this->printVersion(); 
    285                 return; 
    286             } elseif ($arg == "-quiet" || $arg == "-q") { 
    287                 self::$msgOutputLevel = Project::MSG_WARN; 
    288             } elseif ($arg == "-verbose") { 
    289                 $this->printVersion(); 
    290                 self::$msgOutputLevel = Project::MSG_VERBOSE; 
    291             } elseif ($arg == "-debug") { 
    292                 $this->printVersion(); 
    293                 self::$msgOutputLevel = Project::MSG_DEBUG; 
    294             } elseif ($arg == "-logfile") { 
    295                 try { 
    296                       // see: http://phing.info/trac/ticket/65 
    297                     if (!isset($args[$i+1])) { 
    298                         $msg = "You must specify a log file when using the -logfile argument\n"; 
    299                         throw new BuildException($msg); 
    300                     } else { 
    301                         $logFile = new PhingFile($args[++$i]); 
    302                         $out = new FileOutputStream($logFile); // overwrite 
    303                         self::setOutputStream($out); 
    304                         self::setErrorStream($out); 
    305                         self::$isLogFileUsed = true; 
    306                    
    307                 } catch (IOException $ioe) { 
    308                     $msg = "Cannot write on the specified log file. Make sure the path exists and you have write permissions."; 
    309                     throw new BuildException($msg, $ioe); 
    310                
    311             } elseif ($arg == "-buildfile" || $arg == "-file" || $arg == "-f") { 
    312                 if (!isset($args[$i+1])) { 
    313                     $msg = "You must specify a buildfile when using the -buildfile argument."; 
    314                     throw new BuildException($msg); 
    315                 } else { 
    316                     $this->buildFile = new PhingFile($args[++$i]); 
    317                
    318             } elseif ($arg == "-listener") { 
    319                 if (!isset($args[$i+1])) { 
    320                     $msg = "You must specify a listener class when using the -listener argument"; 
    321                     throw new BuildException($msg); 
    322                 } else { 
    323                     $this->listeners[] = $args[++$i]; 
    324                
    325             } elseif (StringHelper::startsWith("-D", $arg)) { 
    326                 $name = substr($arg, 2); 
    327                 $value = null; 
    328                 $posEq = strpos($name, "="); 
    329                 if ($posEq !== false) { 
    330                     $value = substr($name, $posEq+1); 
    331                     $name  = substr($name, 0, $posEq); 
    332                 } elseif ($i < count($args)-1) { 
    333                     $value = $args[++$i]; 
    334                
    335                 self::$definedProps->setProperty($name, $value); 
    336             } elseif ($arg == "-logger") { 
    337                 if (!isset($args[$i+1])) { 
    338                     $msg = "You must specify a classname when using the -logger argument"; 
    339                     throw new BuildException($msg); 
    340                 } else { 
    341                     $this->loggerClassname = $args[++$i]; 
    342                
    343             } elseif ($arg == "-inputhandler") { 
    344                 if ($this->inputHandlerClassname !== null) { 
    345                     throw new BuildException("Only one input handler class may be specified."); 
    346                
    347                 if (!isset($args[$i+1])) { 
    348                     $msg = "You must specify a classname when using the -inputhandler argument"; 
    349                     throw new BuildException($msg); 
    350                 } else { 
    351                     $this->inputHandlerClassname = $args[++$i]; 
    352                
    353             } elseif ($arg == "-projecthelp" || $arg == "-targets" || $arg == "-list" || $arg == "-l" || $arg == "-p") { 
    354                 // set the flag to display the targets and quit 
    355                 $this->projectHelp = true; 
    356             } elseif ($arg == "-find") { 
    357                 // eat up next arg if present, default to build.xml 
    358                 if ($i < count($args)-1) { 
    359                     $this->searchForThis = $args[++$i]; 
    360                 } else { 
    361                     $this->searchForThis = self::DEFAULT_BUILD_FILENAME; 
    362                
    363             } elseif (substr($arg,0,1) == "-") { 
    364                 // we don't have any more args 
     177               self::halt(0); 
     178       
     179 
     180       /** 
     181        * Prints the message of the Exception if it's not null. 
     182        * @param Exception $t 
     183        */ 
     184       public static function printMessage(Exception $t) { 
     185              if (self::getMsgOutputLevel() <= Project::MSG_DEBUG) { 
     186                      self::$err->write($t->__toString()); 
     187              } else { 
     188                      self::$err->write($t->getMessage()); 
     189              } 
     190       
     191 
     192       /** 
     193        * Sets the stdout and stderr streams if they are not already set. 
     194        */ 
     195       private static function initializeOutputStreams() { 
     196               if (self::$out === null) { 
     197                      self::$out = new OutputStream(fopen("php://stdout", "w")); 
     198               
     199               if (self::$err === null) { 
     200                      self::$err = new OutputStream(fopen("php://stderr", "w")); 
     201               
     202       
     203 
     204       /** 
     205        * Sets the stream to use for standard (non-error) output. 
     206        * @param OutputStream $stream The stream to use for standard output. 
     207        */ 
     208       public static function setOutputStream(OutputStream $stream) { 
     209              self::$out = $stream; 
     210       
     211 
     212       /** 
     213        * Gets the stream to use for standard (non-error) output. 
     214        * @return OutputStream 
     215        */ 
     216      public static function getOutputStream() { 
     217              return self::$out; 
     218      } 
     219 
     220       /** 
     221        * Sets the stream to use for error output. 
     222        * @param OutputStream $stream The stream to use for error output. 
     223        */ 
     224       public static function setErrorStream(OutputStream $stream) { 
     225              self::$err = $stream; 
     226       
     227 
     228       /** 
     229        * Gets the stream to use for error output. 
     230        * @return OutputStream 
     231        */ 
     232      public static function getErrorStream() { 
     233              return self::$err; 
     234      } 
     235 
     236       /** 
     237        * Close logfiles, if we have been writing to them. 
     238       
     239        * @since Phing 2.3.0 
     240        */ 
     241       private static function handleLogfile() { 
     242               if (self::$isLogFileUsed) { 
     243                      self::$err->close(); 
     244                      self::$out->close(); 
     245               
     246       
     247 
     248       /** 
     249        * Making output level a static property so that this property 
     250        * can be accessed by other parts of the system, enabling 
     251        * us to display more information -- e.g. backtraces -- for "debug" level. 
     252        * @return int 
     253        */ 
     254       public static function getMsgOutputLevel() { 
     255               return self::$msgOutputLevel; 
     256        } 
     257 
     258       /** 
     259        * Command line entry point. This method kicks off the building 
     260        * of a project object and executes a build using either a given 
     261        * target or the default target. 
     262       
     263        * @param array $args Command line args. 
     264        * @return void 
     265        */ 
     266       public static function fire($args) { 
     267               self::start($args, null); 
     268       
     269 
     270       /** 
     271        * Setup/initialize Phing environment from commandline args. 
     272        * @param array $args commandline args passed to phing shell. 
     273        * @return void 
     274        */ 
     275       public function execute($args) { 
     276 
     277               self::$definedProps = new Properties(); 
     278               $this->searchForThis = null; 
     279 
     280               // cycle through given args 
     281                for ($i = 0, $argcount = count($args); $i < $argcount; ++$i) { 
     282                       // ++$i intentional here, as first param is script name 
     283                       $arg = $args[$i]; 
     284 
     285                       if ($arg == "-help" || $arg == "-h") { 
     286                               $this->printUsage(); 
     287                               return; 
     288                       } elseif ($arg == "-version" || $arg == "-v") { 
     289                               $this->printVersion(); 
     290                               return; 
     291                       } elseif ($arg == "-quiet" || $arg == "-q") { 
     292                               self::$msgOutputLevel = Project::MSG_WARN; 
     293                       } elseif ($arg == "-verbose") { 
     294                               $this->printVersion(); 
     295                               self::$msgOutputLevel = Project::MSG_VERBOSE; 
     296                       } elseif ($arg == "-debug") { 
     297                               $this->printVersion(); 
     298                               self::$msgOutputLevel = Project::MSG_DEBUG; 
     299                       } elseif ($arg == "-logfile") { 
     300                               try { 
     301                                      // see: http://phing.info/trac/ticket/65 
     302                                       if (!isset($args[$i+1])) { 
     303                                               $msg = "You must specify a log file when using the -logfile argument\n"; 
     304                                               throw new BuildException($msg); 
     305                                       } else { 
     306                                               $logFile = new PhingFile($args[++$i]); 
     307                                               $out = new FileOutputStream($logFile); // overwrite 
     308                                               self::setOutputStream($out); 
     309                                               self::setErrorStream($out); 
     310                                               self::$isLogFileUsed = true; 
     311                                       
     312                               } catch (IOException $ioe) { 
     313                                       $msg = "Cannot write on the specified log file. Make sure the path exists and you have write permissions."; 
     314                                       throw new BuildException($msg, $ioe); 
     315                               
     316                       } elseif ($arg == "-buildfile" || $arg == "-file" || $arg == "-f") { 
     317                               if (!isset($args[$i+1])) { 
     318                                       $msg = "You must specify a buildfile when using the -buildfile argument."; 
     319                                       throw new BuildException($msg); 
     320                               } else { 
     321                                       $this->buildFile = new PhingFile($args[++$i]); 
     322                               
     323                       } elseif ($arg == "-listener") { 
     324                               if (!isset($args[$i+1])) { 
     325                                       $msg = "You must specify a listener class when using the -listener argument"; 
     326                                       throw new BuildException($msg); 
     327                               } else { 
     328                                       $this->listeners[] = $args[++$i]; 
     329                               
     330                       } elseif (StringHelper::startsWith("-D", $arg)) { 
     331                               $name = substr($arg, 2); 
     332                               $value = null; 
     333                               $posEq = strpos($name, "="); 
     334                               if ($posEq !== false) { 
     335                                       $value = substr($name, $posEq+1); 
     336                                       $name  = substr($name, 0, $posEq); 
     337                               } elseif ($i < count($args)-1) { 
     338                                       $value = $args[++$i]; 
     339                               
     340                               self::$definedProps->setProperty($name, $value); 
     341                       } elseif ($arg == "-logger") { 
     342                               if (!isset($args[$i+1])) { 
     343                                       $msg = "You must specify a classname when using the -logger argument"; 
     344                                       throw new BuildException($msg); 
     345                               } else { 
     346                                       $this->loggerClassname = $args[++$i]; 
     347                               
     348                       } elseif ($arg == "-inputhandler") { 
     349                               if ($this->inputHandlerClassname !== null) { 
     350                                       throw new BuildException("Only one input handler class may be specified."); 
     351                               
     352                               if (!isset($args[$i+1])) { 
     353                                       $msg = "You must specify a classname when using the -inputhandler argument"; 
     354                                       throw new BuildException($msg); 
     355                               } else { 
     356                                       $this->inputHandlerClassname = $args[++$i]; 
     357                               
     358                       } elseif ($arg == "-projecthelp" || $arg == "-targets" || $arg == "-list" || $arg == "-l" || $arg == "-p") { 
     359                               // set the flag to display the targets and quit 
     360                               $this->projectHelp = true; 
     361                       } elseif ($arg == "-find") { 
     362                               // eat up next arg if present, default to build.xml 
     363                               if ($i < count($args)-1) { 
     364                                       $this->searchForThis = $args[++$i]; 
     365                               } else { 
     366                                       $this->searchForThis = self::DEFAULT_BUILD_FILENAME; 
     367                               
     368                       } elseif (substr($arg,0,1) == "-") { 
     369                               // we don't have any more args 
    365370                                self::$err->write("Unknown argument: $arg"); 
    366                 self::printUsage(); 
    367                 return; 
    368             } else { 
    369                 // if it's no other arg, it may be the target 
    370                 array_push($this->targets, $arg); 
    371             } 
    372         } 
    373  
    374         // if buildFile was not specified on the command line, 
    375         if ($this->buildFile === null) { 
    376             // but -find then search for it 
    377             if ($this->searchForThis !== null) { 
    378                 $this->buildFile = $this->_findBuildFile(self::getProperty("user.dir"), $this->searchForThis); 
    379             } else { 
    380                 $this->buildFile = new PhingFile(self::DEFAULT_BUILD_FILENAME); 
    381             } 
    382         } 
    383         // make sure buildfile exists 
    384         if (!$this->buildFile->exists()) { 
    385             throw new BuildException("Buildfile: " . $this->buildFile->__toString() . " does not exist!"); 
    386         } 
    387  
    388         // make sure it's not a directory 
    389         if ($this->buildFile->isDirectory()) {    
    390             throw new BuildException("Buildfile: " . $this->buildFile->__toString() . " is a dir!"); 
    391         } 
    392  
    393         $this->readyToRun = true; 
    394     } 
    395  
    396     /** 
    397      * Helper to get the parent file for a given file. 
    398      * 
    399      * @param PhingFile $file 
    400      * @return PhingFile Parent file or null if none 
    401      */ 
    402     private function _getParentFile(PhingFile $file) { 
    403         $filename = $file->getAbsolutePath(); 
    404         $file     = new PhingFile($filename); 
    405         $filename = $file->getParent(); 
    406  
    407         if ($filename !== null && self::$msgOutputLevel >= Project::MSG_VERBOSE) { 
    408                 self::$out->write("Searching in $filename" . PHP_EOL); 
    409         } 
    410  
    411         return ($filename === null) ? null : new PhingFile($filename); 
    412     } 
    413  
    414     /** 
    415      * Search parent directories for the build file. 
    416      * 
    417      * Takes the given target as a suffix to append to each 
    418      * parent directory in search of a build file.  Once the 
    419      * root of the file-system has been reached an exception 
    420      * is thrown. 
    421      *  
    422      * @param string $start Start file path. 
    423      * @param string $suffix Suffix filename to look for in parents. 
    424      * @return PhingFile A handle to the build file 
    425      * 
    426      * @throws BuildException    Failed to locate a build file 
    427      */ 
    428     private function _findBuildFile($start, $suffix) { 
    429         if (self::$msgOutputLevel >= Project::MSG_INFO) { 
    430                 self::$out->write("Searching for $suffix ..." . PHP_EOL); 
    431         } 
    432         $startf = new PhingFile($start); 
    433         $parent = new PhingFile($startf->getAbsolutePath()); 
    434         $file   = new PhingFile($parent, $suffix); 
    435  
    436         // check if the target file exists in the current directory 
    437         while (!$file->exists()) { 
    438             // change to parent directory 
    439             $parent = $this->_getParentFile($parent); 
    440  
    441             // if parent is null, then we are at the root of the fs, 
    442             // complain that we can't find the build file. 
    443             if ($parent === null) { 
    444                 throw new BuildException("Could not locate a build file!"); 
    445             } 
    446             // refresh our file handle 
    447             $file = new PhingFile($parent, $suffix); 
    448         } 
    449         return $file; 
    450     } 
    451  
    452     /** 
    453      * Executes the build. 
    454      * @return void 
    455      */ 
    456     function runBuild() { 
    457  
    458         if (!$this->readyToRun) { 
    459             return; 
    460         } 
    461          
    462         $project = new Project(); 
    463                  
     371                                self::printUsage(); 
     372                                return; 
     373                        } else { 
     374                                // if it's no other arg, it may be the target 
     375                                array_push($this->targets, $arg); 
     376                        } 
     377                } 
     378 
     379                // if buildFile was not specified on the command line, 
     380                if ($this->buildFile === null) { 
     381                        // but -find then search for it 
     382                        if ($this->searchForThis !== null) { 
     383                                $this->buildFile = $this->_findBuildFile(self::getProperty("user.dir"), $this->searchForThis); 
     384                        } else { 
     385                                $this->buildFile = new PhingFile(self::DEFAULT_BUILD_FILENAME); 
     386                        } 
     387                } 
     388                // make sure buildfile exists 
     389                if (!$this->buildFile->exists()) { 
     390                        throw new BuildException("Buildfile: " . $this->buildFile->__toString() . " does not exist!"); 
     391                } 
     392 
     393                // make sure it's not a directory 
     394                if ($this->buildFile->isDirectory()) { 
     395                        throw new BuildException("Buildfile: " . $this->buildFile->__toString() . " is a dir!"); 
     396                } 
     397 
     398                $this->readyToRun = true; 
     399        } 
     400 
     401        /** 
     402         * Helper to get the parent file for a given file. 
     403         * 
     404         * @param PhingFile $file 
     405         * @return PhingFile Parent file or null if none 
     406         */ 
     407        private function _getParentFile(PhingFile $file) { 
     408                $filename = $file->getAbsolutePath(); 
     409                $file     = new PhingFile($filename); 
     410                $filename = $file->getParent(); 
     411                return ($filename === null) ? null : new PhingFile($filename); 
     412        } 
     413 
     414        /** 
     415         * Search parent directories for the build file. 
     416         * 
     417         * Takes the given target as a suffix to append to each 
     418         * parent directory in search of a build file.  Once the 
     419         * root of the file-system has been reached an exception 
     420         * is thrown. 
     421         * 
     422         * @param string $start Start file path. 
     423         * @param string $suffix Suffix filename to look for in parents. 
     424         * @return PhingFile A handle to the build file 
     425         * 
     426         * @throws BuildException    Failed to locate a build file 
     427         */ 
     428        private function _findBuildFile($start, $suffix) { 
     429                $startf = new PhingFile($start); 
     430                $parent = new PhingFile($startf->getAbsolutePath()); 
     431                $file   = new PhingFile($parent, $suffix); 
     432 
     433                // check if the target file exists in the current directory 
     434                while (!$file->exists()) { 
     435                        // change to parent directory 
     436                        $parent = $this->_getParentFile($parent); 
     437 
     438                        // if parent is null, then we are at the root of the fs, 
     439                        // complain that we can't find the build file. 
     440                        if ($parent === null) { 
     441                                throw new BuildException("Could not locate a build file!"); 
     442                        } 
     443                        // refresh our file handle 
     444                        $file = new PhingFile($parent, $suffix); 
     445                } 
     446                return $file; 
     447        } 
     448 
     449        /** 
     450         * Executes the build. 
     451         * @return void 
     452         */ 
     453        function runBuild() { 
     454 
     455                if (!$this->readyToRun) { 
     456                        return; 
     457                } 
     458 
     459                $project = new Project(); 
     460 
    464461                self::setCurrentProject($project); 
    465462                set_error_handler(array('Phing', 'handlePhpError')); 
    466                  
    467         $error = null; 
    468  
    469         $this->addBuildListeners($project); 
    470         $this->addInputHandler($project); 
    471          
    472         // set this right away, so that it can be used in logging. 
    473         $project->setUserProperty("phing.file", $this->buildFile->getAbsolutePath()); 
    474  
    475         try { 
    476             $project->fireBuildStarted(); 
    477             $project->init(); 
    478         } catch (Exception $exc) { 
    479             $project->fireBuildFinished($exc); 
    480             throw $exc;         
    481        
    482  
    483         $project->setUserProperty("phing.version", $this->getPhingVersion()); 
    484  
    485         $e = self::$definedProps->keys(); 
    486         while (count($e)) { 
    487             $arg   = (string) array_shift($e); 
    488             $value = (string) self::$definedProps->getProperty($arg); 
    489             $project->setUserProperty($arg, $value); 
    490        
    491         unset($e); 
    492  
    493         $project->setUserProperty("phing.file", $this->buildFile->getAbsolutePath()); 
    494  
    495         // first use the Configurator to create the project object 
    496         // from the given build file. 
    497                  
    498         try { 
    499             ProjectConfigurator::configureProject($project, $this->buildFile); 
    500         } catch (Exception $exc) { 
    501             $project->fireBuildFinished($exc); 
     463 
     464               $error = null; 
     465 
     466               $this->addBuildListeners($project); 
     467               $this->addInputHandler($project); 
     468 
     469               // set this right away, so that it can be used in logging. 
     470               $project->setUserProperty("phing.file", $this->buildFile->getAbsolutePath()); 
     471 
     472               try { 
     473                       $project->fireBuildStarted(); 
     474                       $project->init(); 
     475               } catch (Exception $exc) { 
     476                       $project->fireBuildFinished($exc); 
     477                        throw $exc; 
     478               
     479 
     480               $project->setUserProperty("phing.version", $this->getPhingVersion()); 
     481 
     482               $e = self::$definedProps->keys(); 
     483               while (count($e)) { 
     484                       $arg   = (string) array_shift($e); 
     485                       $value = (string) self::$definedProps->getProperty($arg); 
     486                       $project->setUserProperty($arg, $value); 
     487               
     488               unset($e); 
     489 
     490               $project->setUserProperty("phing.file", $this->buildFile->getAbsolutePath()); 
     491 
     492               // first use the Configurator to create the project object 
     493               // from the given build file. 
     494 
     495               try { 
     496                       ProjectConfigurator::configureProject($project, $this->buildFile); 
     497               } catch (Exception $exc) { 
     498                       $project->fireBuildFinished($exc); 
    502499                        restore_error_handler(); 
    503500                        self::unsetCurrentProject(); 
    504             throw $exc; 
    505         }          
    506  
    507         // make sure that we have a target to execute 
    508         if (count($this->targets) === 0) { 
    509             $this->targets[] = $project->getDefaultTarget(); 
    510        
    511  
    512         // execute targets if help param was not given 
    513         if (!$this->projectHelp) { 
    514              
    515             try {  
    516                 $project->executeTargets($this->targets); 
    517             } catch (Exception $exc) { 
    518                 $project->fireBuildFinished($exc); 
     501                       throw $exc; 
     502                } 
     503 
     504               // make sure that we have a target to execute 
     505               if (count($this->targets) === 0) { 
     506                       $this->targets[] = $project->getDefaultTarget(); 
     507               
     508 
     509               // execute targets if help param was not given 
     510               if (!$this->projectHelp) { 
     511 
     512                        try { 
     513                               $project->executeTargets($this->targets); 
     514                       } catch (Exception $exc) { 
     515                               $project->fireBuildFinished($exc); 
    519516                                restore_error_handler(); 
    520517