[enhance issue #1492 ]Improved nacos configuration parsing, based on PropertySourceLoader
parent
7b42a9a31e
commit
c07701d98e
@ -1,175 +0,0 @@
|
||||
/*
|
||||
* Copyright 2013-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.cloud.nacos.parser;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* @author zkz
|
||||
*/
|
||||
public abstract class AbstractNacosDataParser {
|
||||
|
||||
protected static final String DOT = ".";
|
||||
|
||||
protected static final String VALUE = "value";
|
||||
|
||||
protected static final String EMPTY_STRING = "";
|
||||
|
||||
private String extension;
|
||||
|
||||
private AbstractNacosDataParser nextParser;
|
||||
|
||||
protected AbstractNacosDataParser(String extension) {
|
||||
if (StringUtils.isEmpty(extension)) {
|
||||
throw new IllegalArgumentException("extension cannot be empty");
|
||||
}
|
||||
this.extension = extension.toLowerCase();
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify dataId extensions.
|
||||
* @param extension file extension. json or xml or yml or yaml or properties
|
||||
* @return valid or not
|
||||
*/
|
||||
public final boolean checkFileExtension(String extension) {
|
||||
if (this.isLegal(extension.toLowerCase())) {
|
||||
return true;
|
||||
}
|
||||
if (this.nextParser == null) {
|
||||
return false;
|
||||
}
|
||||
return this.nextParser.checkFileExtension(extension);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Parsing nacos configuration content.
|
||||
* @param data config data from Nacos
|
||||
* @param extension file extension. json or xml or yml or yaml or properties
|
||||
* @return result of Properties
|
||||
* @throws IOException thrown if there is a problem parsing config.
|
||||
*/
|
||||
public final Map<String, Object> parseNacosData(String data, String extension)
|
||||
throws IOException {
|
||||
if (extension == null || extension.length() < 1) {
|
||||
throw new IllegalStateException("The file extension cannot be empty");
|
||||
}
|
||||
if (this.isLegal(extension.toLowerCase())) {
|
||||
return this.doParse(data);
|
||||
}
|
||||
if (this.nextParser == null) {
|
||||
throw new IllegalStateException(getTips(extension));
|
||||
}
|
||||
return this.nextParser.parseNacosData(data, extension);
|
||||
}
|
||||
|
||||
/**
|
||||
* Core logic for parsing.
|
||||
* @param data config from Nacos
|
||||
* @return result of Properties
|
||||
* @throws IOException thrown if there is a problem parsing config.
|
||||
*/
|
||||
protected abstract Map<String, Object> doParse(String data) throws IOException;
|
||||
|
||||
protected AbstractNacosDataParser setNextParser(AbstractNacosDataParser nextParser) {
|
||||
this.nextParser = nextParser;
|
||||
return this;
|
||||
}
|
||||
|
||||
public AbstractNacosDataParser addNextParser(AbstractNacosDataParser nextParser) {
|
||||
if (this.nextParser == null) {
|
||||
this.nextParser = nextParser;
|
||||
}
|
||||
else {
|
||||
this.nextParser.addNextParser(nextParser);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
protected boolean isLegal(String extension) {
|
||||
return this.extension.equalsIgnoreCase(extension)
|
||||
|| this.extension.contains(extension);
|
||||
}
|
||||
|
||||
protected void flattenedMap(Map<String, Object> result, Map<String, Object> dataMap,
|
||||
String parentKey) {
|
||||
Set<Map.Entry<String, Object>> entries = dataMap.entrySet();
|
||||
for (Iterator<Map.Entry<String, Object>> iterator = entries.iterator(); iterator
|
||||
.hasNext();) {
|
||||
Map.Entry<String, Object> 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<String, Object> map = (Map<String, Object>) value;
|
||||
flattenedMap(result, map, fullKey);
|
||||
continue;
|
||||
}
|
||||
else if (value instanceof Collection) {
|
||||
int count = 0;
|
||||
Collection<Object> collection = (Collection<Object>) value;
|
||||
for (Object object : collection) {
|
||||
flattenedMap(result,
|
||||
Collections.singletonMap("[" + (count++) + "]", object),
|
||||
fullKey);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
result.put(fullKey, value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reload the key ending in `value` if need.
|
||||
*/
|
||||
protected Map<String, Object> reloadMap(Map<String, Object> map) {
|
||||
if (map == null || map.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
Map<String, Object> result = new LinkedHashMap<>(map);
|
||||
for (Map.Entry<String, Object> entry : map.entrySet()) {
|
||||
String key = entry.getKey();
|
||||
if (key.contains(DOT)) {
|
||||
int idx = key.lastIndexOf(DOT);
|
||||
String suffix = key.substring(idx + 1);
|
||||
if (VALUE.equalsIgnoreCase(suffix)) {
|
||||
result.put(key.substring(0, idx), entry.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static String getTips(String fileName) {
|
||||
return String.format(
|
||||
"[%s] must contains file extension with properties|yaml|yml|xml|json",
|
||||
fileName);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,128 @@
|
||||
/*
|
||||
* Copyright 2013-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.cloud.nacos.parser;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.boot.env.PropertySourceLoader;
|
||||
import org.springframework.core.env.PropertySource;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import static com.alibaba.cloud.nacos.parser.NacosDataParserHandler.DOT;
|
||||
|
||||
/**
|
||||
* Nacos-specific loader, If need to support other methods of parsing,you need to do the
|
||||
* following steps:
|
||||
* <p>
|
||||
* 1.inherit {@link AbstractPropertySourceLoader} ;<br/>
|
||||
* 2. define the file{@code spring.factories} and append
|
||||
* {@code org.springframework.boot.env.PropertySourceLoader=..}; <br/>
|
||||
* 3.the last step validate.
|
||||
* </p>
|
||||
* Notice the use of {@link NacosByteArrayResource} .
|
||||
*
|
||||
* @author zkz
|
||||
*/
|
||||
public abstract class AbstractPropertySourceLoader implements PropertySourceLoader {
|
||||
|
||||
/**
|
||||
* Prevent interference with other loaders.Nacos-specific loader, unless the reload
|
||||
* changes it.
|
||||
* @param name
|
||||
* @param resource
|
||||
* @return
|
||||
*/
|
||||
protected boolean canLoad(String name, Resource resource) {
|
||||
return resource instanceof NacosByteArrayResource;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the resource into one or more property sources. Implementations may either
|
||||
* return a list containing a single source, or in the case of a multi-document format
|
||||
* such as yaml a source for each document in the resource.
|
||||
* @param name the root name of the property source. If multiple documents are loaded
|
||||
* an additional suffix should be added to the name for each source loaded.
|
||||
* @param resource the resource to load
|
||||
* @return a list property sources
|
||||
* @throws IOException if the source cannot be loaded
|
||||
*/
|
||||
@Override
|
||||
public List<PropertySource<?>> load(String name, Resource resource)
|
||||
throws IOException {
|
||||
if (!canLoad(name, resource)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return this.doLoad(name, resource);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the resource into one or more property sources. Implementations may either
|
||||
* return a list containing a single source, or in the case of a multi-document format
|
||||
* such as yaml a source for each document in the resource.
|
||||
* @param name the root name of the property source. If multiple documents are loaded
|
||||
* an additional suffix should be added to the name for each source loaded.
|
||||
* @param resource the resource to load
|
||||
* @return a list property sources
|
||||
* @throws IOException if the source cannot be loaded
|
||||
*/
|
||||
protected abstract List<PropertySource<?>> doLoad(String name, Resource resource)
|
||||
throws IOException;
|
||||
|
||||
protected void flattenedMap(Map<String, Object> result, Map<String, Object> dataMap,
|
||||
String parentKey) {
|
||||
if (dataMap == null || dataMap.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
Set<Entry<String, Object>> entries = dataMap.entrySet();
|
||||
for (Iterator<Entry<String, Object>> iterator = entries.iterator(); iterator
|
||||
.hasNext();) {
|
||||
Map.Entry<String, Object> 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<String, Object> map = (Map<String, Object>) value;
|
||||
flattenedMap(result, map, fullKey);
|
||||
continue;
|
||||
}
|
||||
else if (value instanceof Collection) {
|
||||
int count = 0;
|
||||
Collection<Object> collection = (Collection<Object>) value;
|
||||
for (Object object : collection) {
|
||||
flattenedMap(result,
|
||||
Collections.singletonMap("[" + (count++) + "]", object),
|
||||
fullKey);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
result.put(fullKey, value);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright 2013-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.cloud.nacos.parser;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
import org.springframework.boot.env.OriginTrackedMapPropertySource;
|
||||
import org.springframework.core.env.PropertySource;
|
||||
import org.springframework.core.io.Resource;
|
||||
|
||||
import static com.alibaba.cloud.nacos.parser.NacosDataParserHandler.DOT;
|
||||
import static com.alibaba.cloud.nacos.parser.NacosDataParserHandler.VALUE;
|
||||
|
||||
/**
|
||||
* @author zkz
|
||||
*/
|
||||
public class JsonPropertySourceLoader extends AbstractPropertySourceLoader {
|
||||
|
||||
/**
|
||||
* Returns the file extensions that the loader supports (excluding the '.').
|
||||
* @return the file extensions
|
||||
*/
|
||||
@Override
|
||||
public String[] getFileExtensions() {
|
||||
return new String[] { "json" };
|
||||
}
|
||||
|
||||
/**
|
||||
* @param name
|
||||
* @param resource
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
protected List<PropertySource<?>> doLoad(String name, Resource resource)
|
||||
throws IOException {
|
||||
Map<String, Object> result = new LinkedHashMap<>(32);
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
Map<String, Object> nacosDataMap = mapper.readValue(resource.getInputStream(),
|
||||
LinkedHashMap.class);
|
||||
flattenedMap(result, this.reloadMap(nacosDataMap), null);
|
||||
return Collections.singletonList(
|
||||
new OriginTrackedMapPropertySource(name, nacosDataMap, true));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Reload the key ending in `value` if need.
|
||||
*/
|
||||
protected Map<String, Object> reloadMap(Map<String, Object> map) {
|
||||
if (map == null || map.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
Map<String, Object> result = new LinkedHashMap<>(map);
|
||||
for (Map.Entry<String, Object> entry : map.entrySet()) {
|
||||
String key = entry.getKey();
|
||||
if (key.contains(DOT)) {
|
||||
int idx = key.lastIndexOf(DOT);
|
||||
String suffix = key.substring(idx + 1);
|
||||
if (VALUE.equalsIgnoreCase(suffix)) {
|
||||
result.put(key.substring(0, idx), entry.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright 2013-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.cloud.nacos.parser;
|
||||
|
||||
import org.springframework.core.io.ByteArrayResource;
|
||||
|
||||
/**
|
||||
* Nacos-specific resource
|
||||
*
|
||||
* @author zkz
|
||||
*/
|
||||
public class NacosByteArrayResource extends ByteArrayResource {
|
||||
|
||||
private String filename;
|
||||
|
||||
/**
|
||||
* Create a new {@code ByteArrayResource}.
|
||||
* @param byteArray the byte array to wrap
|
||||
*/
|
||||
public NacosByteArrayResource(byte[] byteArray) {
|
||||
super(byteArray);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@code ByteArrayResource} with a description.
|
||||
* @param byteArray the byte array to wrap
|
||||
* @param description where the byte array comes from
|
||||
*/
|
||||
public NacosByteArrayResource(byte[] byteArray, String description) {
|
||||
super(byteArray, description);
|
||||
}
|
||||
|
||||
public void setFilename(String filename) {
|
||||
this.filename = filename;
|
||||
}
|
||||
|
||||
/**
|
||||
* This implementation always returns {@code null}, assuming that this resource type
|
||||
* does not have a filename.
|
||||
*/
|
||||
@Override
|
||||
public String getFilename() {
|
||||
return null == this.filename ? this.getDescription() : this.filename;
|
||||
}
|
||||
|
||||
}
|
@ -1,66 +0,0 @@
|
||||
/*
|
||||
* Copyright 2013-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.cloud.nacos.parser;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* @author zkz
|
||||
* @author yuhuangbin
|
||||
*/
|
||||
public class NacosDataJsonParser extends AbstractNacosDataParser {
|
||||
|
||||
protected NacosDataJsonParser() {
|
||||
super("json");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Map<String, Object> doParse(String data) throws IOException {
|
||||
if (StringUtils.isEmpty(data)) {
|
||||
return null;
|
||||
}
|
||||
Map<String, Object> map = parseJSON2Map(data);
|
||||
return this.reloadMap(map);
|
||||
}
|
||||
|
||||
/**
|
||||
* JSON to Map.
|
||||
* @param json json data
|
||||
* @return the map convert by json string
|
||||
* @throws IOException thrown if there is a problem parsing config.
|
||||
*/
|
||||
private Map<String, Object> parseJSON2Map(String json) throws IOException {
|
||||
Map<String, Object> result = new LinkedHashMap<>(32);
|
||||
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
Map<String, Object> nacosDataMap = mapper.readValue(json, LinkedHashMap.class);
|
||||
|
||||
if (CollectionUtils.isEmpty(nacosDataMap)) {
|
||||
return result;
|
||||
}
|
||||
flattenedMap(result, nacosDataMap, EMPTY_STRING);
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
@ -1,66 +0,0 @@
|
||||
/*
|
||||
* Copyright 2013-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.cloud.nacos.parser;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.StringReader;
|
||||
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 Map<String, Object> doParse(String data) throws IOException {
|
||||
Map<String, Object> 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;
|
||||
}
|
||||
String key = dataLine.substring(0, index);
|
||||
String value = dataLine.substring(index + 1);
|
||||
result.put(key.trim(), value.trim());
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
@ -1,129 +0,0 @@
|
||||
/*
|
||||
* Copyright 2013-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.cloud.nacos.parser;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.StringReader;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.NamedNodeMap;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
import org.xml.sax.InputSource;
|
||||
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* With relatively few usage scenarios, only simple parsing is performed to reduce jar
|
||||
* dependencies.
|
||||
*
|
||||
* @author zkz
|
||||
*/
|
||||
public class NacosDataXmlParser extends AbstractNacosDataParser {
|
||||
|
||||
public NacosDataXmlParser() {
|
||||
super("xml");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Map<String, Object> doParse(String data) throws IOException {
|
||||
if (StringUtils.isEmpty(data)) {
|
||||
return null;
|
||||
}
|
||||
Map<String, Object> map = parseXml2Map(data);
|
||||
return this.reloadMap(map);
|
||||
}
|
||||
|
||||
private Map<String, Object> parseXml2Map(String xml) throws IOException {
|
||||
xml = xml.replaceAll("\\r", "").replaceAll("\\n", "").replaceAll("\\t", "");
|
||||
Map<String, Object> map = new LinkedHashMap<>(32);
|
||||
try {
|
||||
DocumentBuilder documentBuilder = DocumentBuilderFactory.newInstance()
|
||||
.newDocumentBuilder();
|
||||
Document document = documentBuilder
|
||||
.parse(new InputSource(new StringReader(xml)));
|
||||
if (null == document) {
|
||||
return null;
|
||||
}
|
||||
parseNodeList(document.getChildNodes(), map, "");
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new IOException("The xml content parse error.", e.getCause());
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
private void parseNodeList(NodeList nodeList, Map<String, Object> map,
|
||||
String parentKey) {
|
||||
if (nodeList == null || nodeList.getLength() < 1) {
|
||||
return;
|
||||
}
|
||||
parentKey = parentKey == null ? "" : parentKey;
|
||||
for (int i = 0; i < nodeList.getLength(); i++) {
|
||||
Node node = nodeList.item(i);
|
||||
String value = node.getNodeValue();
|
||||
value = value == null ? "" : value.trim();
|
||||
String name = node.getNodeName();
|
||||
name = name == null ? "" : name.trim();
|
||||
|
||||
if (StringUtils.isEmpty(name)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String key = StringUtils.isEmpty(parentKey) ? name : parentKey + DOT + name;
|
||||
NamedNodeMap nodeMap = node.getAttributes();
|
||||
parseNodeAttr(nodeMap, map, key);
|
||||
if (node.getNodeType() == Node.ELEMENT_NODE && node.hasChildNodes()) {
|
||||
parseNodeList(node.getChildNodes(), map, key);
|
||||
continue;
|
||||
}
|
||||
if (value.length() < 1) {
|
||||
continue;
|
||||
}
|
||||
map.put(parentKey, value);
|
||||
}
|
||||
}
|
||||
|
||||
private void parseNodeAttr(NamedNodeMap nodeMap, Map<String, Object> map,
|
||||
String parentKey) {
|
||||
if (null == nodeMap || nodeMap.getLength() < 1) {
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < nodeMap.getLength(); i++) {
|
||||
Node node = nodeMap.item(i);
|
||||
if (null == node) {
|
||||
continue;
|
||||
}
|
||||
if (node.getNodeType() == Node.ATTRIBUTE_NODE) {
|
||||
if (StringUtils.isEmpty(node.getNodeName())) {
|
||||
continue;
|
||||
}
|
||||
if (StringUtils.isEmpty(node.getNodeValue())) {
|
||||
continue;
|
||||
}
|
||||
map.put(String.join(DOT, parentKey, node.getNodeName()),
|
||||
node.getNodeValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,44 +0,0 @@
|
||||
/*
|
||||
* Copyright 2013-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.cloud.nacos.parser;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.beans.factory.config.YamlMapFactoryBean;
|
||||
import org.springframework.core.io.ByteArrayResource;
|
||||
|
||||
/**
|
||||
* @author zkz
|
||||
*/
|
||||
public class NacosDataYamlParser extends AbstractNacosDataParser {
|
||||
|
||||
public NacosDataYamlParser() {
|
||||
super(",yml,yaml,");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Map<String, Object> doParse(String data) {
|
||||
YamlMapFactoryBean yamlFactory = new YamlMapFactoryBean();
|
||||
yamlFactory.setResources(new ByteArrayResource(data.getBytes()));
|
||||
|
||||
Map<String, Object> result = new LinkedHashMap<>();
|
||||
flattenedMap(result, yamlFactory.getObject(), EMPTY_STRING);
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue