?根據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="??????????? <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
小石頭 閱讀(589)
評論(0) 編輯 收藏 所屬分類:
每天學一點