diff --git a/spring-cloud-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/client/NacosPropertySourceBuilder.java b/spring-cloud-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/client/NacosPropertySourceBuilder.java index 767a72c1e..7c3dbaa7b 100644 --- a/spring-cloud-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/client/NacosPropertySourceBuilder.java +++ b/spring-cloud-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/client/NacosPropertySourceBuilder.java @@ -17,9 +17,8 @@ package com.alibaba.cloud.nacos.client; import java.util.Date; -import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.Map; -import java.util.Properties; import com.alibaba.cloud.nacos.NacosPropertySourceRepository; import com.alibaba.cloud.nacos.parser.NacosDataParserHandler; @@ -39,7 +38,7 @@ public class NacosPropertySourceBuilder { private static final Logger log = LoggerFactory .getLogger(NacosPropertySourceBuilder.class); - private static final Properties EMPTY_PROPERTIES = new Properties(); + private static final Map EMPTY_MAP = new LinkedHashMap(); private ConfigService configService; @@ -72,14 +71,15 @@ public class NacosPropertySourceBuilder { */ NacosPropertySource build(String dataId, String group, String fileExtension, boolean isRefreshable) { - Properties p = loadNacosData(dataId, group, fileExtension); + Map p = loadNacosData(dataId, group, fileExtension); NacosPropertySource nacosPropertySource = new NacosPropertySource(group, dataId, - propertiesToMap(p), new Date(), isRefreshable); + p, new Date(), isRefreshable); NacosPropertySourceRepository.collectNacosPropertySource(nacosPropertySource); return nacosPropertySource; } - private Properties loadNacosData(String dataId, String group, String fileExtension) { + private Map loadNacosData(String dataId, String group, + String fileExtension) { String data = null; try { data = configService.getConfig(dataId, group, timeout); @@ -87,16 +87,16 @@ public class NacosPropertySourceBuilder { log.warn( "Ignore the empty nacos configuration and get it based on dataId[{}] & group[{}]", dataId, group); - return EMPTY_PROPERTIES; + return EMPTY_MAP; } if (log.isDebugEnabled()) { log.debug(String.format( "Loading nacos data, dataId: '%s', group: '%s', data: %s", dataId, group, data)); } - Properties properties = NacosDataParserHandler.getInstance() + Map dataMap = NacosDataParserHandler.getInstance() .parseNacosData(data, fileExtension); - return properties == null ? EMPTY_PROPERTIES : properties; + return dataMap == null ? EMPTY_MAP : dataMap; } catch (NacosException e) { log.error("get data from Nacos error,dataId:{}, ", dataId, e); @@ -104,14 +104,7 @@ public class NacosPropertySourceBuilder { catch (Exception e) { log.error("parse data from Nacos error,dataId:{},data:{},", dataId, data, e); } - return EMPTY_PROPERTIES; - } - - @SuppressWarnings("unchecked") - private Map propertiesToMap(Properties properties) { - Map result = new HashMap<>(16); - properties.forEach((k, v) -> result.put(String.valueOf(k), v)); - return result; + return EMPTY_MAP; } } diff --git a/spring-cloud-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/parser/AbstractNacosDataParser.java b/spring-cloud-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/parser/AbstractNacosDataParser.java index 4109b049a..6f94cb6c0 100644 --- a/spring-cloud-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/parser/AbstractNacosDataParser.java +++ b/spring-cloud-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/parser/AbstractNacosDataParser.java @@ -17,9 +17,12 @@ package com.alibaba.cloud.nacos.parser; import java.io.IOException; -import java.util.HashMap; +import java.util.Collection; +import java.util.Collections; +import java.util.Iterator; +import java.util.LinkedHashMap; import java.util.Map; -import java.util.Properties; +import java.util.Set; import org.springframework.util.StringUtils; @@ -32,6 +35,8 @@ public abstract class AbstractNacosDataParser { protected static final String VALUE = "value"; + protected static final String EMPTY_STRING = ""; + private String extension; private AbstractNacosDataParser nextParser; @@ -66,7 +71,7 @@ public abstract class AbstractNacosDataParser { * @return result of Properties * @throws IOException thrown if there is a problem parsing config. */ - public final Properties parseNacosData(String data, String extension) + public final Map parseNacosData(String data, String extension) throws IOException { if (extension == null || extension.length() < 1) { throw new IllegalStateException("The file extension cannot be empty"); @@ -86,7 +91,7 @@ public abstract class AbstractNacosDataParser { * @return result of Properties * @throws IOException thrown if there is a problem parsing config. */ - protected abstract Properties doParse(String data) throws IOException; + protected abstract Map doParse(String data) throws IOException; protected AbstractNacosDataParser setNextParser(AbstractNacosDataParser nextParser) { this.nextParser = nextParser; @@ -108,23 +113,36 @@ public abstract class AbstractNacosDataParser { || this.extension.contains(extension); } - /** - * Generate key-value pairs from the map. - */ - protected Properties generateProperties(Map map) { - if (null == map || map.isEmpty()) { - return null; - } - Properties properties = new Properties(); - for (Map.Entry entry : map.entrySet()) { + protected void flattenedMap(Map result, Map dataMap, + String parentKey) { + Set> entries = dataMap.entrySet(); + for (Iterator> iterator = entries.iterator(); iterator + .hasNext();) { + Map.Entry entry = iterator.next(); String key = entry.getKey(); - if (StringUtils.isEmpty(key)) { + Object value = entry.getValue(); + + String fullKey = StringUtils.isEmpty(parentKey) ? key : key.startsWith("[") + ? parentKey.concat(key) : parentKey.concat(DOT).concat(key); + + if (value instanceof Map) { + Map map = (Map) value; + flattenedMap(result, map, fullKey); + continue; + } + else if (value instanceof Collection) { + int count = 0; + Collection collection = (Collection) value; + for (Object object : collection) { + flattenedMap(result, + Collections.singletonMap("[" + (count++) + "]", object), + fullKey); + } continue; } - key = key.startsWith(DOT) ? key.replaceFirst("\\.", "") : key; - properties.put(key, entry.getValue()); + + result.put(fullKey, value); } - return properties; } /** @@ -134,7 +152,7 @@ public abstract class AbstractNacosDataParser { if (map == null || map.isEmpty()) { return null; } - Map result = new HashMap<>(map); + Map result = new LinkedHashMap<>(map); for (Map.Entry entry : map.entrySet()) { String key = entry.getKey(); if (key.contains(DOT)) { diff --git a/spring-cloud-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/parser/NacosDataJsonParser.java b/spring-cloud-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/parser/NacosDataJsonParser.java index 7b22192d1..d33cf62f8 100644 --- a/spring-cloud-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/parser/NacosDataJsonParser.java +++ b/spring-cloud-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/parser/NacosDataJsonParser.java @@ -17,13 +17,8 @@ package com.alibaba.cloud.nacos.parser; import java.io.IOException; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.Iterator; +import java.util.LinkedHashMap; import java.util.Map; -import java.util.Properties; -import java.util.Set; import com.fasterxml.jackson.databind.ObjectMapper; @@ -41,12 +36,12 @@ public class NacosDataJsonParser extends AbstractNacosDataParser { } @Override - protected Properties doParse(String data) throws IOException { + protected Map doParse(String data) throws IOException { if (StringUtils.isEmpty(data)) { return null; } Map map = parseJSON2Map(data); - return this.generateProperties(this.reloadMap(map)); + return this.reloadMap(map); } /** @@ -55,49 +50,17 @@ public class NacosDataJsonParser extends AbstractNacosDataParser { * @return the map convert by json string * @throws IOException thrown if there is a problem parsing config. */ - public static Map parseJSON2Map(String json) throws IOException { - Map result = new HashMap<>(32); + private Map parseJSON2Map(String json) throws IOException { + Map result = new LinkedHashMap<>(32); ObjectMapper mapper = new ObjectMapper(); - Map nacosDataMap = mapper.readValue(json, Map.class); + Map nacosDataMap = mapper.readValue(json, LinkedHashMap.class); if (CollectionUtils.isEmpty(nacosDataMap)) { return result; } - parseNacosDataMap(result, nacosDataMap, ""); + flattenedMap(result, nacosDataMap, EMPTY_STRING); return result; } - private static void parseNacosDataMap(Map result, - Map dataMap, String parentKey) { - Set> entries = dataMap.entrySet(); - for (Iterator> iterator = entries.iterator(); iterator - .hasNext();) { - Map.Entry entry = iterator.next(); - String key = entry.getKey(); - Object value = entry.getValue(); - - String fullKey = StringUtils.isEmpty(parentKey) ? key : key.startsWith("[") - ? parentKey.concat(key) : parentKey.concat(DOT).concat(key); - - if (value instanceof Map) { - Map map = (Map) value; - parseNacosDataMap(result, map, fullKey); - continue; - } - else if (value instanceof Collection) { - int count = 0; - Collection collection = (Collection) value; - for (Object object : collection) { - parseNacosDataMap(result, - Collections.singletonMap("[" + (count++) + "]", object), - fullKey); - } - continue; - } - - result.put(fullKey, value); - } - } - } diff --git a/spring-cloud-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/parser/NacosDataParserHandler.java b/spring-cloud-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/parser/NacosDataParserHandler.java index 5aabf8042..f5787e791 100644 --- a/spring-cloud-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/parser/NacosDataParserHandler.java +++ b/spring-cloud-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/parser/NacosDataParserHandler.java @@ -17,7 +17,7 @@ package com.alibaba.cloud.nacos.parser; import java.io.IOException; -import java.util.Properties; +import java.util.Map; /** * @author zkz @@ -34,10 +34,11 @@ public final class NacosDataParserHandler { * Parsing nacos configuration content. * @param data config from Nacos * @param extension file extension. json or xml or yml or yaml or properties - * @return result of properties + * @return result of LinkedHashMap * @throws IOException thrown if there is a problem parsing config. */ - public Properties parseNacosData(String data, String extension) throws IOException { + public Map parseNacosData(String data, String extension) + throws IOException { if (null == parser) { parser = this.createParser(); } diff --git a/spring-cloud-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/parser/NacosDataPropertiesParser.java b/spring-cloud-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/parser/NacosDataPropertiesParser.java index a560648cf..315caccbf 100644 --- a/spring-cloud-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/parser/NacosDataPropertiesParser.java +++ b/spring-cloud-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/parser/NacosDataPropertiesParser.java @@ -16,24 +16,49 @@ package com.alibaba.cloud.nacos.parser; +import java.io.BufferedReader; import java.io.IOException; import java.io.StringReader; -import java.util.Properties; +import java.util.LinkedHashMap; +import java.util.Map; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import org.springframework.util.StringUtils; /** * @author zkz */ public class NacosDataPropertiesParser extends AbstractNacosDataParser { + private static final Logger log = LoggerFactory + .getLogger(NacosDataPropertiesParser.class); + public NacosDataPropertiesParser() { super("properties"); } @Override - protected Properties doParse(String data) throws IOException { - Properties properties = new Properties(); - properties.load(new StringReader(data)); - return properties; + protected Map doParse(String data) throws IOException { + Map result = new LinkedHashMap<>(); + + try (BufferedReader reader = new BufferedReader(new StringReader(data))) { + for (String line = reader.readLine(); line != null; line = reader + .readLine()) { + String dataLine = line.trim(); + if (StringUtils.isEmpty(dataLine) || dataLine.startsWith("#")) { + continue; + } + int index = dataLine.indexOf("="); + if (index == -1) { + log.warn("the config data is invalid {}", dataLine); + continue; + } + result.put(dataLine.substring(0, index), dataLine.substring(index + 1)); + } + } + return result; } } diff --git a/spring-cloud-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/parser/NacosDataXmlParser.java b/spring-cloud-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/parser/NacosDataXmlParser.java index 7a9c45d60..eab890b9b 100644 --- a/spring-cloud-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/parser/NacosDataXmlParser.java +++ b/spring-cloud-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/parser/NacosDataXmlParser.java @@ -18,9 +18,8 @@ package com.alibaba.cloud.nacos.parser; import java.io.IOException; import java.io.StringReader; -import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.Map; -import java.util.Properties; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; @@ -46,17 +45,17 @@ public class NacosDataXmlParser extends AbstractNacosDataParser { } @Override - protected Properties doParse(String data) throws IOException { + protected Map doParse(String data) throws IOException { if (StringUtils.isEmpty(data)) { return null; } Map map = parseXml2Map(data); - return this.generateProperties(this.reloadMap(map)); + return this.reloadMap(map); } private Map parseXml2Map(String xml) throws IOException { xml = xml.replaceAll("\\r", "").replaceAll("\\n", "").replaceAll("\\t", ""); - Map map = new HashMap<>(32); + Map map = new LinkedHashMap<>(32); try { DocumentBuilder documentBuilder = DocumentBuilderFactory.newInstance() .newDocumentBuilder(); diff --git a/spring-cloud-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/parser/NacosDataYamlParser.java b/spring-cloud-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/parser/NacosDataYamlParser.java index c96105f39..b963a0971 100644 --- a/spring-cloud-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/parser/NacosDataYamlParser.java +++ b/spring-cloud-alibaba-nacos-config/src/main/java/com/alibaba/cloud/nacos/parser/NacosDataYamlParser.java @@ -16,9 +16,10 @@ package com.alibaba.cloud.nacos.parser; -import java.util.Properties; +import java.util.LinkedHashMap; +import java.util.Map; -import org.springframework.beans.factory.config.YamlPropertiesFactoryBean; +import org.springframework.beans.factory.config.YamlMapFactoryBean; import org.springframework.core.io.ByteArrayResource; /** @@ -31,10 +32,13 @@ public class NacosDataYamlParser extends AbstractNacosDataParser { } @Override - protected Properties doParse(String data) { - YamlPropertiesFactoryBean yamlFactory = new YamlPropertiesFactoryBean(); + protected Map doParse(String data) { + YamlMapFactoryBean yamlFactory = new YamlMapFactoryBean(); yamlFactory.setResources(new ByteArrayResource(data.getBytes())); - return yamlFactory.getObject(); + + Map result = new LinkedHashMap<>(); + flattenedMap(result, yamlFactory.getObject(), EMPTY_STRING); + return result; } }