| [ Index ] |
|
Code source de Symfony 1.0.0 |
1 <?php 2 /* 3 * $Id: Commandline.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 23 /** 24 * Commandline objects help handling command lines specifying processes to 25 * execute. 26 * 27 * The class can be used to define a command line as nested elements or as a 28 * helper to define a command line by an application. 29 * <p> 30 * <code> 31 * <someelement><br> 32 * <acommandline executable="/executable/to/run"><br> 33 * <argument value="argument 1" /><br> 34 * <argument line="argument_1 argument_2 argument_3" /><br> 35 * <argument value="argument 4" /><br> 36 * </acommandline><br> 37 * </someelement><br> 38 * </code> 39 * The element <code>someelement</code> must provide a method 40 * <code>createAcommandline</code> which returns an instance of this class. 41 * 42 * @author thomas.haas@softwired-inc.com 43 * @author <a href="mailto:stefan.bodewig@epost.de">Stefan Bodewig</a> 44 */ 45 class Commandline { 46 47 /** 48 * @var array CommandlineArguments[] 49 */ 50 public $arguments = array(); // public so "inner" class can access 51 52 /** 53 * Full path (if not on %PATH% env var) to executable program. 54 * @var string 55 */ 56 public $executable; // public so "inner" class can access 57 58 const DISCLAIMER = "The ' characters around the executable and arguments are not part of the command."; 59 60 public function __construct($to_process = null) { 61 if ($to_process !== null) { 62 $tmp = $this->translateCommandline($to_process); 63 if ($tmp) { 64 $this->setExecutable(array_shift($tmp)); // removes first el 65 foreach($tmp as $arg) { // iterate through remaining elements 66 $this->createArgument()->setValue($arg); 67 } 68 } 69 } 70 } 71 72 73 /** 74 * Creates an argument object and adds it to our list of args. 75 * 76 * <p>Each commandline object has at most one instance of the 77 * argument class.</p> 78 * 79 * @param boolean $insertAtStart if true, the argument is inserted at the 80 * beginning of the list of args, otherwise it is appended. 81 * @return CommandlineArgument 82 */ 83 public function createArgument($insertAtStart = false) { 84 $argument = new CommandlineArgument($this); 85 if ($insertAtStart) { 86 array_unshift($this->arguments, $argument); 87 } else { 88 array_push($this->arguments, $argument); 89 } 90 return $argument; 91 } 92 93 /** 94 * Sets the executable to run. 95 */ 96 public function setExecutable($executable) { 97 if (!$executable) { 98 return; 99 } 100 $this->executable = $executable; 101 $this->executable = strtr($this->executable, '/', DIRECTORY_SEPARATOR); 102 $this->executable = strtr($this->executable, '\\', DIRECTORY_SEPARATOR); 103 } 104 105 public function getExecutable() { 106 return $this->executable; 107 } 108 109 public function addArguments($line) { 110 foreach($line as $arg) { 111 $this->createArgument()->setValue($arg); 112 } 113 } 114 115 /** 116 * Returns the executable and all defined arguments. 117 * @return array 118 */ 119 public function getCommandline() { 120 $args = $this->getArguments(); 121 if ($this->executable === null) { 122 return $args; 123 } 124 return array_merge(array($this->executable), $args); 125 } 126 127 128 /** 129 * Returns all arguments defined by <code>addLine</code>, 130 * <code>addValue</code> or the argument object. 131 */ 132 public function getArguments() { 133 $result = array(); 134 foreach($this->arguments as $arg) { 135 $parts = $arg->getParts(); 136 if ($parts !== null) { 137 foreach($parts as $part) { 138 $result[] = $part; 139 } 140 } 141 } 142 return $result; 143 } 144 145 public function __toString() { 146 return self::toString($this->getCommandline()); 147 } 148 149 /** 150 * Put quotes around the given String if necessary. 151 * 152 * <p>If the argument doesn't include spaces or quotes, return it 153 * as is. If it contains double quotes, use single quotes - else 154 * surround the argument by double quotes.</p> 155 * 156 * @exception BuildException if the argument contains both, single 157 * and double quotes. 158 */ 159 public static function quoteArgument($argument) { 160 if (strpos($argument, "\"") !== false) { 161 if (strpos($argument, "'") !== false) { 162 throw new BuildException("Can't handle single and double quotes in same argument"); 163 } else { 164 return escapeshellarg($argument); 165 } 166 } elseif (strpos($argument, "'") !== false || strpos($argument, " ") !== false) { 167 return escapeshellarg($argument); 168 //return '\"' . $argument . '\"'; 169 } else { 170 return $argument; 171 } 172 } 173 174 /** 175 * Quotes the parts of the given array in way that makes them 176 * usable as command line arguments. 177 */ 178 public static function toString($lines) { 179 // empty path return empty string 180 if (!$lines) { 181 return ""; 182 } 183 184 // path containing one or more elements 185 $result = ""; 186 for ($i = 0, $len=count($lines); $i < $len; $i++) { 187 if ($i > 0) { 188 $result .= ' '; 189 } 190 $result .= self::quoteArgument($lines[$i]); 191 } 192 return $result; 193 } 194 195 /** 196 * 197 * @param string $to_process 198 * @return array 199 */ 200 public static function translateCommandline($to_process) { 201 202 if (!$to_process) { 203 return array(); 204 } 205 206 // parse with a simple finite state machine 207 208 $normal = 0; 209 $inQuote = 1; 210 $inDoubleQuote = 2; 211 212 $state = $normal; 213 $args = array(); 214 $current = ""; 215 $lastTokenHasBeenQuoted = false; 216 217 $tok = strtok($to_process, ""); 218 $tokens = preg_split('/(["\' ])/', $to_process, -1, PREG_SPLIT_DELIM_CAPTURE); 219 while(($nextTok = array_shift($tokens)) !== null) { 220 switch ($state) { 221 case $inQuote: 222 if ("'" == $nextTok) { 223 $lastTokenHasBeenQuoted = true; 224 $state = $normal; 225 } else { 226 $current .= $nextTok; 227 } 228 break; 229 case $inDoubleQuote: 230 if ("\"" == $nextTok) { 231 $lastTokenHasBeenQuoted = true; 232 $state = $normal; 233 } else { 234 $current .= $nextTok; 235 } 236 break; 237 default: 238 if ("'" == $nextTok) { 239 $state = $inQuote; 240 } elseif ("\"" == $nextTok) { 241 $state = $inDoubleQuote; 242 } elseif (" " == $nextTok) { 243 if ($lastTokenHasBeenQuoted || strlen($current) != 0) { 244 $args[] = $current; 245 $current = ""; 246 } 247 } else { 248 $current .= $nextTok; 249 } 250 $lastTokenHasBeenQuoted = false; 251 break; 252 } 253 } 254 255 if ($lastTokenHasBeenQuoted || strlen($current) != 0) { 256 $args[] = $current; 257 } 258 259 if ($state == $inQuote || $state == $inDoubleQuote) { 260 throw new BuildException("unbalanced quotes in " . $to_process); 261 } 262 263 return $args; 264 } 265 266 /** 267 * @return int Number of components in current commandline. 268 */ 269 public function size() { 270 return count($this->getCommandline()); 271 } 272 273 public function __copy() { 274 $c = new Commandline(); 275 $c->setExecutable($this->executable); 276 $c->addArguments($this->getArguments()); 277 return $c; 278 } 279 280 /** 281 * Clear out the whole command line. */ 282 public function clear() { 283 $this->executable = null; 284 $this->arguments->removeAllElements(); 285 } 286 287 /** 288 * Clear out the arguments but leave the executable in place for 289 * another operation. 290 */ 291 public function clearArgs() { 292 $this->arguments = array(); 293 } 294 295 /** 296 * Return a marker. 297 * 298 * <p>This marker can be used to locate a position on the 299 * commandline - to insert something for example - when all 300 * parameters have been set.</p> 301 * @return CommandlineMarker 302 */ 303 public function createMarker() { 304 return new CommandlineMarker($this, count($this->arguments)); 305 } 306 307 /** 308 * Returns a String that describes the command and arguments 309 * suitable for verbose output before a call to 310 * <code>Runtime.exec(String[])<code>. 311 * 312 * <p>This method assumes that the first entry in the array is the 313 * executable to run.</p> 314 * @param array $args CommandlineArgument[] to use 315 * @return string 316 */ 317 public function describeCommand($args = null) { 318 319 if ($args === null) { 320 $args = $this->getCommandline(); 321 } 322 323 if (!$args) { 324 return ""; 325 } 326 327 $buf = "Executing '"; 328 $buf .= $args[0]; 329 $buf .= "'"; 330 if (count($args) > 0) { 331 $buf .= " with "; 332 $buf .= $this->describeArguments($args, 1); 333 } else { 334 $buf .= self::DISCLAIMER; 335 } 336 return $buf; 337 } 338 339 /** 340 * Returns a String that describes the arguments suitable for 341 * verbose output before a call to 342 * <code>Runtime.exec(String[])<code> 343 * @param $args arguments to use (default is to use current class args) 344 * @param $offset ignore entries before this index 345 * @return string 346 */ 347 protected function describeArguments($args = null, $offset = 0) { 348 if ($args === null) { 349 $args = $this->getArguments(); 350 } 351 352 if ($args === null || count($args) <= $offset) { 353 return ""; 354 } 355 356 $buf = "argument"; 357 if (count($args) > $offset) { 358 $buf .= "s"; 359 } 360 $buf .= ":" . Phing::getProperty("line.separator"); 361 for ($i = $offset, $alen=count($args); $i < $alen; $i++) { 362 $buf .= "'" . $args[$i] . "'" . Phing::getProperty("line.separator"); 363 } 364 $buf .= self::DISCLAIMER; 365 return $buf; 366 } 367 } 368 369 370 /** 371 * "Inner" class used for nested xml command line definitions. 372 */ 373 class CommandlineArgument { 374 375 private $parts = array(); 376 private $outer; 377 378 public function __construct(Commandline $outer) { 379 $this->outer = $outer; 380 } 381 382 /** 383 * Sets a single commandline argument. 384 * 385 * @param string $value a single commandline argument. 386 */ 387 public function setValue($value) { 388 $this->parts = array($value); 389 } 390 391 /** 392 * Line to split into several commandline arguments. 393 * 394 * @param line line to split into several commandline arguments 395 */ 396 public function setLine($line) { 397 if ($line === null) { 398 return; 399 } 400 $this->parts = $this->outer->translateCommandline($line); 401 } 402 403 /** 404 * Sets a single commandline argument and treats it like a 405 * PATH - ensures the right separator for the local platform 406 * is used. 407 * 408 * @param value a single commandline argument. 409 */ 410 public function setPath($value) { 411 $this->parts = array( (string) $value ); 412 } 413 414 /** 415 * Sets a single commandline argument to the absolute filename 416 * of the given file. 417 * 418 * @param value a single commandline argument. 419 */ 420 public function setFile(PhingFile $value) { 421 $this->parts = array($value->getAbsolutePath()); 422 } 423 424 /** 425 * Returns the parts this Argument consists of. 426 * @return array string[] 427 */ 428 public function getParts() { 429 return $this->parts; 430 } 431 } 432 433 /** 434 * Class to keep track of the position of an Argument. 435 */ 436 // <p>This class is there to support the srcfile and targetfile 437 // elements of <execon> and <transform> - don't know 438 // whether there might be additional use cases.</p> --SB 439 class CommandlineMarker { 440 441 private $position; 442 private $realPos = -1; 443 private $outer; 444 445 public function __construct(Comandline $outer, $position) { 446 $this->outer = $outer; 447 $this->position = $position; 448 } 449 450 /** 451 * Return the number of arguments that preceeded this marker. 452 * 453 * <p>The name of the executable - if set - is counted as the 454 * very first argument.</p> 455 */ 456 public function getPosition() { 457 if ($this->realPos == -1) { 458 $realPos = ($this->outer->executable === null ? 0 : 1); 459 for ($i = 0; $i < $position; $i++) { 460 $arg = $this->arguments[$i]; 461 $realPos += count($arg->getParts()); 462 } 463 } 464 return $this->realPos; 465 } 466 } 467
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
| Généré le : Fri Mar 16 22:42:14 2007 | par Balluche grâce à PHPXref 0.7 |