FELIX-4710 : Web Console: Display templated name hint for factory configuration entries. Apply updated patch from Stefan Seifert
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1654729 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/webconsole/src/main/java/org/apache/felix/webconsole/internal/configuration/ConfigAdminSupport.java b/webconsole/src/main/java/org/apache/felix/webconsole/internal/configuration/ConfigAdminSupport.java
index d15d94d..3d4a343 100644
--- a/webconsole/src/main/java/org/apache/felix/webconsole/internal/configuration/ConfigAdminSupport.java
+++ b/webconsole/src/main/java/org/apache/felix/webconsole/internal/configuration/ConfigAdminSupport.java
@@ -37,6 +37,8 @@
import java.util.StringTokenizer;
import java.util.TreeMap;
import java.util.Vector;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
import javax.servlet.http.HttpServletRequest;
@@ -67,7 +69,8 @@
static {
CONFIG_PROPERTIES_HIDE.add(PROPERTY_FACTORYCONFIG_NAMEHINT);
}
-
+ private static final Pattern NAMEHINT_PLACEHOLER_REGEXP = Pattern.compile("\\{([^\\{\\}]*)}");
+
private final BundleContext bundleContext;
private final ConfigurationAdmin service;
@@ -626,84 +629,100 @@
*/
private static final String getConfigurationFactoryNameHint(Configuration config, MetaTypeServiceSupport mtss)
{
- // check for configured name hint template
Dictionary props = config.getProperties();
- Object nameHintTemplateObject = props.get(PROPERTY_FACTORYCONFIG_NAMEHINT);
- if (nameHintTemplateObject == null || !(nameHintTemplateObject instanceof String))
- {
- // check for metatype default value for name hint template
- if (mtss != null)
- {
- Map adMap = mtss.getAttributeDefinitionMap(config, null);
- PropertyDescriptor ad = (PropertyDescriptor)adMap.get(PROPERTY_FACTORYCONFIG_NAMEHINT);
- if (ad != null && ad.getDefaultValue() != null && ad.getDefaultValue().length == 1)
- {
- nameHintTemplateObject = ad.getDefaultValue()[0];
- }
- }
- if (nameHintTemplateObject == null)
- {
- return null;
- }
- }
- String nameHint = (String) nameHintTemplateObject;
- Enumeration keys = props.keys();
- while (keys.hasMoreElements())
- {
- String key = (String) keys.nextElement();
- Object value = props.get(key);
- if (value != null)
- {
- StringBuffer valueString = new StringBuffer();
- if (value instanceof String[]) {
- String[] valueArray = (String[])value;
- for (int i = 0; i < valueArray.length; i++) {
- if (i > 0) {
- valueString.append(",");
- }
- valueString.append(valueArray[i]);
- }
- }
- else {
- valueString.append(value.toString());
- }
- nameHint = nameHint.replaceAll(regexQuote("{" + key + "}"), valueString.toString());
- }
- }
- return nameHint;
- }
+ Map adMap = (mtss != null) ? mtss.getAttributeDefinitionMap(config, null) : null;
+ // check for configured name hint template
+ String nameHint = getConfigurationPropertyValueOrDefault(PROPERTY_FACTORYCONFIG_NAMEHINT, props, adMap);
+ if (nameHint == null)
+ {
+ return null;
+ }
+
+ // search for all variable patterns in name hint and replace them with configured/default values
+ Matcher matcher = NAMEHINT_PLACEHOLER_REGEXP.matcher(nameHint);
+ StringBuffer sb = new StringBuffer();
+ while (matcher.find())
+ {
+ String propertyName = matcher.group(1);
+ String value = getConfigurationPropertyValueOrDefault(propertyName, props, adMap);
+ if (value == null) {
+ value = "";
+ }
+ matcher.appendReplacement(sb, matcherQuoteReplacement(value));
+ }
+ matcher.appendTail(sb);
+
+ // make sure name hint does not only contain whitespaces
+ nameHint = sb.toString().trim();
+ if (nameHint.length() == 0) {
+ return null;
+ }
+ else {
+ return nameHint;
+ }
+ }
+
/**
- * Replacement for Pattern.quote(), which only available in JDK 1.5 and up.
+ * Gets configured service property value, or default value if no value is configured.
+ * @param propertyName Property name
+ * @param props Service configuration properties map
+ * @param adMap Attribute definitions map
+ * @return Value or null if none found
+ */
+ private static String getConfigurationPropertyValueOrDefault(String propertyName, Dictionary props, Map adMap) {
+ // get configured property value
+ Object value = props.get(propertyName);
+
+ if (value != null)
+ {
+ // if set convert to string
+ if (value instanceof String[]) {
+ String[] valueArray = (String[])value;
+ StringBuffer valueString = new StringBuffer();
+ for (int i = 0; i < valueArray.length; i++) {
+ if (i > 0) {
+ valueString.append(",");
+ }
+ valueString.append(valueArray[i]);
+ }
+ return valueString.toString();
+ }
+ else {
+ return value.toString();
+ }
+ }
+ else
+ {
+ // if not set try to get default value
+ PropertyDescriptor ad = (PropertyDescriptor)adMap.get(propertyName);
+ if (ad != null && ad.getDefaultValue() != null && ad.getDefaultValue().length == 1)
+ {
+ return ad.getDefaultValue()[0];
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Replacement for Matcher.quoteReplacement which is only available in JDK 1.5 and up.
* @param str Unquoted string
* @return Quoted string
*/
- private static final String regexQuote(String str)
+ private static String matcherQuoteReplacement(String str)
{
- int eInd = str.indexOf("\\E");
- if (eInd < 0)
- {
- // No need to handle backslashes.
- return "\\Q" + str + "\\E";
+ StringBuffer sb = new StringBuffer();
+ for (int i = 0; i < str.length(); i++) {
+ char c = str.charAt(i);
+ if (c == '$' || c == '\\') {
+ sb.append('\\');
+ }
+ sb.append(c);
}
-
- StringBuffer sb = new StringBuffer(str.length() + 16);
- sb.append("\\Q"); // start quote
-
- int pos = 0;
- do
- {
- // A backslash is quoted by another backslash;
- // 'E' is not needed to be quoted.
- sb.append(str.substring(pos, eInd)).append("\\E" + "\\\\" + "E" + "\\Q");
- pos = eInd + 2;
- }
- while ((eInd = str.indexOf("\\E", pos)) >= 0);
-
- sb.append(str.substring(pos, str.length())).append("\\E"); // end quote
return sb.toString();
}
-
+
final void listFactoryConfigurations(JSONObject json, String pidFilter,
String locale)
{