All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.alibaba.cloud.nacos.parser.NacosXmlPropertySourceLoader Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2013-2023 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 javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import com.alibaba.cloud.nacos.utils.StringUtils;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import org.springframework.boot.env.OriginTrackedMapPropertySource;
import org.springframework.boot.env.PropertiesPropertySourceLoader;
import org.springframework.core.Ordered;
import org.springframework.core.env.PropertySource;
import org.springframework.core.io.Resource;

/**
 * Parsing for XML requires overwriting the default
 * {@link PropertiesPropertySourceLoader}, because it internally rigorously validates
 * ({@code DOCTYPE}) THE XML in a way that makes it difficult to customize the
 * configuration; at finally, make sure it's in the first place.
 *
 * @author zkz
 */
public class NacosXmlPropertySourceLoader extends AbstractPropertySourceLoader
		implements Ordered {

	/**
	 * Get the order value of this object.
	 * 

* Higher values are interpreted as lower priority. As a consequence, the object with * the lowest value has the highest priority (somewhat analogous to Servlet * {@code load-on-startup} values). *

* Same order values will result in arbitrary sort positions for the affected objects. * @return the order value * @see #HIGHEST_PRECEDENCE * @see #LOWEST_PRECEDENCE */ @Override public int getOrder() { return Integer.MIN_VALUE; } /** * Returns the file extensions that the loader supports (excluding the '.'). * @return the file extensions */ @Override public String[] getFileExtensions() { return new String[] { "xml" }; } /** * 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 protected List> doLoad(String name, Resource resource) throws IOException { Map nacosDataMap = parseXml2Map(resource); return Collections.singletonList( new OriginTrackedMapPropertySource(name, nacosDataMap, true)); } private Map parseXml2Map(Resource resource) throws IOException { Map map = new LinkedHashMap<>(32); try { DocumentBuilder documentBuilder = DocumentBuilderFactory.newInstance() .newDocumentBuilder(); Document document = documentBuilder.parse(resource.getInputStream()); 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 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 + AbstractPropertySourceLoader.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 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(AbstractPropertySourceLoader.DOT, parentKey, node.getNodeName()), node.getNodeValue()); } } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy