PlaceholderHelper { public Set<String> extractPlaceholderKeys(String propertyString) { Set<String> placeholderKeys = Sets.newHashSet(); if (Strings.isNullOrEmpty(propertyString) || (!isNormalizedPlaceholder(propertyString) && !isExpressionWithPlaceholder(propertyString))) { return placeholderKeys; } Stack<String> stack = new Stack<>(); stack.push(propertyString); while (!stack.isEmpty()) { String strVal = stack.pop(); int startIndex = strVal.indexOf(PLACEHOLDER_PREFIX); if (startIndex == -1) { placeholderKeys.add(strVal); continue; } int endIndex = findPlaceholderEndIndex(strVal, startIndex); if (endIndex == -1) { continue; } String placeholderCandidate = strVal.substring(startIndex + PLACEHOLDER_PREFIX.length(), endIndex); if (placeholderCandidate.startsWith(PLACEHOLDER_PREFIX)) { stack.push(placeholderCandidate); } else { int separatorIndex = placeholderCandidate.indexOf(VALUE_SEPARATOR); if (separatorIndex == -1) { stack.push(placeholderCandidate); } else { stack.push(placeholderCandidate.substring(0, separatorIndex)); String defaultValuePart = normalizeToPlaceholder(placeholderCandidate.substring(separatorIndex + VALUE_SEPARATOR.length())); if (!Strings.isNullOrEmpty(defaultValuePart)) { stack.push(defaultValuePart); } } } if (endIndex + PLACEHOLDER_SUFFIX.length() < strVal.length() - 1) { String remainingPart = normalizeToPlaceholder(strVal.substring(endIndex + PLACEHOLDER_SUFFIX.length())); if (!Strings.isNullOrEmpty(remainingPart)) { stack.push(remainingPart); } } } return placeholderKeys; }  Object resolvePropertyValue(ConfigurableBeanFactory beanFactory, String beanName, String placeholder); Set<String> extractPlaceholderKeys(String propertyString);  }
@Test public void testExtractPlaceholderKeys() throws Exception { check("${some.key}", "some.key"); check("${some.key:100}", "some.key"); check("${some.key:${some.other.key}}", "some.key", "some.other.key"); check("${some.key:${some.other.key:100}}", "some.key", "some.other.key"); check("${some.key}/xx", "some.key"); check("${some.key:100}/xx", "some.key"); check("${some.key:${some.other.key}/xx}/yy", "some.key", "some.other.key"); check("${some.key:${some.other.key:100}/xx}/yy", "some.key", "some.other.key"); }
@Test public void testExtractPlaceholderKeysFromExpression() throws Exception { check("#{new java.text.SimpleDateFormat('${some.key}').parse('${another.key}')}", "some.key", "another.key"); check("#{new java.text.SimpleDateFormat('${some.key:abc}').parse('${another.key:100}')}", "some.key", "another.key"); check("#{new java.text.SimpleDateFormat('${some.key:${some.other.key}}').parse('${another.key}')}", "some.key", "another.key", "some.other.key"); check("#{new java.text.SimpleDateFormat('${some.key:${some.other.key:abc}}').parse('${another.key}')}", "some.key", "another.key", "some.other.key"); check("#{new java.text.SimpleDateFormat('${${some.key}}').parse('${${another.key:other.key}}')}", "some.key", "another.key"); check("#{new java.text.SimpleDateFormat('${some.key}/xx').parse('${another.key}/xx')}", "some.key", "another.key"); check("#{new java.text.SimpleDateFormat('${some.key:abc}/xx').parse('${another.key:100}/xx')}", "some.key", "another.key"); check("#{new java.text.SimpleDateFormat('${some.key:${some.other.key}/xx}/xx').parse('${another.key}/xx')}", "some.key", "another.key", "some.other.key"); check("#{new java.text.SimpleDateFormat('${some.key:${some.other.key:abc}/xx}/xx').parse('${another.key}/xx')}", "some.key", "another.key", "some.other.key"); check("#{new java.text.SimpleDateFormat('${${some.key}/xx}').parse('${${another.key:other.key}/xx}/xx')}", "some.key", "another.key"); assertTrue(placeholderHelper.extractPlaceholderKeys("#{systemProperties[some.key] ?: 123}").isEmpty()); assertTrue(placeholderHelper.extractPlaceholderKeys("#{ T(java.lang.Math).random() * 100.0 }").isEmpty()); }
@Test public void testExtractInvalidPlaceholderKeys() throws Exception { assertTrue(placeholderHelper.extractPlaceholderKeys("some.key").isEmpty()); assertTrue(placeholderHelper.extractPlaceholderKeys("some.key:100").isEmpty()); }