azkaban-memoizeit
Changes
src/java/azkaban/utils/PropsUtils.java 80(+53 -27)
Details
src/java/azkaban/utils/PropsUtils.java 80(+53 -27)
diff --git a/src/java/azkaban/utils/PropsUtils.java b/src/java/azkaban/utils/PropsUtils.java
index e3c9c2d..e0dac83 100644
--- a/src/java/azkaban/utils/PropsUtils.java
+++ b/src/java/azkaban/utils/PropsUtils.java
@@ -20,6 +20,7 @@ import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
+import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -146,45 +147,70 @@ public class PropsUtils {
.compile("\\$\\{([a-zA-Z_.0-9]+)\\}");
public static Props resolveProps(Props props) {
- if(props == null) return null;
-
+ if (props == null) {
+ return null;
+ }
+
Props resolvedProps = new Props();
+ LinkedHashSet<String> visitedVariables = new LinkedHashSet<String>();
for (String key : props.getKeySet()) {
- StringBuffer replaced = new StringBuffer();
String value = props.get(key);
- Matcher matcher = VARIABLE_PATTERN.matcher(value);
- while (matcher.find()) {
- String variableName = matcher.group(1);
- if (variableName.equals(key)) {
- throw new IllegalArgumentException(
- String.format(
- "Circular property definition starting from property[%s]",
- key));
- }
+ visitedVariables.add(key);
+ String replacedValue = resolveVariableReplacement(value, props,
+ visitedVariables);
+ visitedVariables.clear();
- String replacement = props.get(variableName);
- if (replacement == null)
- throw new UndefinedPropertyException(
- "Could not find variable substitution for variable '"
- + variableName + "' in key '" + key + "'.");
+ resolvedProps.put(key, replacedValue);
+ }
+
+ return resolvedProps;
+ };
- replacement = replacement.replaceAll("\\\\", "\\\\\\\\");
- replacement = replacement.replaceAll("\\$", "\\\\\\$");
+ private static String resolveVariableReplacement(String value, Props props, LinkedHashSet<String> visitedVariables) {
+ StringBuffer buffer = new StringBuffer();
+ int startIndex = 0;
- matcher.appendReplacement(replaced, replacement);
- matcher.appendTail(replaced);
+ Matcher matcher = VARIABLE_PATTERN.matcher(value);
+ while (matcher.find(startIndex)) {
+ if (startIndex < matcher.start()) {
+ // Copy everything up front to the buffer
+ buffer.append(value.substring(startIndex, matcher.start()));
+ }
+
+ String subVariable = matcher.group(1);
+ // Detected a cycle
+ if (visitedVariables.contains(subVariable)) {
+ throw new IllegalArgumentException(String.format(
+ "Circular variable substitution found: [%s] -> [%s]",
+ StringUtils.join(visitedVariables, "->"),
+ subVariable));
+ } else {
+ // Add substitute variable and recurse.
+ String replacement = props.get(subVariable);
+ visitedVariables.add(subVariable);
+
+ if (replacement == null) {
+ throw new UndefinedPropertyException(
+ String.format(
+ "Could not find variable substitution for variable(s) [%s]",
+ StringUtils.join(visitedVariables, "->")));
+ }
- value = replaced.toString();
- replaced = new StringBuffer();
- matcher = VARIABLE_PATTERN.matcher(value);
+ buffer.append(resolveVariableReplacement(replacement, props,
+ visitedVariables));
+ visitedVariables.remove(subVariable);
}
- matcher.appendTail(replaced);
- resolvedProps.put(key, replaced.toString());
+
+ startIndex = matcher.end();
}
- return resolvedProps;
+ if (startIndex < value.length()) {
+ buffer.append(value.substring(startIndex));
+ }
+
+ return buffer.toString();
}
public static Props addCommonFlowProperties(final ExecutableFlow flow) {
diff --git a/src/java/azkaban/utils/StringUtils.java b/src/java/azkaban/utils/StringUtils.java
index 90fd688..6684b00 100644
--- a/src/java/azkaban/utils/StringUtils.java
+++ b/src/java/azkaban/utils/StringUtils.java
@@ -15,6 +15,7 @@
*/
package azkaban.utils;
+import java.util.Collection;
import java.util.List;
public class StringUtils {
@@ -45,7 +46,7 @@ public class StringUtils {
* @param delimiter
* @return
*/
- public static String join(List<String> list, String delimiter) {
+ public static String join(Collection<String> list, String delimiter) {
StringBuffer buffer = new StringBuffer();
for (String str: list) {
buffer.append(str);
@@ -54,4 +55,5 @@ public class StringUtils {
return buffer.toString();
}
+
}