001: /*
002: * CoadunationLib: The coaduntion implementation library.
003: * Copyright (C) 2006 Rift IT Contracting
004: *
005: * This library is free software; you can redistribute it and/or
006: * modify it under the terms of the GNU Lesser General Public
007: * License as published by the Free Software Foundation; either
008: * version 2.1 of the License, or (at your option) any later version.
009: *
010: * This library is distributed in the hope that it will be useful,
011: * but WITHOUT ANY WARRANTY; without even the implied warranty of
012: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
013: * Lesser General Public License for more details.
014: *
015: * You should have received a copy of the GNU Lesser General Public
016: * License along with this library; if not, write to the Free Software
017: * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
018: *
019: * XMLConfigurationException.java
020: *
021: * XMLConfigurationParser.java
022: *
023: * The parser for the XML configuration file.
024: */
025:
026: // the package definition
027: package com.rift.coad.lib.configuration.xml;
028:
029: // java imports
030: import java.util.Date;
031: import java.util.Map;
032: import java.util.HashMap;
033: import java.util.Iterator;
034: import java.io.BufferedReader;
035: import java.io.File;
036: import java.io.FileReader;
037: import javax.xml.parsers.SAXParserFactory;
038: import javax.xml.parsers.SAXParser;
039: import org.xml.sax.InputSource;
040: import org.xml.sax.helpers.DefaultHandler;
041: import org.xml.sax.SAXException;
042: import org.xml.sax.Attributes;
043:
044: /**
045: * This class is responsible for reading in the configuration information.
046: *
047: * @author Brett Chaldecott
048: */
049: public class XMLConfigurationParser {
050:
051: // the classes static member variables
052: private static final String GENERAL_SECTION = "GENERAL";
053: private static final String XML_CONFIG_PATH = "xml.config.path";
054:
055: /**
056: * This class stores the configuration information for a
057: */
058: public class XMLConfigInfo {
059:
060: // the classes private member variables
061: private String className = null;
062: private Map configInfo = null;
063:
064: /**
065: * The constructor of the xml configuration information
066: */
067: public XMLConfigInfo(String className) {
068: this .className = className;
069: configInfo = new HashMap();
070: }
071:
072: /**
073: * The method that returns the name of the class.
074: *
075: * @return The name of the class for which the configuration is stored.
076: */
077: public String getClassName() {
078: return className;
079: }
080:
081: /**
082: * This method addes an entry to the config information map.
083: *
084: * @param entry The entry to add to the map.
085: */
086: public void addEntry(XMLConfigurationEntry entry) {
087: configInfo.put(entry.getKey(), entry);
088: }
089:
090: /**
091: * This method returns the configuration information map.
092: *
093: * @return The map containing the configuration information.
094: */
095: public Map getConfigInfo() {
096: return configInfo;
097: }
098: }
099:
100: /**
101: * The inner class responsible for handling the contents of the Coadunation
102: * xml source document.
103: */
104: public class XMLConfigurationHandler extends DefaultHandler {
105:
106: // the classes static constant
107: private static final String CONFIGURATION = "configuration";
108: private static final String OBJECT_SECTION = "object";
109: private static final String OBJECT_SECTION_NAME = "name";
110: private static final String OBJECT_ENTRY = "entry";
111: private static final String OBJECT_ENTRY_KEY = "key";
112: private static final String OBJECT_ENTRY_TYPE = "type";
113:
114: // in section section variables
115: private boolean inConfiguration = false;
116: private boolean inObjectSection = false;
117: private boolean inObjectEntry = false;
118:
119: // data variables
120: private String inData = null;
121: private XMLConfigInfo sectionConfig = null;
122: private XMLConfigurationEntry entry = null;
123:
124: // the classes private member variables
125: private Map configSections = null;
126:
127: /**
128: * The constructor of the xml configuration handler.
129: *
130: * @param configSections The configurtion sections
131: */
132: public XMLConfigurationHandler(Map configSections) {
133: this .configSections = configSections;
134: }
135:
136: /**
137: * Parse the start of an element
138: */
139: public void startElement(String uri, String localName,
140: String qName, Attributes attributes)
141: throws SAXException {
142: try {
143: // handle a package and retrieve the value information
144: if (qName.compareToIgnoreCase(CONFIGURATION) == 0) {
145: inConfiguration = true;
146: } else if (inConfiguration
147: && qName.compareToIgnoreCase(OBJECT_SECTION) == 0) {
148: String name = (String) attributes
149: .getValue(OBJECT_SECTION_NAME);
150: if (name == null) {
151: name = XMLConfigurationParser.GENERAL_SECTION;
152: }
153: sectionConfig = new XMLConfigInfo(name);
154: inObjectSection = true;
155: } else if (inConfiguration && inObjectSection
156: && qName.compareToIgnoreCase(OBJECT_ENTRY) == 0) {
157: String name = (String) attributes
158: .getValue(OBJECT_ENTRY_KEY);
159: String type = (String) attributes
160: .getValue(OBJECT_ENTRY_TYPE);
161: entry = new XMLConfigurationEntry();
162: entry.setKey(name);
163: entry.setType(new XMLConfigurationType(type));
164: inData = "";
165: inObjectEntry = true;
166: }
167: } catch (Exception ex) {
168: throw new SAXException(
169: "Failed to handle the start element : "
170: + ex.getMessage());
171: }
172: }
173:
174: /**
175: * Read in the characters
176: */
177: public void characters(char[] ch, int start, int length) {
178: if (inObjectEntry) {
179: inData += new String(ch, start, length);
180: }
181: }
182:
183: /**
184: * Handle the end of an element
185: */
186: public void endElement(String uri, String localName,
187: String qName) throws SAXException {
188: try {
189: // handle a package and retrieve the value information
190: if (qName.compareToIgnoreCase(CONFIGURATION) == 0) {
191: inConfiguration = false;
192: } else if (inConfiguration
193: && qName.compareToIgnoreCase(OBJECT_SECTION) == 0) {
194: configSections.put(sectionConfig.getClassName(),
195: sectionConfig);
196: inObjectSection = false;
197: } else if (inConfiguration && inObjectSection
198: && qName.compareToIgnoreCase(OBJECT_ENTRY) == 0) {
199: entry.setValueFromString(inData.trim());
200: if (entry.isIntiailized() == false) {
201: throw new SAXException(
202: "An entry has not been initialized");
203: }
204: sectionConfig.addEntry(entry);
205: entry = null;
206: inData = "";
207: inObjectEntry = false;
208: }
209: } catch (Exception ex) {
210: throw new SAXException(
211: "Failed to handle the end element : "
212: + ex.getMessage(), ex);
213: }
214: }
215:
216: }
217:
218: // classes private member variables
219: private Map configSections = null;
220: private XMLConfigurationHandler handler = null;
221: private long lastModifiedAtRead = 0;
222: private File configFile = null;
223:
224: /**
225: * Creates a new instance of XMLConfigurationParser
226: */
227: public XMLConfigurationParser() throws XMLConfigurationException {
228: try {
229: configSections = new HashMap();
230: handler = new XMLConfigurationHandler(configSections);
231: SAXParser parser = SAXParserFactory.newInstance()
232: .newSAXParser();
233: configFile = new File(System.getProperty(XML_CONFIG_PATH));
234: InputSource source = new InputSource(new FileReader(
235: configFile));
236: parser.parse(source, handler);
237: lastModifiedAtRead = configFile.lastModified();
238: } catch (Exception ex) {
239: throw new XMLConfigurationException(
240: "Failed load the configuration : "
241: + ex.getMessage(), ex);
242: }
243: }
244:
245: /**
246: * This method checks to see if the configuration file has been modified
247: * since it was last read and returns true if this is the case.
248: *
249: * @return TRUE if modified, FALSE if not.
250: */
251: public boolean modified() {
252: if (lastModifiedAtRead != configFile.lastModified()) {
253: return true;
254: }
255: return false;
256: }
257:
258: /**
259: * This method returns a reference to the configuration class object.
260: *
261: * @return The reference to the xml configuration object
262: * @param classRef The reference to the class.
263: */
264: public XMLConfiguration getConfig(Class classRef) {
265: XMLConfiguration configuration = new XMLConfiguration(classRef
266: .getName());
267:
268: copyConfig((XMLConfigInfo) configSections.get(GENERAL_SECTION),
269: configuration);
270: copyConfig((XMLConfigInfo) configSections.get(classRef
271: .getName()), configuration);
272:
273: return configuration;
274: }
275:
276: /**
277: * This method copies the xml configuration.
278: *
279: * @param info The xml configuration information to copy.
280: * @param config The configuration class to copy the information into.
281: */
282: private void copyConfig(XMLConfigInfo info, XMLConfiguration config) {
283: if (info == null) {
284: return;
285: }
286: Map entries = info.getConfigInfo();
287: for (Iterator iter = entries.keySet().iterator(); iter
288: .hasNext();) {
289: String key = (String) iter.next();
290: config
291: .addConfigurationEntry((XMLConfigurationEntry) entries
292: .get(key));
293: }
294: }
295: }
|