builder/src/main/java/net/happyonroad/builder/SpringComponentPackaging.java
private String interpolate(String content, Map<String, Object> replaces, char mode) {
        Pattern pattern = mode == 'A' ? INTERPOLATE_PTN_A : INTERPOLATE_PTN_B;
        Matcher m = pattern.matcher(content);
        StringBuffer sb = new StringBuffer();
        while (m.find()) {
            String variable = m.group(1);
            Object replace = replaces.get(variable);
            String replacement = replace == null ? "" : replace.toString();
            if (pattern.matcher(replacement).find())
                replacement = interpolate(replacement, replaces, mode);
            try {
                m.appendReplacement(sb, replacement);
            } catch (Exception e) {
                System.err.println(e.getMessage());
            }
        }
        m.appendTail(sb);
        return sb.toString().trim();
    }
private String interpolate(String content, Map<String, Object> replaces, char mode) {
        Pattern pattern = mode == 'A' ? INTERPOLATE_PTN_A : INTERPOLATE_PTN_B;
        Matcher m = pattern.matcher(content);
        StringBuffer sb = new StringBuffer();
        while (m.find()) {
            String variable = m.group(1);
            Object replace = replaces.get(variable);
            String replacement = replace == null ? "" : replace.toString();
            if (pattern.matcher(replacement).find())
                replacement = interpolate(replacement, replaces, mode);
            try {
                m.appendReplacement(sb, replacement);
            } catch (Exception e) {
                System.err.println(e.getMessage());
            }
        }
        m.appendTail(sb);
        return sb.toString().trim();
    }
interpolate xml, bat file content with ${}