tfc2005

BlogJava 首页 新随笔 联系 聚合 管理
  8 Posts :: 0 Stories :: 2 Comments :: 0 Trackbacks
    String title = JiveGlobals.getJiveProperty("websiteconf.name");   //网页标题

 

进到JiveGlobals看一看

 public static String getJiveProperty(String name) {

        loadProperties();

        return properties.getProperty(name);

}

看一看 loadProperties();

private synchronized static void loadProperties() {

                if (jiveHome == null) {

                jiveHome = new InitPropLoader().getJiveHome();

            }

            //Create a manager with the full path to the xml config file.

            properties = new XMLProperties(jiveHome + File.separator +

                    JIVE_CONFIG_FILENAME);

 

}

 

package com.jivesoftware.forum.util; 

import java.io.*;

import java.text.*;

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.

     *

     * @parm file the full path the file that properties should be read from

     *      and written to.

     */

    public XMLProperties(String file) {

        this.file = new File(file);

        try {

            SAXBuilder builder = new SAXBuilder();

            // Strip formatting

            DataUnformatFilter format = new DataUnformatFilter();

            builder.setXMLFilter(format);

            doc = builder.build(new File(file));

        }

        catch (Exception e) {

            System.err.println("Error creating XML parser in "

                + "PropertyManager.java");

            e.printStackTrace();

        }

    }

 

    /**

     * Returns the value of the specified property.

     *

     * @param name the name of the property to get.

     * @return the value of the specified property.

     */

    public String getProperty(String name) {

        if (propertyCache.containsKey(name)) {

            return (String)propertyCache.get(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; 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.

        String 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 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 void deleteProperty(String 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.

            file.delete();

            // 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.

            tempFile.renameTo(file);

        }

    }

 

    /**

     * 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;

    }

}

 

著名的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);
  }
 }

}

 

 



posted on 2005-06-17 10:43 佟福春 阅读(283) 评论(1)  编辑  收藏 所属分类: jive学习

Feedback

# re: index.jsp(4) 2009-03-21 11:40 易京勇
条理不错.很清晰.  回复  更多评论
  


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


网站导航: