View Javadoc

1   /*   Copyright (C) 2003 Finalist IT Group
2    *
3    *   This file is part of JAG - the Java J2EE Application Generator
4    *
5    *   JAG is free software; you can redistribute it and/or modify
6    *   it under the terms of the GNU General Public License as published by
7    *   the Free Software Foundation; either version 2 of the License, or
8    *   (at your option) any later version.
9    *   JAG is distributed in the hope that it will be useful,
10   *   but WITHOUT ANY WARRANTY; without even the implied warranty of
11   *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12   *   GNU General Public License for more details.
13   *   You should have received a copy of the GNU General Public License
14   *   along with JAG; if not, write to the Free Software
15   *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16   */
17  package com.finalist.jaggenerator;
18  
19  import org.w3c.dom.Document;
20  import org.w3c.dom.Element;
21  import org.w3c.dom.NodeList;
22  import org.xml.sax.SAXException;
23  
24  import javax.xml.parsers.DocumentBuilder;
25  import javax.xml.parsers.DocumentBuilderFactory;
26  import javax.xml.parsers.ParserConfigurationException;
27  import java.io.File;
28  import java.io.FileWriter;
29  import java.io.IOException;
30  import java.util.*;
31  
32  /***
33   * The ConfigManager deals with loading / saving JAG configuraton information
34   * to/from an XML config file.
35   *
36   * @author Michael O'Connor - Finalist IT Group
37   */
38  public class ConfigManager {
39  
40     private static final String JAG_CONFIG = "jag-config";
41     private static final File JAG_CONFIG_FILE = new File("jag-config.xml");
42     private static final String[] STRING_ARRAY = new String[0];
43     private static final File DATABASE_DRIVERS_CLASSPATH_FILE =
44           new File("set_database_drivers_classpath.bat");
45     private static final String SET_COMMAND = "set DATABASE_DRIVERS_CLASSPATH=";
46     private static final char SEMICOLON = ';';
47  
48     /***
49      * The name of the XML tag that contains the GUI configuration properties.
50      */
51     protected static final String XMLTAG_GUI = "gui";
52  
53     private static ConfigManager ourInstance;
54     private Document doc;
55  
56  
57     private ConfigManager() {
58        load();
59     }
60  
61  
62     /***
63      * The ConfigManager is a singleton - this method obtains the one and only instance.
64      *
65      * @return
66      */
67     public synchronized static ConfigManager getInstance() {
68        if (ourInstance == null) {
69           ourInstance = new ConfigManager();
70        }
71        return ourInstance;
72     }
73  
74     /***
75      * Gets the config information, parsed as an XML document.
76      * <p/>
77      * <b>NOTE:</b> this Document is provided READ-ONLY - any changes made to the doc will NOT be persisted!
78      *
79      * @return the doc.
80      */
81     public Document getDocument() {
82        return doc;
83     }
84  
85     /***
86      * Creates a Map that contains key-value pairs representing the XML elements / text nodes
87      * that fall underneath the node with the supplied name. If there are more than one node with the supplied
88      * name, only the first of these is translated into a Map.
89      * <p/>
90      * Property values are of type String[] : if a given property within the Map occurs more than
91      * once in the XML there will be more than one String in the array.
92      *
93      * @param rootElementName The name of the parent node whose children we want making into a Properties object.
94      *
95      * @return a Map whose keys are Strings and whose values are String[].
96      *         The map will be empty (but never <code>null</code>) if there are no nodes with the name
97      *         specified in <code>rootElementName</code>.
98      */
99     public Map retrievePropertiesFromXML(String rootElementName) {
100       HashMap props = new HashMap();
101       Element propsRoot = (Element) doc.getElementsByTagName(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.getFirstChild().getNodeValue()});
112                }
113                else {
114                   ArrayList newValues = new ArrayList(Arrays.asList(existingValues));
115                   newValues.add(child.getFirstChild().getNodeValue());
116                   props.put(key, newValues.toArray(STRING_ARRAY));
117                }
118             }
119          }
120       }
121 
122       return props;
123    }
124 
125    /***
126     * Saves the configurations to the XML JAG_CONFIG_FILE.
127     */
128    public void save() {
129       try {
130          DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
131          DocumentBuilder builder = dbf.newDocumentBuilder();
132          Document newDoc = builder.newDocument();
133          Element root = newDoc.createElement(JAG_CONFIG);
134 
135          //add the supported databases XML
136          Element dbRoot = DatabaseManager.getInstance().appendXML(root);
137          root.appendChild(dbRoot);
138 
139          newDoc.appendChild(root);
140 
141          //copy the appserver typemappings (these are not touched by JAG)
142          HashMap mappingsMap = new HashMap();
143          mappingsMap.put(DatabaseManager.NAME, DatabaseManager.getInstance().getTypeMappings());
144          Element mappingsRoot = appendPropertiesAsXML(root, mappingsMap, DatabaseManager.APPSERVER_TYPEMAPPINGS);
145          root.appendChild(mappingsRoot);
146 
147          String XMLDoc = com.finalist.jaggenerator.JagGenerator.outXML(newDoc);
148          FileWriter fw = new FileWriter(JAG_CONFIG_FILE);
149          fw.write(XMLDoc);
150          fw.close();
151 
152       }
153       catch (ParserConfigurationException e) {
154          e.printStackTrace();
155       }
156       catch (IOException e) {
157          e.printStackTrace();
158       }
159 
160       saveDatabaseDriversClasspath();
161    }
162 
163 
164    /***
165     * Reads in JAG's configuration from the XML JAG_CONFIG_FILE.
166     */
167    private void load() {
168       DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
169       DocumentBuilder builder = null;
170       try {
171          builder = dbf.newDocumentBuilder();
172          doc = builder.parse(JAG_CONFIG_FILE);
173 
174       }
175       catch (ParserConfigurationException e) {
176          e.printStackTrace();
177          JagGenerator.kickTheBucket("The XML parser can't even start up!");
178       }
179       catch (SAXException e) {
180          e.printStackTrace();
181          JagGenerator.kickTheBucket("JAG's config JAG_CONFIG_FILE (" + JAG_CONFIG_FILE + ") is invalid!");
182       }
183       catch (IOException e) {
184          e.printStackTrace();
185          JagGenerator.kickTheBucket("JAG's can't access the config JAG_CONFIG_FILE (" + JAG_CONFIG_FILE + ")!");
186       }
187    }
188 
189    /***
190     * Temporary work-around for dynamic loading of database driver classes..
191     * <p/>
192     * Write the database drivers classpath to a JAG_CONFIG_FILE, which is used by the startup scripts to build
193     * the JAG classpath.
194     */
195    private void saveDatabaseDriversClasspath() {
196       try {
197          DATABASE_DRIVERS_CLASSPATH_FILE.delete();
198          StringBuffer temp = new StringBuffer(SET_COMMAND);
199          Database[] databases = DatabaseManager.getInstance().getSupportedDatabases();
200          for (int i = 0; i < databases.length; i++) {
201             temp.append(databases[i].getFilename());
202             temp.append(SEMICOLON);
203          }
204 
205          FileWriter fw = new FileWriter(DATABASE_DRIVERS_CLASSPATH_FILE);
206          fw.write(temp.toString());
207          fw.flush();
208          fw.close();
209       }
210       catch (IOException e) {
211          e.printStackTrace();  //To change body of catch statement use Options | File Templates.
212       }
213    }
214 
215    /***
216     * Converts a Properties object into XML and appends it to the supplied root element.
217     *
218     * @param root            The root element to attach the properties XML to.
219     * @param props           The Map containing the properties to be XML-ised.  Must be a mapping of
220     *                        String to String[].
221     * @param rootElementName The name for the base XML tag.
222     */
223    private Element appendPropertiesAsXML(Element root, Map props, String rootElementName) {
224       Document doc = root.getOwnerDocument();
225       Element propsRoot = doc.createElement(rootElementName);
226 
227       Iterator i = props.entrySet().iterator();
228       while (i.hasNext()) {
229          Map.Entry entry = (Map.Entry) i.next();
230          String propertyName = (String) entry.getKey();
231          String[] value = (String[]) entry.getValue();
232          for (int j = 0; j < value.length; j++) {
233             Element nelly = doc.createElement(propertyName);
234             if (value[j] != null) {
235                nelly.appendChild(doc.createTextNode(value[j]));
236             }
237             propsRoot.appendChild(nelly);
238          }
239       }
240       return propsRoot;
241    }
242 }