根据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>
* <X>
* <Y>
* <Z>someValue</Z>
* </Y>
* </X>
* </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><img src="http://www.jdon.com/images/jdlt.gif" width="179" height="64" alt="Community Forums" border="0"></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&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
小石头 阅读(584)
评论(0) 编辑 收藏 所属分类:
每天学一点