001: /* Copyright (C) 2003 Finalist IT Group
002: *
003: * This file is part of JAG - the Java J2EE Application Generator
004: *
005: * JAG is free software; you can redistribute it and/or modify
006: * it under the terms of the GNU General Public License as published by
007: * the Free Software Foundation; either version 2 of the License, or
008: * (at your option) any later version.
009: * JAG is distributed in the hope that it will be useful,
010: * but WITHOUT ANY WARRANTY; without even the implied warranty of
011: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
012: * GNU General Public License for more details.
013: * You should have received a copy of the GNU General Public License
014: * along with JAG; if not, write to the Free Software
015: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
016: */
017: package com.finalist.jaggenerator;
018:
019: import org.w3c.dom.Document;
020: import org.w3c.dom.Element;
021: import org.w3c.dom.NodeList;
022: import org.xml.sax.SAXException;
023:
024: import javax.xml.parsers.DocumentBuilder;
025: import javax.xml.parsers.DocumentBuilderFactory;
026: import javax.xml.parsers.ParserConfigurationException;
027: import java.io.File;
028: import java.io.FileWriter;
029: import java.io.IOException;
030: import java.util.*;
031:
032: /**
033: * The ConfigManager deals with loading / saving JAG configuraton information
034: * to/from an XML config file.
035: *
036: * @author Michael O'Connor - Finalist IT Group
037: */
038: public class ConfigManager {
039:
040: private static final String JAG_CONFIG = "jag-config";
041: private static final File JAG_CONFIG_FILE = new File(
042: "jag-config.xml");
043: private static final String[] STRING_ARRAY = new String[0];
044: private static final File DATABASE_DRIVERS_CLASSPATH_FILE = new File(
045: "set_database_drivers_classpath.bat");
046: private static final String SET_COMMAND = "set DATABASE_DRIVERS_CLASSPATH=";
047: private static final char SEMICOLON = ';';
048:
049: /**
050: * The name of the XML tag that contains the GUI configuration properties.
051: */
052: protected static final String XMLTAG_GUI = "gui";
053:
054: private static ConfigManager ourInstance;
055: private Document doc;
056:
057: private ConfigManager() {
058: load();
059: }
060:
061: /**
062: * The ConfigManager is a singleton - this method obtains the one and only instance.
063: *
064: * @return
065: */
066: public synchronized static ConfigManager getInstance() {
067: if (ourInstance == null) {
068: ourInstance = new ConfigManager();
069: }
070: return ourInstance;
071: }
072:
073: /**
074: * Gets the config information, parsed as an XML document.
075: * <p/>
076: * <b>NOTE:</b> this Document is provided READ-ONLY - any changes made to the doc will NOT be persisted!
077: *
078: * @return the doc.
079: */
080: public Document getDocument() {
081: return doc;
082: }
083:
084: /**
085: * Creates a Map that contains key-value pairs representing the XML elements / text nodes
086: * that fall underneath the node with the supplied name. If there are more than one node with the supplied
087: * name, only the first of these is translated into a Map.
088: * <p/>
089: * Property values are of type String[] : if a given property within the Map occurs more than
090: * once in the XML there will be more than one String in the array.
091: *
092: * @param rootElementName The name of the parent node whose children we want making into a Properties object.
093: *
094: * @return a Map whose keys are Strings and whose values are String[].
095: * The map will be empty (but never <code>null</code>) if there are no nodes with the name
096: * specified in <code>rootElementName</code>.
097: */
098: public Map retrievePropertiesFromXML(String rootElementName) {
099: HashMap props = new HashMap();
100: Element propsRoot = (Element) doc.getElementsByTagName(
101: rootElementName).item(0);
102: if (propsRoot != null) {
103: NodeList children = propsRoot.getChildNodes();
104:
105: for (int j = 0; j < children.getLength(); j++) {
106: if (children.item(j) instanceof Element) {
107: Element child = (Element) children.item(j);
108: String key = child.getNodeName();
109: String[] existingValues = (String[]) props.get(key);
110: if (existingValues == null) {
111: props.put(key, new String[] { child
112: .getFirstChild().getNodeValue() });
113: } else {
114: ArrayList newValues = new ArrayList(Arrays
115: .asList(existingValues));
116: newValues.add(child.getFirstChild()
117: .getNodeValue());
118: props.put(key, newValues.toArray(STRING_ARRAY));
119: }
120: }
121: }
122: }
123:
124: return props;
125: }
126:
127: /**
128: * Saves the configurations to the XML JAG_CONFIG_FILE.
129: */
130: public void save() {
131: try {
132: DocumentBuilderFactory dbf = DocumentBuilderFactory
133: .newInstance();
134: DocumentBuilder builder = dbf.newDocumentBuilder();
135: Document newDoc = builder.newDocument();
136: Element root = newDoc.createElement(JAG_CONFIG);
137:
138: //add the supported databases XML
139: Element dbRoot = DatabaseManager.getInstance().appendXML(
140: root);
141: root.appendChild(dbRoot);
142:
143: newDoc.appendChild(root);
144:
145: //copy the appserver typemappings (these are not touched by JAG)
146: HashMap mappingsMap = new HashMap();
147: mappingsMap.put(DatabaseManager.NAME, DatabaseManager
148: .getInstance().getTypeMappings());
149: Element mappingsRoot = appendPropertiesAsXML(root,
150: mappingsMap, DatabaseManager.APPSERVER_TYPEMAPPINGS);
151: root.appendChild(mappingsRoot);
152:
153: String XMLDoc = com.finalist.jaggenerator.JagGenerator
154: .outXML(newDoc);
155: FileWriter fw = new FileWriter(JAG_CONFIG_FILE);
156: fw.write(XMLDoc);
157: fw.close();
158:
159: } catch (ParserConfigurationException e) {
160: e.printStackTrace();
161: } catch (IOException e) {
162: e.printStackTrace();
163: }
164:
165: saveDatabaseDriversClasspath();
166: }
167:
168: /**
169: * Reads in JAG's configuration from the XML JAG_CONFIG_FILE.
170: */
171: private void load() {
172: DocumentBuilderFactory dbf = DocumentBuilderFactory
173: .newInstance();
174: DocumentBuilder builder = null;
175: try {
176: builder = dbf.newDocumentBuilder();
177: doc = builder.parse(JAG_CONFIG_FILE);
178:
179: } catch (ParserConfigurationException e) {
180: e.printStackTrace();
181: JagGenerator
182: .kickTheBucket("The XML parser can't even start up!");
183: } catch (SAXException e) {
184: e.printStackTrace();
185: JagGenerator.kickTheBucket("JAG's config JAG_CONFIG_FILE ("
186: + JAG_CONFIG_FILE + ") is invalid!");
187: } catch (IOException e) {
188: e.printStackTrace();
189: JagGenerator
190: .kickTheBucket("JAG's can't access the config JAG_CONFIG_FILE ("
191: + JAG_CONFIG_FILE + ")!");
192: }
193: }
194:
195: /**
196: * Temporary work-around for dynamic loading of database driver classes..
197: * <p/>
198: * Write the database drivers classpath to a JAG_CONFIG_FILE, which is used by the startup scripts to build
199: * the JAG classpath.
200: */
201: private void saveDatabaseDriversClasspath() {
202: try {
203: DATABASE_DRIVERS_CLASSPATH_FILE.delete();
204: StringBuffer temp = new StringBuffer(SET_COMMAND);
205: Database[] databases = DatabaseManager.getInstance()
206: .getSupportedDatabases();
207: for (int i = 0; i < databases.length; i++) {
208: temp.append(databases[i].getFilename());
209: temp.append(SEMICOLON);
210: }
211:
212: FileWriter fw = new FileWriter(
213: DATABASE_DRIVERS_CLASSPATH_FILE);
214: fw.write(temp.toString());
215: fw.flush();
216: fw.close();
217: } catch (IOException e) {
218: e.printStackTrace(); //To change body of catch statement use Options | File Templates.
219: }
220: }
221:
222: /**
223: * Converts a Properties object into XML and appends it to the supplied root element.
224: *
225: * @param root The root element to attach the properties XML to.
226: * @param props The Map containing the properties to be XML-ised. Must be a mapping of
227: * String to String[].
228: * @param rootElementName The name for the base XML tag.
229: */
230: private Element appendPropertiesAsXML(Element root, Map props,
231: String rootElementName) {
232: Document doc = root.getOwnerDocument();
233: Element propsRoot = doc.createElement(rootElementName);
234:
235: Iterator i = props.entrySet().iterator();
236: while (i.hasNext()) {
237: Map.Entry entry = (Map.Entry) i.next();
238: String propertyName = (String) entry.getKey();
239: String[] value = (String[]) entry.getValue();
240: for (int j = 0; j < value.length; j++) {
241: Element nelly = doc.createElement(propertyName);
242: if (value[j] != null) {
243: nelly.appendChild(doc.createTextNode(value[j]));
244: }
245: propsRoot.appendChild(nelly);
246: }
247: }
248: return propsRoot;
249: }
250: }
|