[ Index ] |
|
Code source de Symfony 1.0.0 |
1 <?php 2 3 /* 4 * $Id: PropertyTask.php 3076 2006-12-18 08:52:12Z fabien $ 5 * 6 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 7 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 8 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 9 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 10 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 11 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 12 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 13 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 14 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 15 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 16 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 17 * 18 * This software consists of voluntary contributions made by many individuals 19 * and is licensed under the LGPL. For more information please see 20 * <http://phing.info>. 21 */ 22 23 include_once 'phing/Task.php'; 24 include_once 'phing/system/util/Properties.php'; 25 26 /** 27 * Task for setting properties in buildfiles. 28 * 29 * @author Andreas Aderhold <andi@binarycloud.com> 30 * @author Hans Lellelid <hans@xmpl.org> 31 * @version $Revision$ 32 * @package phing.tasks.system 33 */ 34 class PropertyTask extends Task { 35 36 /** name of the property */ 37 protected $name; 38 39 /** value of the property */ 40 protected $value; 41 42 protected $reference; 43 protected $env; // Environment 44 protected $file; 45 protected $ref; 46 protected $prefix; 47 protected $fallback; 48 49 /** Whether to force overwrite of existing property. */ 50 protected $override = false; 51 52 /** Whether property should be treated as "user" property. */ 53 protected $userProperty = false; 54 55 /** 56 * Sets a the name of current property component 57 */ 58 function setName($name) { 59 $this->name = (string) $name; 60 } 61 62 /** Get property component name. */ 63 function getName() { 64 return $this->name; 65 } 66 67 /** 68 * Sets a the value of current property component. 69 * @param mixed Value of name, all scalars allowed 70 */ 71 function setValue($value) { 72 $this->value = (string) $value; 73 } 74 75 /** 76 * Sets value of property to CDATA tag contents. 77 * @param string $values 78 * @since 2.2.0 79 */ 80 public function addText($value) { 81 $this->setValue($value); 82 } 83 84 /** Get the value of current property component. */ 85 function getValue() { 86 return $this->value; 87 } 88 89 /** Set a file to use as the source for properties. */ 90 function setFile($file) { 91 if (is_string($file)) { 92 $file = new PhingFile($file); 93 } 94 $this->file = $file; 95 } 96 97 /** Get the PhingFile that is being used as property source. */ 98 function getFile() { 99 return $this->file; 100 } 101 102 function setRefid(Reference $ref) { 103 $this->reference = $ref; 104 } 105 106 function getRefid() { 107 return $this->reference; 108 } 109 110 /** 111 * Prefix to apply to properties loaded using <code>file</code>. 112 * A "." is appended to the prefix if not specified. 113 * @param string $prefix prefix string 114 * @return void 115 * @since 2.0 116 */ 117 public function setPrefix($prefix) { 118 $this->prefix = $prefix; 119 if (!StringHelper::endsWith(".", $prefix)) { 120 $this->prefix .= "."; 121 } 122 } 123 124 /** 125 * @return string 126 * @since 2.0 127 */ 128 public function getPrefix() { 129 return $this->prefix; 130 } 131 132 /** 133 * the prefix to use when retrieving environment variables. 134 * Thus if you specify environment="myenv" 135 * you will be able to access OS-specific 136 * environment variables via property names "myenv.PATH" or 137 * "myenv.TERM". 138 * <p> 139 * Note that if you supply a property name with a final 140 * "." it will not be doubled. ie environment="myenv." will still 141 * allow access of environment variables through "myenv.PATH" and 142 * "myenv.TERM". This functionality is currently only implemented 143 * on select platforms. Feel free to send patches to increase the number of platforms 144 * this functionality is supported on ;).<br> 145 * Note also that properties are case sensitive, even if the 146 * environment variables on your operating system are not, e.g. it 147 * will be ${env.Path} not ${env.PATH} on Windows 2000. 148 * @param env prefix 149 */ 150 function setEnvironment($env) { 151 $this->env = (string) $env; 152 } 153 154 function getEnvironment() { 155 return $this->env; 156 } 157 158 /** 159 * Set whether this is a user property (ro). 160 * This is deprecated in Ant 1.5, but the userProperty attribute 161 * of the class is still being set via constructor, so Phing will 162 * allow this method to function. 163 * @param boolean $v 164 */ 165 function setUserProperty($v) { 166 $this->userProperty = (boolean) $v; 167 } 168 169 function getUserProperty() { 170 return $this->userProperty; 171 } 172 173 function setOverride($v) { 174 $this->override = (boolean) $v; 175 } 176 177 function getOverride() { 178 return $this->override; 179 } 180 181 function toString() { 182 return (string) $this->value; 183 } 184 185 /** 186 * @param Project $p 187 */ 188 function setFallback($p) { 189 $this->fallback = $p; 190 } 191 192 function getFallback() { 193 return $this->fallback; 194 } 195 /** 196 * set the property in the project to the value. 197 * if the task was give a file or env attribute 198 * here is where it is loaded 199 */ 200 function main() { 201 if ($this->name !== null) { 202 if ($this->value === null && $this->ref === null) { 203 throw new BuildException("You must specify value or refid with the name attribute", $this->getLocation()); 204 } 205 } else { 206 if ($this->file === null && $this->env === null ) { 207 throw new BuildException("You must specify file or environment when not using the name attribute", $this->getLocation()); 208 } 209 } 210 211 if ($this->file === null && $this->prefix !== null) { 212 throw new BuildException("Prefix is only valid when loading from a file.", $this->getLocation()); 213 } 214 215 if (($this->name !== null) && ($this->value !== null)) { 216 $this->addProperty($this->name, $this->value); 217 } 218 219 if ($this->file !== null) { 220 $this->loadFile($this->file); 221 } 222 223 if ( $this->env !== null ) { 224 $this->loadEnvironment($this->env); 225 } 226 227 if (($this->name !== null) && ($this->ref !== null)) { 228 // get the refereced property 229 try { 230 $this->addProperty($this->name, $this->reference->getReferencedObject($this->project)->toString()); 231 } catch (BuildException $be) { 232 if ($this->fallback !== null) { 233 $this->addProperty($this->name, $this->reference->getReferencedObject($this->fallback)->toString()); 234 } else { 235 throw $be; 236 } 237 } 238 } 239 } 240 241 /** 242 * load the environment values 243 * @param string $prefix prefix to place before them 244 */ 245 protected function loadEnvironment($prefix) { 246 247 $props = new Properties(); 248 if ( substr($prefix, strlen($prefix)-1) == '.' ) { 249 $prefix .= "."; 250 } 251 $this->log("Loading Environment $prefix", PROJECT_MSG_VERBOSE); 252 foreach($_ENV as $key => $value) { 253 $props->setProperty($prefix . '.' . $key, $value); 254 } 255 $this->addProperties($props); 256 } 257 258 /** 259 * iterate through a set of properties, 260 * resolve them then assign them 261 */ 262 protected function addProperties($props) { 263 $this->resolveAllProperties($props); 264 foreach($props->keys() as $name) { 265 $value = $props->getProperty($name); 266 $v = $this->project->replaceProperties($value); 267 if ($this->prefix !== null) { 268 $name = $this->prefix . $name; 269 } 270 $this->addProperty($name, $v); 271 } 272 } 273 274 /** 275 * add a name value pair to the project property set 276 * @param string $name name of property 277 * @param string $value value to set 278 */ 279 protected function addProperty($name, $value) { 280 if ($this->userProperty) { 281 if ($this->project->getUserProperty($name) === null || $this->override) { 282 $this->project->setInheritedProperty($name, $value); 283 } else { 284 $this->log("Override ignored for " . $name, PROJECT_MSG_VERBOSE); 285 } 286 } else { 287 if ($this->override) { 288 $this->project->setProperty($name, $value); 289 } else { 290 $this->project->setNewProperty($name, $value); 291 } 292 } 293 } 294 295 /** 296 * load properties from a file. 297 * @param PhingFile $file 298 */ 299 protected function loadFile(PhingFile $file) { 300 $props = new Properties(); 301 $this->log("Loading ". $file->getAbsolutePath(), PROJECT_MSG_INFO); 302 try { // try to load file 303 if ($file->exists()) { 304 $props->load($file); 305 $this->addProperties($props); 306 } else { 307 $this->log("Unable to find property file: ". $file->getAbsolutePath() ."... skipped", PROJECT_MSG_WARN); 308 } 309 } catch (IOException $ioe) { 310 throw new BuildException("Could not load properties from file.", $ioe); 311 } 312 } 313 314 /** 315 * Given a Properties object, this method goes through and resolves 316 * any references to properties within the object. 317 * 318 * @param Properties $props The collection of Properties that need to be resolved. 319 * @return void 320 */ 321 protected function resolveAllProperties(Properties $props) { 322 323 $keys = $props->keys(); 324 325 while(count($keys)) { 326 327 // There may be a nice regex/callback way to handle this 328 // replacement, but at the moment it is pretty complex, and 329 // would probably be a lot uglier to work into a preg_replace_callback() 330 // system. The biggest problem is the fact that a resolution may require 331 // multiple passes. 332 333 $name = array_shift($keys); 334 $value = $props->getProperty($name); 335 $resolved = false; 336 337 while(!$resolved) { 338 339 $fragments = array(); 340 $propertyRefs = array(); 341 342 // [HL] this was ::parsePropertyString($this->value ...) ... this seems wrong 343 self::parsePropertyString($value, $fragments, $propertyRefs); 344 345 $resolved = true; 346 if (count($propertyRefs) !== 0) { 347 348 $sb = ""; 349 350 $i = $fragments; 351 $j = $propertyRefs; 352 while(count($i)) { 353 $fragment = array_shift($i); 354 if ($fragment === null) { 355 $propertyName = array_shift($j); 356 357 if ($propertyName === $name) { 358 // Should we maybe just log this as an error & move on? 359 // $this->log("Property ".$name." was circularly defined.", PROJECT_MSG_ERR); 360 throw new BuildException("Property ".$name." was circularly defined."); 361 } 362 363 $fragment = $this->getProject()->getProperty($propertyName); 364 if ($fragment === null) { 365 if ($props->containsKey($propertyName)) { 366 $fragment = $props->getProperty($propertyName); 367 $resolved = false; // parse again (could have been replaced w/ another var) 368 } else { 369 $fragment = "\${".$propertyName."}"; 370 } 371 } 372 } 373 $sb .= $fragment; 374 } 375 376 $this->log("Resolved Property \"$value\" to \"$sb\"", PROJECT_MSG_DEBUG); 377 $value = $sb; 378 $props->setProperty($name, $value); 379 380 } // if (count($propertyRefs)) 381 382 } // while (!$resolved) 383 384 } // while (count($keys) 385 } 386 387 388 /** 389 * This method will parse a string containing ${value} style 390 * property values into two lists. The first list is a collection 391 * of text fragments, while the other is a set of string property names 392 * null entries in the first list indicate a property reference from the 393 * second list. 394 * 395 * This is slower than regex, but useful for this class, which has to handle 396 * multiple parsing passes for properties. 397 * 398 * @param string $value The string to be scanned for property references 399 * @param array &$fragments The found fragments 400 * @param array &$propertyRefs The found refs 401 */ 402 protected function parsePropertyString($value, &$fragments, &$propertyRefs) { 403 404 $prev = 0; 405 $pos = 0; 406 407 while (($pos = strpos($value, '$', $prev)) !== false) { 408 409 if ($pos > $prev) { 410 array_push($fragments, StringHelper::substring($value, $prev, $pos-1)); 411 } 412 if ($pos === (strlen($value) - 1)) { 413 array_push($fragments, '$'); 414 $prev = $pos + 1; 415 } elseif ($value{$pos+1} !== '{' ) { 416 417 // the string positions were changed to value-1 to correct 418 // a fatal error coming from function substring() 419 array_push($fragments, StringHelper::substring($value, $pos, $pos + 1)); 420 $prev = $pos + 2; 421 } else { 422 $endName = strpos($value, '}', $pos); 423 if ($endName === false) { 424 throw new BuildException("Syntax error in property: $value"); 425 } 426 $propertyName = StringHelper::substring($value, $pos + 2, $endName-1); 427 array_push($fragments, null); 428 array_push($propertyRefs, $propertyName); 429 $prev = $endName + 1; 430 } 431 } 432 433 if ($prev < strlen($value)) { 434 array_push($fragments, StringHelper::substring($value, $prev)); 435 } 436 } 437 438 }
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 |