小石头
Excellence in any department can be attained only by the labor of a lifetime; it is not to be purchased at a lesser price.
posts - 91,comments - 22,trackbacks - 0

 根据jive学习读取XML文件
 
要引入的包:jdom.jar


读取

package com.jivesoftware.forum.util;

import java.io.*;
import java.util.*;

import org.jdom.*;
import org.jdom.input.*;
import org.jdom.output.*;

/**
 * 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>
 * &lt;X&gt;
 *     &lt;Y&gt;
 *         &lt;Z&gt;someValue&lt;/Z&gt;
 *     &lt;/Y&gt;
 * &lt;/X&gt;
 * </pre>
 *
 * 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.
 */
public class XMLProperties {

    private File file;
    private Document doc;

    /**
     * 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 propertyCache = new HashMap();

    /**
     * Creates a new XMLProperties object.
     *
     * @param fileName the full path the file that properties should be read from
     *      and written to.
     */
    public XMLProperties(String fileName) throws IOException {
        this.file = new File(fileName);
        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()) {
                System.err.println("WARNING: " + fileName + " 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: " + fileName);
            }
        }
        // Check read and write privs.
        if (!file.canRead()) {
            throw new IOException("XML properties file must be readable: " + fileName);
        }
        if (!file.canWrite()) {
            throw new IOException("XML properties file must be writable: " + fileName);
        }
        try {
            SAXBuilder builder = new SAXBuilder();
            // Strip formatting
            //DataUnformatFilter format = new DataUnformatFilter();
            builder.setXMLFilter(format);
            doc = builder.build(file);
        }
        catch (Exception e) {
            System.err.println("Error creating XML properties file: ");
            e.printStackTrace();
            throw new IOException(e.getMessage());
        }
    }

    /**
     * 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 = (String)propertyCache.get(name);
        if (value != null) {
            return value;
        }

        String[] propName = parsePropertyName(name);
        // Search for this property by traversing down the XML heirarchy.
        Element element = doc.getRootElement();
        for (int i = 0; i < propName.length; i++) {
            element = element.getChild(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.getText();
        if ("".equals(value)) {
            return null;
        }
        else {
            // Add to cache so that getting property next time is fast.
            value = value.trim();
            propertyCache.put(name, value);
            return value;
        }
    }

    /**
     * Return all children property names of a parent property as a String array,
     * or an empty array if the if there are no children. For example, given
     * the properties <tt>X.Y.A</tt>, <tt>X.Y.B</tt>, and <tt>X.Y.C</tt>, then
     * the child properties of <tt>X.Y</tt> are <tt>A</tt>, <tt>B</tt>, and
     * <tt>C</tt>.
     *
     * @param parent the name of the parent property.
     * @return all child property values for the given parent.
     */
    public String [] getChildrenProperties(String parent) {
        String[] propName = parsePropertyName(parent);
        // Search for this property by traversing down the XML heirarchy.
        Element element = doc.getRootElement();
        for (int i = 0; i < propName.length; i++) {
            element = element.getChild(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.
        List children = element.getChildren();
        int childCount = children.size();
        String [] childrenNames = new String[childCount];
        for (int i=0; i<childCount; i++) {
            childrenNames[i] = ((Element)children.get(i)).getName();
        }
        return childrenNames;
    }

    /**
     * Sets the value of the specified property. If the property doesn't
     * currently exist, it will be automatically created.
     *
     * @param name the name of the property to set.
     * @param value the new value for the property.
     */
    public synchronized void setProperty(String name, String value) {
        // Set cache correctly with prop name and value.
        propertyCache.put(name, value);

        String[] propName = parsePropertyName(name);
        // Search for this property by traversing down the XML heirarchy.
        Element element = doc.getRootElement();
        for (int i=0; i<propName.length; i++) {
            // If we don't find this part of the property in the XML heirarchy
            // we add it as a new node
            if (element.getChild(propName[i]) == null) {
                element.addContent(new Element(propName[i]));
            }
            element = element.getChild(propName[i]);
        }
        // Set the value of the property in this node.
        element.setText(value);
        // write the XML properties to disk
        saveProperties();
    }

    /**
     * Deletes the specified property.
     *
     * @param name the property to delete.
     */
    public synchronized void deleteProperty(String name) {
        // Remove property from cache.
        propertyCache.remove(name);

        String[] propName = parsePropertyName(name);
        // Search for this property by traversing down the XML heirarchy.
        Element element = doc.getRootElement();
        for (int i=0; i<propName.length-1; i++) {
            element = element.getChild(propName[i]);
            // Can't find the property so return.
            if (element == null) {
                return;
            }
        }
        // Found the correct element to remove, so remove it...
        element.removeChild(propName[propName.length-1]);
        // .. then write to disk.
        saveProperties();
    }

    /**
     * Saves the properties to disk as an XML document. A temporary file is
     * used during the writing process for maximum safety.
     */
    private synchronized void saveProperties() {
        OutputStream out = null;
        boolean error = false;
        // Write data out to a temporary file first.
        File tempFile = null;
        try {
            tempFile = new File(file.getParentFile(), file.getName() + ".tmp");
            // Use JDOM's XMLOutputter to do the writing and formatting. The
            // file should always come out pretty-printed.
            XMLOutputter outputter = new XMLOutputter("    ", true);
            out = new BufferedOutputStream(new FileOutputStream(tempFile));
            outputter.output(doc, out);
        }
        catch (Exception e) {
            e.printStackTrace();
            // There were errors so abort replacing the old property file.
            error = true;
        }
        finally {
            try {  out.close();  }
            catch (Exception e) {
                e.printStackTrace();
                error = true;
            }
        }
        // No errors occured, so we should be safe in replacing the old
        if (!error) {
            // Delete the old file so we can replace it.
            if (!file.delete()) {
                System.err.println("Error deleting property file: " +
                        file.getAbsolutePath());
                return;
            }
            // Rename the temp file. The delete and rename won't be an
            // automic operation, but we should be pretty safe in general.
            // At the very least, the temp file should remain in some form.
            if (!tempFile.renameTo(file)) {
                System.err.println("Error renaming temp file from " +
                    tempFile.getAbsolutePath() + " to " + file.getAbsolutePath());
            }
        }
    }

    /**
     * Returns an array representation of the given Jive property. Jive
     * properties are always in the format "prop.name.is.this" which would be
     * represented as an array of four Strings.
     *
     * @param name the name of the Jive property.
     * @return an array representation of the given Jive property.
     */
    private String[] parsePropertyName(String name) {
        // Figure out the number of parts of the name (this becomes the size
        // of the resulting array).
        int size = 1;
        for (int i=0; i<name.length(); i++) {
            if (name.charAt(i) == '.') {
                size++;
            }
        }
        String[] propName = new String[size];
        // Use a StringTokenizer to tokenize the property name.
        StringTokenizer tokenizer = new StringTokenizer(name, ".");
        int i = 0;
        while (tokenizer.hasMoreTokens()) {
            propName[i] = tokenizer.nextToken();
            i++;
        }
        return propName;
    }

    public static void main(String[] args){
      try {
        XMLProperties pop=new XMLProperties("jive_config.xml");
        String str=pop.getProperty("upload.dir");
        System.out.println(str);
      }
      catch (IOException ex) {
        ex.printStackTrace();
      }
    }
}


jive_config.xml

<?xml version="1.0" encoding="UTF-8"?>
<!--
    This file stores all properties need by Jive. Property names must be in the
    format:
        prop.name.is.blah=value
    That will be stored as:
        <prop>
            <name>
                <is>
                    <blah>value</blah>
                </is>
            </name>
        </prop>

     All properties must be under the "jive" element.

     This file should live in your jiveHome directory. The path to that directory
     should be specified in your jive_init.properties file. The
     jive_init.properties must be in your appserver's classpath.
-->
<!-- root element, all properties must be under this element -->
<jive>
    <!-- Search properties -->
    <search>
        <enabled>true</enabled>
        <autoIndexEnabled>true</autoIndexEnabled>
        <autoIndexInterval>5</autoIndexInterval>
        <lastIndexed>1127707029812</lastIndexed>
    </search>
    <!-- Mail properties -->
    <mail>
        <!-- If debug is true, JavaMail will debug to System.out -->
        <debug>false</debug>
        <smtp>
            <host>localhost</host>
            <port>25</port>
        </smtp>
    </mail>
    <!-- Watches properties -->
    <watches>
        <enabled>true</enabled>
        <email>
            <fromName>Jive_Administrator</fromName>
            <fromEmail>banq@jdon.com</fromEmail>
            <subject>Your thread was updated</subject>
            <body>Hello {name}! The thread {threadName} was updated!</body>
        </email>
    </watches>
    <!-- Properties for the Jive Forums 2.0 default skin. Feel free to hand -->
    <!-- edit these values to customize the look of your forums. However,   -->
    <!-- you must restart your appserver for any changes to take effect.    -->
    <skin>
        <default>
            <fontFace>arial,sans-serif</fontFace>
            <buttonFontFace>verdana,arial,sans-serif</buttonFontFace>
            <homeURL>index.jsp</homeURL>
            <bgColor>#ffffff</bgColor>
            <textColor>#000000</textColor>
            <linkColor>#000000</linkColor>
            <vLinkColor>#000000</vLinkColor>
            <aLinkColor>#000000</aLinkColor>
            <tableBorderColor>#cccccc</tableBorderColor>
            <tableHeaderBgColor>#999999</tableHeaderBgColor>
            <tableHeaderTextColor>#ffffff</tableHeaderTextColor>
            <tableRowColor1>#eeeeee</tableRowColor1>
            <tableRowColor2>#d9e4f9</tableRowColor2>
            <paginatorTextColor>#333333</paginatorTextColor>
            <paginatorTableBgColor>#eeeeee</paginatorTableBgColor>
            <communityDescription>test中文</communityDescription>
            <headerLogo>&lt;img src="http://www.jdon.com/images/jdlt.gif" width="179" height="64" alt="Community Forums" border="0"&gt;</headerLogo>
            <headerBorderColor>#707070</headerBorderColor>
            <headerBgColor>#eeeeee</headerBgColor>
            <headerFontFace>verdana,arial,sans-serif</headerFontFace>
            <threadMode>flat</threadMode>
            <sidebarHeaderBgColor>#eeeeee</sidebarHeaderBgColor>
            <sidebarHeaderTextColor>#000000</sidebarHeaderTextColor>
            <sidebarBgColor>#ffffff</sidebarBgColor>
            <prefsHeaderTextColor>#000000</prefsHeaderTextColor>
            <prefsBgColor>#ffffff</prefsBgColor>
            <prefsHeaderBgColor>#eeeeee</prefsHeaderBgColor>
        </default>
    </skin>
    <upload>
        <dir>/home/jdon/jive/upload/</dir>
        <relurl>upload/</relurl>
    </upload>
    <websiteconf>
        <url>http://www.jdon.com/</url>
        <name>Jdon</name>
    </websiteconf>
    <connectionProvider>
        <className>com.jivesoftware.forum.database.DefaultConnectionProvider</className>
    </connectionProvider>
    <locale>
        <country />
        <language>zh</language>
    </locale>
    <database>
        <defaultProvider>
            <driver>com.mysql.jdbc.Driver</driver>
            <serverURL>jdbc:mysql://127.0.0.1/Jive?useUnicode=true&amp;characterEncoding=UTF-8</serverURL>
            <username>banq</username>
            <password>225034ba</password>
            <minConnections>5</minConnections>
            <maxConnections>50</maxConnections>
            <connectionTimeout>0.5</connectionTimeout>
        </defaultProvider>
    </database>
    <setup>true</setup>
    <cache>
        <enabled>false</enabled>
    </cache>
</jive>

相关资料 :

Jive中Jdom使用剖析
板桥里人 http://www.jdon.com 2002/06/04

著名的Open Source论坛Jive有很多东西值得我们分析和学习,通过分析其Jdom的使用机制,我们可以自如方便的读写XML
配置文件,从而实现下列一些功能:

1.,在配置文件中设置系统语言版本属性,不同语言版本,系统界面文字不一样,可以定义自己国家的文字,比如英文版 中
文简体版. 这样,可以很方便的将一个系统延伸到各种语言,不用直接修改程序,只要修改XML配置文件就可以.

2.在配置文件中设置邮件内容, 通常一个系统都有各种自动邮件分发,比如用户注册成功后,会有一封Email发送到他的
信箱,这套系统安装在不同客户场合,Email的内容当然不一样,如A客户使用了这套系统,当然希望在Email中有A客户的单
位名称,这些都不必修改程序可以完成.

3.设置系统的可选属性,一个系统安装在不同客户场合中,客户的要求总有些不一样,有些功能是可选的,那么当然这些都
要设置在XML配置文件中.

4.使用XML存放树形结构记录是最方便的,尤其对于那些目录分类系统,如Yahoo,在大分类中有小分类,或者直接是元素,


我们知道关系数据库是不擅长存放树形数据,在关系数据库中,典型做法是采取两个表:一个表记录每个cell;一个表指明
其前后关系;但是我们一旦要从这两张表展开树形结构,将要在空间和时间上反复平衡.

如果使用XML作为数据源,就很方便解决这个问题,如果配合对XML数据源有很方便的增 修 删 等功能,那么我们当然选择
XML,实际上,Jdom就方便地提供了这个工具.Jdom是类似DOM SAX之类的XML解析办法,只适合Java语言,Jdom的特点就是简
单方便。

那么,让我们来看看Jive是怎么实现上面功能的吧,它是把这些属性都写在一个叫jive_config.xml的文件中.这个XML文
件的排列方式和使用方式是这样:

XML文件内容格式:


<!-- root element, all properties must be under this element -->
<jive>
 <email>
  <fromName>Jive_Administrator</fromName>
  <fromEmail>webmaster@example.com</fromEmail>
  <subject>Your thread was updated!</subject>
  <body>Hello {name}! The thread {threadName} was updated!</body>
 </email>
<jive>

 


<jive></jive>是根元素,所有的属性必须在其中

使用方式也比较简单,使用标点符号"."来间隔.比如我们要得到上面的webmaster@example.com的值,那么使用
email.fromEmail就可以.在Jive中,具体语句就是JiveGlobals.getJiveProperty("email.fromEmail");

这样获取值很简单,而且明了,无论XML树形结构有多深,我们都可以方便的获取.

这里关键的是一个使用Jdom来解析XML文件的类:XMLProperties 其中实现了几个主要操作方法:

获得(查询):getProperty(name) ;
新增修改:properties.setProperty(name, value);
删除:properties.deleteProperty(name) ;

这几个方法是不是很类似Hasntable的方法?Hashtable中数据是存放在内存中,而XML是存放在文件系统,无疑我们可
以象使用hashtable一样方便的使用XML。

XMLProperties我们可以原封不动的拷贝到我们系统中。唯一要做的就是编制类似Jive的JiveGlobals,其实这也很简
单,分两步:先load取出XML文件;然后就提供getProperty(name)等方法。如


public class JiveGlobals {

 private static final String JIVE_CONFIG_FILENAME = "jive_config.xml";

....

 public static String getJiveProperty(String name) {
  loadProperties();
  return properties.getProperty(name);
 }
....

 private synchronized static void loadProperties() {
  if (properties == null) {
   //Create a manager with the full path to the xml config file.
   properties = new XMLProperties(jiveHome + File.separator +
           JIVE_CONFIG_FILENAME);
  }
 }

}

 


当然,所有这些前提,是到http://www.jdom.org下载Jdom包,并加入到Tomcat的common/lib中,或者放入Classpath
中。

其他辅助文件有:DataFormatFilter.java DataUnformatFilter.java XMLFilterBase.java

但在本文中把使用他的语句DataUnformatFilter注释掉了,1为了学习方便,2我试了一下去掉不影响功能

如果你对Jdom具体每一句是如何使用的,可以仔细研究XMLProperties,很容易理解的.

posted on 2007-01-10 15:34 小石头 阅读(576) 评论(0)  编辑  收藏 所属分类: 每天学一点

只有注册用户登录后才能发表评论。


网站导航: