public String replaceVariables(String value, Map<String, Map<String, String>> replacementsMap) throws AmbariRuntimeException {
    if ((value != null) && (replacementsMap != null) && !replacementsMap.isEmpty()) {
      int count = 0; // Used to help prevent an infinite loop...
      boolean replacementPerformed;

      do {
        if (++count > 1000) {
          throw new AmbariRuntimeException(String.format("Circular reference found while replacing variables in %s", value));
        }

        Matcher matcher = PATTERN_VARIABLE.matcher(value);
        StringBuffer sb = new StringBuffer();

        replacementPerformed = false;

        while (matcher.find()) {
          String type = matcher.group(1);
          String name = matcher.group(2);
          String function = matcher.group(3);

          if ((name != null) && !name.isEmpty()) {
            Map<String, String> replacements = (type == null) ? replacementsMap.get("") : replacementsMap.get(type);
            if (replacements == null || replacements.get(name) == null) {
              continue;
            }

            String replacement = replacements.get(name);
            if (function != null) {
              replacement = applyReplacementFunction(function, replacement, replacementsMap);
            }

            // Escape '$' and '\' so they don't cause any issues.
            matcher.appendReplacement(sb, replacement.replace("\\", "\\\\").replace("$", "\\$"));
            replacementPerformed = true;
          }
        }

        matcher.appendTail(sb);
        value = sb.toString();
      } while (replacementPerformed); // Process the string again to make sure new variables were not introduced
    }

    return value;
  }
Performs variable replacement on the supplied String value using values from the replacementsMap.
<p/>
The value is a String containing one or more "variables" in the form of ${variable_name}, such
that "variable_name" may indicate a group identifier; else "" is used as the group.
For example:
<p/>
variable_name:  group: ""; property: "variable_name"
group1/variable_name:  group: "group1"; property: "variable_name"
root/group1/variable_name:  Not Supported
<p/>
The replacementsMap is a Map of Maps creating a (small) hierarchy of data to traverse in order
to resolve the variable.
<p/>
If a variable resolves to one or more variables, that new variable(s) will be processed and replaced.
If variable exists after a set number of iterations it is assumed that a cycle has been created
and the process will abort returning a String in a possibly unexpected state.

@param value           a String containing zero or more variables to be replaced
@param replacementsMap a Map of data used to perform the variable replacements
@return a new String
ambari-server/src/main/java/org/apache/ambari/server/state/kerberos/VariableReplacementHelper.java