if (priorVariables == null) { priorVariables = new ArrayList(); priorVariables.add(base);
VariableParser parser = createParser(data, offset, length); Token tok; while ((tok = parser.nextToken(data)) != null) { switch (tok.getType()) { case Token.TEXT_TOKEN : buf.append(data, tok.getStartIndex(), tok.getLength()); break;  case Token.ESCAPED_VAR_TOKEN : buf.append(getVariablePrefix()); tokenCnt++; break;  case Token.VARIABLE_TOKEN : String variable = tok.getText(data);    if (priorVariables.contains(variable)) { String initialBase = priorVariables.remove(0).toString(); priorVariables.add(variable); StrBuilder priorVariableSb = new StrBuilder();    for (Iterator it = priorVariables.iterator(); it.hasNext();) { priorVariableSb.append(it.next()); if (it.hasNext()) { priorVariableSb.append("->"); } } throw new IllegalStateException("Infinite loop in property interpolation of " + initialBase + ": " + priorVariableSb.toString()); }  priorVariables.add(variable);  resultObj = resolveVariable(variable); if (resultObj != null) { resultObj = doReplace(resultObj, priorVariables); buf.append(resultObj); } else {  buf.append(getVariablePrefix()).append(variable).append(getVariableSuffix()); }      priorVariables.remove(priorVariables.size() - 1); break; } tokenCnt++;
    private Object doReplace(Object obj, List priorVariables) {        if (obj == null) {            return null;        }        String base = obj.toString();        if (base.indexOf(getVariablePrefix()) < 0) {            return obj;        }        // on the first call initialize priorVariables        // and add base as the first element        if (priorVariables == null) {            priorVariables = new ArrayList();            priorVariables.add(base);        }        int begin = -1;        int end = -1;        int prec = 0 - getVariableSuffix().length();        String variable = null;        StringBuffer result = new StringBuffer();        Object objResult = null;        int objLen = 0;        while (((begin = base.indexOf(                getVariablePrefix(),                 prec + getVariableSuffix().length())) > -1)            && ((end = findEndToken(base, begin)) > -1)) {            int escBegin = escaped(base, begin);            if (escBegin >= 0) {                result.append(base.substring(prec + getVariableSuffix().length(), escBegin));                unescape(result, base, escBegin, end + getVariableSuffix().length(), priorVariables);            }            else {                result.append(base.substring(prec + getVariableSuffix().length(), begin));                variable = base.substring(begin + getVariablePrefix().length(), end);                // if we've got a loop, create a useful exception message and                // throw                if (priorVariables.contains(variable)) {                    String initialBase = priorVariables.remove(0).toString();                    priorVariables.add(variable);                    StringBuffer priorVariableSb = new StringBuffer();                    // create a nice trace of interpolated variables like so:                    // var1->var2->var3                    for (Iterator it = priorVariables.iterator(); it.hasNext();) {                        priorVariableSb.append(it.next());                        if (it.hasNext()) {                            priorVariableSb.append("->");                        }                    }                    throw new IllegalStateException("Infinite loop in property interpolation of "                        + initialBase                        + ": "                        + priorVariableSb.toString());                }                // otherwise, add this variable to the interpolation list.                priorVariables.add(variable);                objResult = resolveVariable(variable);                if (objResult != null) {                    objResult = doReplace(objResult, priorVariables);                    result.append(objResult);                    objLen = objResult.toString().length();                } else {                    // variable not defined - so put it back in the value                    result.append(getVariablePrefix()).append(variable).append(getVariableSuffix());                }                // pop the interpolated variable off the stack                // this maintains priorVariables correctness for                // properties with multiple interpolations, e.g.                // prop.name=${some.other.prop1}/blahblah/${some.other.prop2}                priorVariables.remove(priorVariables.size() - 1);            }            prec = end;        }        result.append(base.substring(prec + getVariableSuffix().length(), base.length()));        return (objResult != null && objLen > 0 && objLen == result.length()) ? objResult : result.toString();    }