package coursier.paths;

import java.util.LinkedHashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Util {

    // No real reason to put that in the path module, except from the fact that that makes this accessible
    // from both the bootstrap-launcher and cli modules.

    private static final Pattern propertyRegex =
            Pattern.compile(Pattern.quote("${") + "[^" + Pattern.quote("{[()]}") + "]*" + Pattern.quote("}"));

    public static Map<String, String> expandProperties(Map<String, String> properties) {

        final Map<String, String> resolved = new LinkedHashMap<>(properties.size());

        for (String k : properties.keySet()) {
            String value = properties.get(k);

            Matcher matcher = propertyRegex.matcher(value);

            // cycles would loop indefinitely here :-|
            while (matcher.find()) {
                int start = matcher.start(0);
                int end = matcher.end(0);
                String subKey = value.substring(start + 2, end - 1);
                String subValue = resolved.get(subKey);
                if (subValue == null)
                    subValue = System.getProperty(subKey);
                if (subValue == null)
                    subValue = ""; // throw instead?
                value = value.substring(0, start) + subValue + value.substring(end);
            }

            resolved.put(k, value);
        }

        return resolved;
    }
}

@@ -663,42 +663,533 @@
 ));%0A
-%0A        for (String k : propertie
+        final Map%3CString, String%3E withProps = new LinkedHashMap%3C%3E(properties.size());%0A%0A        for (String k : properties.keySet()) %7B%0A            String value = properties.get(k);%0A%0A            Matcher matcher = propertyRegex.matcher(value);%0A            if (matcher.find()) %7B%0A                withProps.put(k, value);%0A            %7D else %7B%0A                resolved.put(k, value);%0A            %7D%0A        %7D%0A%0A        // we don't go recursive here - dynamic properties can only reference static ones%0A%0A        for (String k : withProp
 s.ke

Tweak prop expander