package com.smtservlet.util; import java.io.ByteArrayInputStream; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.net.URI; import java.net.URL; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import org.dom4j.Attribute; import org.dom4j.Document; import org.dom4j.Element; import org.dom4j.Node; import org.dom4j.io.SAXReader; import org.springframework.core.io.Resource; public class SMTMergeSpringXml { public static class BeanXmlResource implements Resource { private String _xmlString; public BeanXmlResource(String xmlString) throws Exception { _xmlString = xmlString; } @Override public InputStream getInputStream() throws IOException { return new ByteArrayInputStream(_xmlString.getBytes("UTF-8")); } @Override public boolean exists() { return true; } @Override public URL getURL() throws IOException { return null; } @Override public URI getURI() throws IOException { return null; } @Override public File getFile() throws IOException { return null; } @Override public long contentLength() throws IOException { return 0; } @Override public long lastModified() throws IOException { return 0; } @Override public Resource createRelative(String relativePath) throws IOException { return null; } @Override public String getFilename() { return null; } @Override public String getDescription() { return "BeanXmlResource"; } } private static class BeanXmlInfo { public String _beanId; public Class _beanClz; public Map _mapNameToAttr = new LinkedHashMap(); public Map _mapNameToProp = new LinkedHashMap(); public BeanXmlInfo(String beanId, String beanClz, Element xmlBean) throws Exception { _beanId = beanId; _beanClz = Class.forName(beanClz); // 读取本节点所有attr int attrCount = xmlBean.attributeCount(); for(int i = 0; i < attrCount; i ++) { Attribute attr = xmlBean.attribute(i); _mapNameToAttr.put(attr.getName(), attr.asXML()); } // 读取所有子节点 for (Iterator iterInner = xmlBean.nodeIterator(); iterInner.hasNext();) { // 如果当前不是节点则忽略(忽略注释,文本之类内容) Node xmlNode = iterInner.next(); if(xmlNode.getNodeType() != Node.ELEMENT_NODE) continue; if(!"property".equals(xmlNode.getName())) throw new Exception("find bean not preoprty : " + xmlNode.getName()); Element xmlProp = (Element) xmlNode; String propName = xmlProp.attribute("name").getValue(); _mapNameToProp.put(propName, xmlProp.asXML()); } } public String asXML() { StringBuilder sbXML = new StringBuilder(); sbXML.append("\n"); for(String propXml : _mapNameToProp.values()) { sbXML.append(propXml); sbXML.append("\n"); } sbXML.append("\n"); return sbXML.toString(); } } private StringBuilder _sbXml; private Set _setDeletedBeans = new HashSet(); private Map> _mapBeanId2ClzName2XmlInfo = new HashMap>(); public SMTMergeSpringXml() { _sbXml = new StringBuilder(); _sbXml.append( "\r\n" + "\n"); } public Resource finishXML() throws Exception { // 删除不需要的bean for(String beanId : _setDeletedBeans) { _mapBeanId2ClzName2XmlInfo.remove(beanId); } // 合并生成bean for(Entry> entry : _mapBeanId2ClzName2XmlInfo.entrySet()) { BeanXmlInfo beanXmlInfo = findLastBean(entry.getValue()); if(beanXmlInfo == null) continue; _sbXml.append(beanXmlInfo.asXML()); } _sbXml.append("\n"); return new BeanXmlResource(_sbXml.toString()); } private BeanXmlInfo findLastBean(Map beanMap) throws Exception { BeanXmlInfo[] listBeans = new BeanXmlInfo[beanMap.size()]; // 扫描所有的bean,统计继承次数 for(BeanXmlInfo curBean : beanMap.values()) { int count = 0; // 检查bean的继承次数 for(BeanXmlInfo checkBean : beanMap.values()) { if(checkBean._beanClz.isAssignableFrom(curBean._beanClz)) count ++; } if(listBeans[count - 1] != null) throw new Exception("find dup level bean class : " + curBean._beanId + " : " + curBean._beanClz.getName()); listBeans[count - 1] = curBean; } // 将属性进行合并 BeanXmlInfo lastBeans = listBeans[listBeans.length - 1]; for(int i = listBeans.length - 2; i >= 0; i --) { for(Entry entry : listBeans[i]._mapNameToProp.entrySet()) { String propName = entry.getKey(); if(!lastBeans._mapNameToProp.containsKey(propName)) lastBeans._mapNameToProp.put(propName, entry.getValue()); } } return lastBeans; } public void mergeXml(InputStream is) throws Exception { //boolean b = Object.class.isAssignableFrom(String.class); SAXReader reader=new SAXReader(); Document doc=reader.read(is); Element xmlBeans = (Element) doc.selectSingleNode("beans"); for (Iterator iterInner = xmlBeans.nodeIterator(); iterInner.hasNext();) { // 如果当前不是节点则忽略(忽略注释,文本之类内容) Node xmlNode = iterInner.next(); if(xmlNode.getNodeType() != Node.ELEMENT_NODE) continue; // 如果当前不是bean,则直接插入 Element xmlBean = (Element) xmlNode; if(!"bean".equals(xmlBean.getName())) { _sbXml.append(xmlBean.asXML()); continue; } // 如果当前bean不存在id, 则直接插入 Attribute attrId = xmlBean.attribute("id"); if(attrId == null) { _sbXml.append(xmlBean.asXML()); continue; } String beanId = attrId.getText(); // 如果当前bean不存在class, 则直接插入 Attribute attrClz = xmlBean.attribute("class"); if(attrClz == null) { _sbXml.append(xmlBean.asXML()); continue; } String clzName = attrClz.getText(); if("deleteBean".equals(clzName)) { _setDeletedBeans.add(beanId); continue; } // 获取class映射表 Map mapClzName2XmlInfo = _mapBeanId2ClzName2XmlInfo.get(beanId); if(mapClzName2XmlInfo == null) { mapClzName2XmlInfo = new HashMap(); _mapBeanId2ClzName2XmlInfo.put(beanId, mapClzName2XmlInfo); } // 创建item BeanXmlInfo beanXmlInfo = new BeanXmlInfo(beanId, clzName, xmlBean); mapClzName2XmlInfo.put(clzName, beanXmlInfo); } } }