/* * 文件名称: ConfigsParseHelper.java * 版权信息: Copyright 2001-2011 ZheJiang Collaboration Data System Co., LTD. All right reserved. * ---------------------------------------------------------------------------------------------- * 修改历史: * ---------------------------------------------------------------------------------------------- * 修改原因: 新增 * 修改人员: LuoJingtian * 修改日期: 2011-12-19 * 修改内容: */ package com.mfh.comn.config; import org.slf4j.Logger; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; /** * 配置项入口UConfig.xml解析类, 包级私有, 不允许包外访问. 统一配置入口固定为classpath路径的uconfig.xml. 配置样例:<BR> * <pre> * <configs> * <config domain="COM.SHK.COMMON" description="DESC" merge-rule="default"> * <default type="properties" location="jdbc.properties"/> * <extends type="properties" location="/WEB-INF/classes/jdbc2.properties"/> * <extends type="properties" location="/WEB-INF/classes/jdbc3.properties"/> * </config> * </configs> * </pre> * * @author <a href="mailto:luojt@zjcds.com">LuoJingtian</a> created on 2011-12-19 * @since chch Framework 1.0 */ public class ConfigsParseHelper { /** 日志记录器 */ private static Logger logger = org.slf4j.LoggerFactory.getLogger(ConfigsParseHelper.class); public final static ThreadLocal<String> configLocal = new ThreadLocal<>();//使用哪个配置文件 private static Map<String, Document> configDomFull = new HashMap<>();//uConfig.xml总配置文件的缓存。 public static final String configAlias = "uconfig.xml";//统一配置文件 /** * 初始化 * @param configAlias 统一配置文件区别标识,整个操作系统可以支持多个 * @param stream 文件流 * @author zhangyz created on 2013-5-25 */ public static void init(String configAlias, InputStream stream) { try { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder docBuilder = factory.newDocumentBuilder(); String key = configAlias; if (configLocal.get() != null) key = configLocal.get(); Document doc = configDomFull.get(key); if (doc == null){ doc = docBuilder.parse(stream); configDomFull.put(key, doc); } } catch(Exception ex) { throw new RuntimeException("解析统一配置文件入口失败!"); } finally { if (stream != null) try { stream.close(); } catch (IOException e) { e.printStackTrace(); } } } /** * 获取所有统一配置项信息 * * @return 所有统一配置项信息 Key=Domain * @author LuoJingtian created on 2011-12-20 * @since chch Framework 1.0 */ public static Map<String, ConfigItem> getConfigs(String configAlias) { Map<String, ConfigItem> configs = new HashMap<String, ConfigItem>(); try { Document doc = getUConfigXmlDocument(configAlias); NodeList configNodes = doc.getDocumentElement().getElementsByTagName("config"); Element configElem; for (int i = 0; i < configNodes.getLength(); i++) { configElem = (Element) configNodes.item(i); ConfigItem configItem = parseConfigItem(configElem); if (configItem != null) configs.put(configItem.getDomain(), configItem); } } catch (ParserConfigurationException e) { logger.error("解析统一配置入口文件失败, 不能创建解析器.", e); throw new RuntimeException("解析统一配置入口文件失败, 不能创建解析器.", e); } catch (SAXException e) { logger.error("解析统一配置入口文件失败, 文件格式不正确.", e); throw new RuntimeException("解析统一配置入口文件失败, 文件格式不正确.", e); } catch (IOException e) { logger.error("解析统一配置入口文件失败.", e); throw new RuntimeException("解析统一配置入口文件失败.", e); } catch (Exception e) { logger.error("解析统一配置入口文件失败.", e); throw new RuntimeException("解析统一配置入口文件失败.", e); } return configs; } /** * 获取统一配置项的实现类定义 * @param configAlias * @return * @author zhangyz created on 2013-5-25 */ @SuppressWarnings("unchecked") public static ConfigClass getConfigClass(String configAlias) { ConfigClass configClass = new ConfigClass(); Map<String, Class<SingleConfiguration>> propClassMap = new HashMap<String, Class<SingleConfiguration>> (); try { Document doc = getUConfigXmlDocument(configAlias); Element classNode; NodeList classNodes = doc.getDocumentElement().getElementsByTagName("class"); if (classNodes.getLength() > 0) { Element classEle = (Element)classNodes.item(0); String uclassName = classEle.getAttribute("uconfig"); configClass.setUconfigClass((Class<UConfig>)Class.forName(uclassName)); classNodes = classEle.getElementsByTagName("item"); for (int ii = 0; ii < classNodes.getLength(); ii++) { classNode = (Element) classNodes.item(ii); String fileType = classNode.getAttribute("type"); String domainClass = classNode.getTextContent(); Class<SingleConfiguration> classItem = (Class<SingleConfiguration>)Class.forName(domainClass); propClassMap.put(fileType, classItem); } } configClass.setConfigDomainClass(propClassMap); return configClass; } catch (Exception e) { logger.error("解析统一配置入口文件失败.", e); throw new RuntimeException("解析统一配置入口文件失败.", e); } } /** * 获取所有统一配置项信息 * * @return 所有统一配置项信息 Key=Domain * @author LuoJingtian created on 2011-12-20 * @since chch Framework 1.0 */ public static ConfigItem getConfig(String domain, String configAlias) { ConfigItem configItem = null; try { Document doc = getUConfigXmlDocument(configAlias); NodeList configNodes = doc.getDocumentElement().getElementsByTagName("config"); Element configElem; for (int i = 0; i < configNodes.getLength(); i++) { configElem = (Element) configNodes.item(i); if (configElem.getAttribute("domain").equalsIgnoreCase(domain)) { configItem = parseConfigItem(configElem); break; } } } catch (ParserConfigurationException e) { logger.error("解析统一配置入口文件失败, 不能创建解析器.", e); throw new RuntimeException("解析统一配置入口文件失败, 不能创建解析器.", e); } catch (SAXException e) { logger.error("解析统一配置入口文件失败, 文件格式不正确.", e); throw new RuntimeException("解析统一配置入口文件失败, 文件格式不正确.", e); } catch (IOException e) { e.printStackTrace(); logger.error("解析统一配置入口文件失败.", e); throw new RuntimeException("解析统一配置入口文件失败.", e); } catch (Exception e) { logger.error("解析统一配置入口文件失败.", e); throw new RuntimeException("解析统一配置入口文件失败.", e); } return configItem; } /** * 获取UConfig XML文档对象, uconfig.xml必须在classpath路径下 * @return UConfig XML文档对象 * @throws ParserConfigurationException * @throws SAXException * @throws IOException * @author LuoJingtian created on 2011-12-22 * @since chch Framework 1.0 */ private static Document getUConfigXmlDocument(String configAlias) throws ParserConfigurationException, SAXException, IOException { if (configLocal.get() != null) return configDomFull.get(configLocal.get()); else return configDomFull.get(configAlias); } /** * 解析单个配置节点 * @param configElem 单个配置节点, /configs/config * @return * @author LuoJingtian created on 2011-12-21 * @since chch Framework 1.0 */ private static ConfigItem parseConfigItem(Element configElem) { ConfigItem configItem = new ConfigItem(); configItem.setDomain(configElem.getAttribute("domain")); configItem.setDescription(configElem.getAttribute("description")); configItem.setMergeRule(configElem.getAttribute("merge-rule")); NodeList defaults = configElem.getElementsByTagName("default"); if (defaults != null && defaults.getLength() > 0){ Element defalutElem = (Element) defaults.item(0); configItem.setDefaultLocation(parseConfigLocationItem(defalutElem)); configItem.setExtendsLocations(parseExtendsLocation(configElem)); return configItem; } else return null; } /** * 解析扩展配置节点元素 * * @param configElem 配置节点 /configs/config/extends * @return 扩展配置信息 * @author LuoJingtian created on 2011-12-19 * @since chch Framework 1.0 */ private static List<ConfigLocationItem> parseExtendsLocation(Element configElem) { NodeList extedsNodes = configElem.getElementsByTagName("extends"); int extendsCount = extedsNodes.getLength(); List<ConfigLocationItem> extendsLocations = new ArrayList<ConfigLocationItem>(extendsCount); Element extendsElem; for (int i = 0; i < extendsCount; i++) { extendsElem = (Element) extedsNodes.item(i); extendsLocations.add(parseConfigLocationItem(extendsElem)); } return extendsLocations == null ? new ArrayList<ConfigLocationItem>(0) : extendsLocations; } /** * 解析单个配置项 * * @param configLocationElem 配置位置节点 * @return 配置位置项信息 * @author LuoJingtian created on 2011-12-20 * @since chch Framework 1.0 */ private static ConfigLocationItem parseConfigLocationItem(Element configLocationElem) { ConfigLocationItem configLocationItem = new ConfigLocationItem(); configLocationItem.setType(configLocationElem.getAttribute("type")); configLocationItem.setLocation(configLocationElem.getAttribute("location")); configLocationItem.setParser(configLocationElem.getAttribute("parser"));//针对xml类型的 return configLocationItem; } }