package li.util; import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; import java.io.InputStreamReader; import java.net.URISyntaxException; import java.util.ArrayList; import java.util.List; import java.util.Properties; import javax.xml.namespace.QName; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.xpath.XPathConstants; import javax.xml.xpath.XPathFactory; import org.w3c.dom.Document; import org.w3c.dom.NodeList; /** * 文件工具类 * * @author li (limingwei@mail.com) * @version 0.1.5 (2012-05-08) */ public class Files { private static final Log log = Log.init(); private static final String CONST_CONFIG_REGEX = "^.*(config|ioc|aop|const)\\.xml$"; private static final String PROPERTIES_REGEX = "^.*\\.properties$"; /** * 返回项目的classes目录 */ public static File root() { try { return new File(Thread.currentThread().getContextClassLoader().getResource("").toURI().getPath()); } catch (URISyntaxException e) { throw new RuntimeException(e + " ", e); } } /** * 根据文件名正则表达式搜索一个路径下的文件,返回文件路径的List * * @param file 要搜索的目录 * @param regex 要求文件路径要符合的正则表达式 * @param increase 是否递进搜索 * @param fileOrFloder 1 文件 2 文件夹 * @return 文件绝对路径列表 */ public static List<String> list(File file, String regex, Boolean increase, Integer fileOrFloder) { List<String> list = new ArrayList<String>(); if (((1 == fileOrFloder && file.isFile()) || (2 == fileOrFloder && file.isDirectory())) && Verify.regex(file.getPath(), regex)) { list.add(file.getPath()); } else if (increase && file.isDirectory()) { File[] files = file.listFiles(); for (File f : files) { list.addAll(list(f, regex, increase, fileOrFloder)); // 递归调用本方法 } } return list; } /** * 根据文件路径path构建一个org.w3c.dom.Document * * @param path XML文件路径,相对于classPath的相对路径 */ public static Document build(String path) { try { DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); documentBuilderFactory.setNamespaceAware(true); return documentBuilderFactory.newDocumentBuilder().parse(path); } catch (Exception e) { log.error("? Files.build() path=?", e, path); return null; } } /** * 根据xpath表达式和returnType从document中读取值 * * @param document 被XPath解析的对象,Object类型,可以是Document,NodeList等 * @param returnType XPathConstants枚举中的值,表示返回类型 */ public static Object xpath(Object document, String xpath, QName returnType) { try { return XPathFactory.newInstance().newXPath().compile(xpath).evaluate(document, returnType); } catch (Exception e) { log.error("? Files.xpath() document:? xpath:? returnType:?", e, document, xpath, returnType); return null; } } /** * 搜索并返回文件名包含 name的 Properties的并集,有缓存的 */ public static Properties load(String name) { Properties properties = (Properties) Log.get("~!@#PROPERTIES#" + name);// 从缓存中查找properties if (null == properties) { List<String> propertyFiles = (List<String>) Log.get("~!@#PROPERTIE_FILES");// 从缓存中查找propertyFiles if (null == propertyFiles) { File rootFolder = Files.root(); propertyFiles = list(rootFolder, PROPERTIES_REGEX, true, 1); Log.put("~!@#PROPERTIE_FILES", propertyFiles); // 将 PROPERTIES文件列表缓存 log.info("Found ? properties files , at ?", propertyFiles.size(), rootFolder); } properties = new Properties(); for (Object filePath : propertyFiles) { if (Verify.contain((String) filePath, name)) { try { Properties prop = new Properties(); prop.load(new InputStreamReader(new BufferedInputStream(new FileInputStream((String) filePath)), "UTF-8")); properties.putAll(prop); } catch (Exception e) { throw new RuntimeException(e + " ", e); } } } Log.put("~!@#PROPERTIES#" + name, properties);// 将 properties 缓存 } return properties; } /** * 返回框架的常量配置项,来自config.properties和xml const */ public static Properties config() { Properties config = (Properties) Log.get("~!@#CONFIG");// 从缓存中查找properties if (null == config) { log.info("reading configs, from properties and xml ..."); config = Files.load("config.properties"); List<String> fileList = Files.list(Files.root(), CONST_CONFIG_REGEX, true, 1);// 搜索配置文件 for (String filePath : fileList) { NodeList beanNodes = (NodeList) Files.xpath(Files.build(filePath), "//const", XPathConstants.NODESET); for (int length = (null == beanNodes ? -1 : beanNodes.getLength()), i = 0; i < length; i++) { String name = Files.xpath(beanNodes.item(i), "@name", XPathConstants.STRING) + ""; String value = Files.xpath(beanNodes.item(i), "@value", XPathConstants.STRING) + ""; config.setProperty(name, value); } } Log.put("~!@#CONFIG", config);// 将 properties 缓存 } return config; } }