/** * Given a Properties object, this method goes through and resolves * any references to properties within the object. * * @param Properties $props The collection of Properties that need to be resolved. * @throws BuildException * @return void */ protected function resolveAllProperties(Properties $props) { foreach ($props->keys() as $name) { // There may be a nice regex/callback way to handle this // replacement, but at the moment it is pretty complex, and // would probably be a lot uglier to work into a preg_replace_callback() // system. The biggest problem is the fact that a resolution may require // multiple passes. $value = $props->getProperty($name); $resolved = false; $resolveStack = array(); while (!$resolved) { $fragments = array(); $propertyRefs = array(); // [HL] this was ::parsePropertyString($this->value ...) ... this seems wrong self::parsePropertyString($value, $fragments, $propertyRefs); $resolved = true; if (count($propertyRefs) == 0) { continue; } $sb = ""; $j = $propertyRefs; foreach ($fragments as $fragment) { if ($fragment !== null) { $sb .= $fragment; continue; } $propertyName = array_shift($j); if (in_array($propertyName, $resolveStack)) { // Should we maybe just log this as an error & move on? // $this->log("Property ".$name." was circularly defined.", Project::MSG_ERR); throw new BuildException("Property " . $propertyName . " was circularly defined."); } $fragment = $this->getProject()->getProperty($propertyName); if ($fragment !== null) { $sb .= $fragment; continue; } if ($props->containsKey($propertyName)) { $fragment = $props->getProperty($propertyName); if (strpos($fragment, '${') !== false) { $resolveStack[] = $propertyName; $resolved = false; // parse again (could have been replaced w/ another var) } } else { $fragment = "\${" . $propertyName . "}"; } $sb .= $fragment; } $this->log("Resolved Property \"{$value}\" to \"{$sb}\"", Project::MSG_DEBUG); $value = $sb; $props->setProperty($name, $value); } // while (!$resolved) } // while (count($keys) }