📄 xmlproperties.java
字号:
/** * $RCSfile$ * $Revision: 5867 $ * $Date: 2006-10-26 16:53:30 -0700 (Thu, 26 Oct 2006) $ * * Copyright (C) 2004 Jive Software. All rights reserved. * * This software is published under the terms of the GNU Public License (GPL), * a copy of which is included in this distribution. */package org.jivesoftware.util;import org.dom4j.CDATA;import org.dom4j.Document;import org.dom4j.Element;import org.dom4j.Node;import org.dom4j.io.OutputFormat;import org.dom4j.io.SAXReader;import java.io.*;import java.util.*;/** * Provides the the ability to use simple XML property files. Each property is * in the form X.Y.Z, which would map to an XML snippet of: * <pre> * <X> * <Y> * <Z>someValue</Z> * </Y> * </X> * </pre> * <p/> * The XML file is passed in to the constructor and must be readable and * writtable. Setting property values will automatically persist those value * to disk. The file encoding used is UTF-8. * * @author Derek DeMoro * @author Iain Shigeoka */public class XMLProperties { private File file; private Document document; /** * Parsing the XML file every time we need a property is slow. Therefore, * we use a Map to cache property values that are accessed more than once. */ private Map<String, String> propertyCache = new HashMap<String, String>(); /** * Creates a new XMLPropertiesTest object. * * @param fileName the full path the file that properties should be read from * and written to. * @throws IOException if an error occurs loading the properties. */ public XMLProperties(String fileName) throws IOException { this(new File(fileName)); } /** * Loads XML properties from a stream. * * @param in the input stream of XML. * @throws IOException if an exception occurs when reading the stream. */ public XMLProperties(InputStream in) throws IOException { Reader reader = new BufferedReader(new InputStreamReader(in)); buildDoc(reader); } /** * Creates a new XMLPropertiesTest object. * * @param file the file that properties should be read from and written to. * @throws IOException if an error occurs loading the properties. */ public XMLProperties(File file) throws IOException { this.file = file; if (!file.exists()) { // Attempt to recover from this error case by seeing if the // tmp file exists. It's possible that the rename of the // tmp file failed the last time Jive was running, // but that it exists now. File tempFile; tempFile = new File(file.getParentFile(), file.getName() + ".tmp"); if (tempFile.exists()) { Log.error("WARNING: " + file.getName() + " was not found, but temp file from " + "previous write operation was. Attempting automatic recovery." + " Please check file for data consistency."); tempFile.renameTo(file); } // There isn't a possible way to recover from the file not // being there, so throw an error. else { throw new FileNotFoundException("XML properties file does not exist: " + file.getName()); } } // Check read and write privs. if (!file.canRead()) { throw new IOException("XML properties file must be readable: " + file.getName()); } if (!file.canWrite()) { throw new IOException("XML properties file must be writable: " + file.getName()); } FileReader reader = new FileReader(file); buildDoc(reader); } /** * Returns the value of the specified property. * * @param name the name of the property to get. * @return the value of the specified property. */ public synchronized String getProperty(String name) { String value = propertyCache.get(name); if (value != null) { return value; } String[] propName = parsePropertyName(name); // Search for this property by traversing down the XML heirarchy. Element element = document.getRootElement(); for (int i = 0; i < propName.length; i++) { element = element.element(propName[i]); if (element == null) { // This node doesn't match this part of the property name which // indicates this property doesn't exist so return null. return null; } } // At this point, we found a matching property, so return its value. // Empty strings are returned as null. value = element.getTextTrim(); if ("".equals(value)) { return null; } else { // Add to cache so that getting property next time is fast. propertyCache.put(name, value); return value; } } /** * Return all values who's path matches the given property * name as a String array, or an empty array if the if there * are no children. This allows you to retrieve several values * with the same property name. For example, consider the * XML file entry: * <pre> * <foo> * <bar> * <prop>some value</prop> * <prop>other value</prop> * <prop>last value</prop> * </bar> * </foo> * </pre> * If you call getProperties("foo.bar.prop") will return a string array containing * {"some value", "other value", "last value"}. * * @param name the name of the property to retrieve * @return all child property values for the given node name. */ public String[] getProperties(String name) { String[] propName = parsePropertyName(name); // Search for this property by traversing down the XML heirarchy, // stopping one short. Element element = document.getRootElement(); for (int i = 0; i < propName.length - 1; i++) { element = element.element(propName[i]); if (element == null) { // This node doesn't match this part of the property name which // indicates this property doesn't exist so return empty array. return new String[]{}; } } // We found matching property, return names of children. Iterator iter = element.elementIterator(propName[propName.length - 1]); List<String> props = new ArrayList<String>(); String value; while (iter.hasNext()) { // Empty strings are skipped. value = ((Element)iter.next()).getTextTrim(); if (!"".equals(value)) { props.add(value); } } String[] childrenNames = new String[props.size()]; return props.toArray(childrenNames); } /** * Return all values who's path matches the given property * name as a String array, or an empty array if the if there * are no children. This allows you to retrieve several values * with the same property name. For example, consider the * XML file entry: * <pre> * <foo> * <bar> * <prop>some value</prop> * <prop>other value</prop> * <prop>last value</prop> * </bar> * </foo> * </pre> * If you call getProperties("foo.bar.prop") will return a string array containing * {"some value", "other value", "last value"}. * * @param name the name of the property to retrieve * @return all child property values for the given node name. */ public Iterator getChildProperties(String name) { String[] propName = parsePropertyName(name); // Search for this property by traversing down the XML heirarchy, // stopping one short. Element element = document.getRootElement(); for (int i = 0; i < propName.length - 1; i++) { element = element.element(propName[i]); if (element == null) { // This node doesn't match this part of the property name which // indicates this property doesn't exist so return empty array. return Collections.EMPTY_LIST.iterator(); } } // We found matching property, return values of the children. Iterator iter = element.elementIterator(propName[propName.length - 1]); ArrayList<String> props = new ArrayList<String>(); while (iter.hasNext()) { props.add(((Element)iter.next()).getText()); } return props.iterator(); } /** * Returns the value of the attribute of the given property name or <tt>null</tt> * if it doesn't exist. Note, this * * @param name the property name to lookup - ie, "foo.bar" * @param attribute the name of the attribute, ie "id" * @return the value of the attribute of the given property or <tt>null</tt> if * it doesn't exist. */ public String getAttribute(String name, String attribute) { if (name == null || attribute == null) { return null; } String[] propName = parsePropertyName(name); // Search for this property by traversing down the XML heirarchy. Element element = document.getRootElement(); for (int i = 0; i < propName.length; i++) { String child = propName[i]; element = element.element(child); if (element == null) { // This node doesn't match this part of the property name which // indicates this property doesn't exist so return empty array. break; } } if (element != null) { // Get its attribute values return element.attributeValue(attribute); } return null; } /** * Sets a property to an array of values. Multiple values matching the same property * is mapped to an XML file as multiple elements containing each value. * For example, using the name "foo.bar.prop", and the value string array containing * {"some value", "other value", "last value"} would produce the following XML: * <pre> * <foo> * <bar> * <prop>some value</prop> * <prop>other value</prop> * <prop>last value</prop> * </bar> * </foo> * </pre> * * @param name the name of the property. * @param values the values for the property (can be empty but not null). */ public void setProperties(String name, List<String> values) { String[] propName = parsePropertyName(name); // Search for this property by traversing down the XML heirarchy, // stopping one short. Element element = document.getRootElement(); for (int i = 0; i < propName.length - 1; i++) { // If we don't find this part of the property in the XML heirarchy // we add it as a new node if (element.element(propName[i]) == null) { element.addElement(propName[i]); } element = element.element(propName[i]); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -