VariableReplacementHelper { public String replaceVariables(String value, Map<String, Map<String, String>> replacementsMap) throws AmbariException { if ((value != null) && (replacementsMap != null) && !replacementsMap.isEmpty()) { int count = 0; boolean replacementPerformed; do { if (++count > 1000) { throw new AmbariException(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); Map<String, String> replacements; if ((name != null) && !name.isEmpty()) { if (type == null) { replacements = replacementsMap.get(""); } else { replacements = replacementsMap.get(type); } if (replacements != null) { String replacement = replacements.get(name); if (replacement != null) { if (function != null) { replacement = applyReplacementFunction(function, replacement, replacementsMap); } matcher.appendReplacement(sb, replacement.replace("\\", "\\\\").replace("$", "\\$")); replacementPerformed = true; } } } } matcher.appendTail(sb); value = sb.toString(); } while (replacementPerformed); } return value; }  String replaceVariables(String value, Map<String, Map<String, String>> replacementsMap);  }
@Test public void testReplaceVariables() throws AmbariException { Map<String, Map<String, String>> configurations = new HashMap<String, Map<String, String>>() { { put("", new HashMap<String, String>() {{ put("global_variable", "Hello World"); put("variable-name", "dash"); put("variable_name", "underscore"); put("variable.name", "dot"); }}); put("config_type", new HashMap<String, String>() {{ put("variable-name", "config_type_dash"); put("variable_name", "config_type_underscore"); put("variable.name", "config_type_dot"); }}); put("config.type", new HashMap<String, String>() {{ put("variable-name", "config.type_dash"); put("variable_name", "config.type_underscore"); put("variable.name", "config.type_dot"); }}); put("config-type", new HashMap<String, String>() {{ put("variable.name", "Replacement1"); put("variable.name1", "${config-type2/variable.name}"); put("variable.name2", ""); }}); put("config-type2", new HashMap<String, String>() {{ put("variable.name", "Replacement2"); put("self_reference", "${config-type2/self_reference}"); put("${config-type/variable.name}_reference", "Replacement in the key"); }}); } }; Assert.assertEquals("concrete", helper.replaceVariables("concrete", configurations)); Assert.assertEquals("Hello World", helper.replaceVariables("${global_variable}", configurations)); Assert.assertEquals("Replacement1", helper.replaceVariables("${config-type/variable.name}", configurations)); Assert.assertEquals("Replacement1|Replacement2", helper.replaceVariables("${config-type/variable.name}|${config-type2/variable.name}", configurations)); Assert.assertEquals("Replacement1|Replacement2|${config-type3/variable.name}", helper.replaceVariables("${config-type/variable.name}|${config-type2/variable.name}|${config-type3/variable.name}", configurations)); Assert.assertEquals("Replacement2|Replacement2", helper.replaceVariables("${config-type/variable.name1}|${config-type2/variable.name}", configurations)); Assert.assertEquals("Replacement1_reference", helper.replaceVariables("${config-type/variable.name}_reference", configurations)); Assert.assertEquals("dash", helper.replaceVariables("${variable-name}", configurations)); Assert.assertEquals("underscore", helper.replaceVariables("${variable_name}", configurations)); Assert.assertEquals("config_type_dot", helper.replaceVariables("${config_type/variable.name}", configurations)); Assert.assertEquals("config_type_dash", helper.replaceVariables("${config_type/variable-name}", configurations)); Assert.assertEquals("config_type_underscore", helper.replaceVariables("${config_type/variable_name}", configurations)); Assert.assertEquals("config.type_dot", helper.replaceVariables("${config.type/variable.name}", configurations)); Assert.assertEquals("config.type_dash", helper.replaceVariables("${config.type/variable-name}", configurations)); Assert.assertEquals("config.type_underscore", helper.replaceVariables("${config.type/variable_name}", configurations)); Assert.assertEquals("dot", helper.replaceVariables("${variable.name}", configurations)); Assert.assertEquals("", helper.replaceVariables("${config-type/variable.name2}", configurations)); try { Assert.assertEquals("${config-type2/self_reference}", helper.replaceVariables("${config-type2/self_reference}", configurations)); Assert.fail(String.format("%s expected to be thrown", AmbariException.class.getName())); } catch (AmbariException e) { } }
@Test public void testReplaceComplicatedVariables() throws AmbariException { Map<String, Map<String, String>> configurations = new HashMap<String, Map<String, String>>() { { put("", new HashMap<String, String>() {{ put("host", "c6401.ambari.apache.org"); put("realm", "EXAMPLE.COM"); }}); } }; Assert.assertEquals("hive.metastore.local=false,hive.metastore.uris=thrift: helper.replaceVariables("hive.metastore.local=false,hive.metastore.uris=thrift: Assert.assertEquals("Hello my realm is {EXAMPLE.COM}", helper.replaceVariables("Hello my realm is {${realm}}", configurations)); Assert.assertEquals("$c6401.ambari.apache.org", helper.replaceVariables("$${host}", configurations)); }
@Test public void testReplaceVariablesWithFunctions() throws AmbariException { Map<String, Map<String, String>> configurations = new HashMap<String, Map<String, String>>() { { put("", new HashMap<String, String>() {{ put("delimited.data", "one,two,three,four"); put("realm", "UNIT.TEST"); }}); put("kafka-broker", new HashMap<String, String>() {{ put("listeners", "PLAINTEXT: }}); put("clusterHostInfo", new HashMap<String, String>() {{ put("hive_metastore_host", "host1.unit.test, host2.unit.test , host3.unit.test"); }}); put("foobar-site", new HashMap<String, String>() {{ put("data", "one, two, three, four"); put("hello", "hello"); put("hello_there", "hello, there"); put("hello_there_one", "hello, there, one"); }}); } }; Assert.assertEquals("test=thrift: helper.replaceVariables("test=${delimited.data|each(thrift: Assert.assertEquals("hive.metastore.local=false,hive.metastore.uris=thrift: helper.replaceVariables("hive.metastore.local=false,hive.metastore.uris=${clusterHostInfo/hive_metastore_host | each(thrift: List<String> expected; List<String> actual; expected = new LinkedList<String>(Arrays.asList("four", "hello", "one", "three", "two")); actual = new LinkedList<String>(Arrays.asList(helper.replaceVariables("${foobar-site/hello | append(foobar-site/data, \\,, true)}", configurations).split(","))); Collections.sort(expected); Collections.sort(actual); Assert.assertEquals(expected, actual); expected = new LinkedList<String>(Arrays.asList("four", "hello", "one", "there", "three", "two")); actual = new LinkedList<String>(Arrays.asList(helper.replaceVariables("${foobar-site/hello_there | append(foobar-site/data, \\,, true)}", configurations).split(","))); Collections.sort(expected); Collections.sort(actual); Assert.assertEquals(expected, actual); expected = new LinkedList<String>(Arrays.asList("four", "hello", "one", "there", "three", "two")); actual = new LinkedList<String>(Arrays.asList(helper.replaceVariables("${foobar-site/hello_there_one | append(foobar-site/data, \\,, true)}", configurations).split(","))); Collections.sort(expected); Collections.sort(actual); Assert.assertEquals(expected, actual); expected = new LinkedList<String>(Arrays.asList("four", "hello", "one", "one", "there", "three", "two")); actual = new LinkedList<String>(Arrays.asList(helper.replaceVariables("${foobar-site/hello_there_one | append(foobar-site/data, \\,, false)}", configurations).split(","))); Collections.sort(expected); Collections.sort(actual); Assert.assertEquals(expected, actual); try { helper.replaceVariables("${foobar-site/hello_there_one | append(foobar-site/data, \\,)}", configurations); Assert.fail("Expected IllegalArgumentException"); } catch (IllegalArgumentException e) { } Assert.assertEquals("test=unit.test", helper.replaceVariables("test=${realm|toLower()}", configurations)); Assert.assertEquals("PLAINTEXTSASL: }