/**
  * 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)
 }