From 41c63672c02a1398f757e74c5909802f95a11498 Mon Sep 17 00:00:00 2001 From: John Niang Date: Thu, 6 Feb 2020 17:09:39 +0800 Subject: [PATCH] Refactor ConfigInitializer and improve map type config (#4321) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Refactor ConfigInitializer * Rename some variable names and add some java docs Co-authored-by: kezhenxu94 Co-authored-by: 吴晟 Wu Sheng --- .../apm/util/ConfigInitializer.java | 164 +++++++++++++----- .../conf/SnifferConfigInitializerTest.java | 4 + 2 files changed, 121 insertions(+), 47 deletions(-) diff --git a/apm-commons/apm-util/src/main/java/org/apache/skywalking/apm/util/ConfigInitializer.java b/apm-commons/apm-util/src/main/java/org/apache/skywalking/apm/util/ConfigInitializer.java index 0072d0055..a7be27e3f 100644 --- a/apm-commons/apm-util/src/main/java/org/apache/skywalking/apm/util/ConfigInitializer.java +++ b/apm-commons/apm-util/src/main/java/org/apache/skywalking/apm/util/ConfigInitializer.java @@ -21,9 +21,13 @@ package org.apache.skywalking.apm.util; import java.lang.reflect.Field; import java.lang.reflect.Modifier; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.util.Collections; import java.util.LinkedList; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Properties; import java.util.logging.Logger; @@ -44,38 +48,36 @@ public class ConfigInitializer { for (Field field : recentConfigType.getFields()) { if (Modifier.isPublic(field.getModifiers()) && Modifier.isStatic(field.getModifiers())) { String configKey = (parentDesc + "." + field.getName()).toLowerCase(); - /** - * Map config format is, config_key[map_key]=map_value - * Such as plugin.opgroup.resttemplate.rule[abc]=/url/path - */ - if (field.getType().equals(Map.class)) { - Map map = (Map)field.get(null); - for (Object key : properties.keySet()) { - String stringKey = key.toString(); - if (stringKey.startsWith(configKey + "[") && stringKey.endsWith("]")) { - String itemKey = stringKey.substring(configKey.length() + 1, stringKey.length() - 1); - map.put(itemKey, properties.getProperty(stringKey)); - } + Class type = field.getType(); + + if (type.equals(Map.class)) { + /* + * Map config format is, config_key[map_key]=map_value + * Such as plugin.opgroup.resttemplate.rule[abc]=/url/path + */ + // Deduct two generic types of the map + ParameterizedType genericType = (ParameterizedType)field.getGenericType(); + Type[] argumentTypes = genericType.getActualTypeArguments(); + + Type keyType = null; + Type valueType = null; + if (argumentTypes != null && argumentTypes.length == 2) { + // Get key type and value type of the map + keyType = argumentTypes[0]; + valueType = argumentTypes[1]; } + Map map = (Map)field.get(null); + // Set the map from config key and properties + setForMapType(configKey, map, properties, keyType, valueType); } else { - /** + /* * Others typical field type */ String value = properties.getProperty(configKey); - if (value != null) { - Class type = field.getType(); - if (type.equals(int.class)) - field.set(null, Integer.valueOf(value)); - else if (type.equals(String.class)) - field.set(null, value); - else if (type.equals(long.class)) - field.set(null, Long.valueOf(value)); - else if (type.equals(boolean.class)) - field.set(null, Boolean.valueOf(value)); - else if (type.equals(List.class)) - field.set(null, convert2List(value)); - else if (type.isEnum()) - field.set(null, Enum.valueOf((Class)type, value.toUpperCase())); + // Convert the value into real type + Object convertedValue = convertToTypicalType(type, value); + if (convertedValue != null) { + field.set(null, convertedValue); } } } @@ -87,28 +89,108 @@ public class ConfigInitializer { } } - private static List convert2List(String value) { - List result = new LinkedList(); - if (StringUtil.isEmpty(value)) { - return result; + /** + * Convert string value to typical type. + * @param type type to convert + * @param value string value to be converted + * @return converted value or null + */ + private static Object convertToTypicalType(Type type, String value) { + if (value == null || type == null) { + return null; } + Object result = null; + if (String.class.equals(type)) { + result = value; + } else if (int.class.equals(type) || Integer.class.equals(type)) { + result = Integer.valueOf(value); + } else if (long.class.equals(type) || Long.class.equals(type)) { + result = Long.valueOf(value); + } else if (boolean.class.equals(type) || Boolean.class.equals(type)) { + result = Boolean.valueOf(value); + } else if (float.class.equals(type) || Float.class.equals(type)) { + result = Boolean.valueOf(value); + } else if (double.class.equals(type) || Double.class.equals(type)) { + result = Double.valueOf(value); + } else if (List.class.equals(type)) { + result = convert2List(value); + } else if (type instanceof Class) { + Class clazz = (Class)type; + if (clazz.isEnum()) { + result = Enum.valueOf((Class)type, value.toUpperCase()); + } + } + return result; + } + + /** + * Set map items. + * @param configKey config key must not be null + * @param map map to set must not be null + * @param properties properties must not be null + * @param keyType key type of the map + * @param valueType value type of the map + */ + private static void setForMapType(String configKey, Map map, Properties properties, + final Type keyType, + final Type valueType) { + + Objects.requireNonNull(configKey); + Objects.requireNonNull(map); + Objects.requireNonNull(properties); + + String prefix = configKey + "["; + String suffix = "]"; + + properties.forEach((propertyKey, propertyValue) -> { + String propertyStringKey = propertyKey.toString(); + if (propertyStringKey.startsWith(prefix) && propertyStringKey.endsWith(suffix)) { + String itemKey = propertyStringKey.substring(prefix.length(), propertyStringKey.length() - suffix.length()); + Object keyObj; + Object valueObj; + + keyObj = convertToTypicalType(keyType, itemKey); + valueObj = convertToTypicalType(valueType, propertyValue.toString()); + + if (keyObj == null) { + keyObj = itemKey; + } + + if (valueObj == null) { + valueObj = propertyValue; + } + + map.put(keyObj, valueObj); + } + }); + } + + private static List convert2List(String value) { + if (StringUtil.isEmpty(value)) { + return Collections.emptyList(); + } + List result = new LinkedList<>(); + String[] segments = value.split(","); for (String segment : segments) { String trimmedSegment = segment.trim(); - if (!StringUtil.isEmpty(trimmedSegment)) { + if (StringUtil.isNotEmpty(trimmedSegment)) { result.add(trimmedSegment); } } return result; } + } class ConfigDesc { - private LinkedList descs = new LinkedList(); + private LinkedList descs = new LinkedList<>(); void append(String currentDesc) { - descs.addLast(currentDesc); + if (StringUtil.isNotEmpty(currentDesc)) { + descs.addLast(currentDesc); + } } void removeLastDesc() { @@ -117,18 +199,6 @@ class ConfigDesc { @Override public String toString() { - if (descs.size() == 0) { - return ""; - } - StringBuilder ret = new StringBuilder(descs.getFirst()); - boolean first = true; - for (String desc : descs) { - if (first) { - first = false; - continue; - } - ret.append(".").append(desc); - } - return ret.toString(); + return String.join(".", descs); } } diff --git a/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/conf/SnifferConfigInitializerTest.java b/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/conf/SnifferConfigInitializerTest.java index 0ed5d4e52..4d0ed5cbd 100644 --- a/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/conf/SnifferConfigInitializerTest.java +++ b/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/conf/SnifferConfigInitializerTest.java @@ -66,12 +66,16 @@ public class SnifferConfigInitializerTest { @Test public void testConfigOverriding() throws AgentPackageNotFoundException, ConfigNotFoundException { System.setProperty("skywalking.agent.service_name", "testAppFromSystem"); + System.setProperty("skywalking.agent.instance_properties[key1]", "value1"); + System.setProperty("skywalking.agent.instance_properties[key2]", "value2"); System.setProperty("skywalking.collector.backend_service", "127.0.0.1:8090"); String agentOptions = "agent.service_name=testAppFromAgentOptions,logging.level=debug"; SnifferConfigInitializer.initialize(agentOptions); assertThat(Config.Agent.SERVICE_NAME, is("testAppFromAgentOptions")); assertThat(Config.Collector.BACKEND_SERVICE, is("127.0.0.1:8090")); assertThat(Config.Logging.LEVEL, is(LogLevel.DEBUG)); + assertThat(Config.Agent.INSTANCE_PROPERTIES.get("key1"), is("value1")); + assertThat(Config.Agent.INSTANCE_PROPERTIES.get("key2"), is("value2")); } @Test