KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > finalist > jaggenerator > DatabaseManager


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 JavaDoc;
20 import org.w3c.dom.Element JavaDoc;
21 import org.w3c.dom.NodeList JavaDoc;
22
23 import javax.swing.*;
24 import java.io.ByteArrayOutputStream JavaDoc;
25 import java.io.File JavaDoc;
26 import java.io.IOException JavaDoc;
27 import java.io.InputStream JavaDoc;
28 import java.util.*;
29 import java.util.jar.JarEntry JavaDoc;
30 import java.util.jar.JarFile JavaDoc;
31
32 /**
33  * The DatabaseManager handles JAG's generic database support.
34  * This enables JAG to connect to any database, provided the database has a JDBC driver.
35  *
36  * @author Michael O'Connor - Finalist IT Group
37  */

38 public class DatabaseManager {
39    private static DatabaseManager ourInstance;
40    private static ArrayList databases = new ArrayList();
41
42    private static final String JavaDoc DATABASE = "database";
43    private static final String JavaDoc SUPPORTED_DATABASES = "supported-databases";
44    public static final String JavaDoc NAME = "name";
45    private static final String JavaDoc DRIVER_CLASS = "driver-class";
46    private static final String JavaDoc APPSERVER_TYPEMAPPING = "appserver-typemapping";
47    private static final int READ_BUFFER_SIZE = 2048;
48    private static final String JavaDoc DOT_CLASS = ".class";
49    public static final String JavaDoc APPSERVER_TYPEMAPPINGS = "appserver-typemappings";
50
51    private static String JavaDoc[] typeMappings;
52    private static final Database[] DATABASE_ARRAY = new Database[0];
53    private static final String JavaDoc FILE = "file";
54
55    /**
56     * The DatabaseManager is a singleton - this method obtains the one and only instance.
57     * @return
58     */

59    public synchronized static DatabaseManager getInstance() {
60       if (ourInstance == null) {
61          ourInstance = new DatabaseManager();
62       }
63       return ourInstance;
64    }
65
66    private DatabaseManager() {
67       load();
68    }
69
70
71    /**
72     * Adds JDBC driver(s) from the specified File.
73     *
74     * @param driverFile
75     * @return a List of Database objects, one for each driver found in the file.
76     */

77    public List JavaDoc addDrivers(final File JavaDoc driverFile) {
78       boolean driverFound = false;
79       List JavaDoc newDatabases = new ArrayList();
80
81       try {
82          final JarFile JavaDoc jar = new JarFile JavaDoc(driverFile);
83          Enumeration e = jar.entries();
84
85          while (e.hasMoreElements()) {
86             JarEntry JavaDoc entry = (JarEntry JavaDoc) e.nextElement();
87             if (entry.getName().endsWith(DOT_CLASS)) {
88                String JavaDoc className = entry.getName().replace('/', '.').
89                      substring(0, entry.getName().indexOf(DOT_CLASS));
90                try {
91                   Class JavaDoc clazz = new JarClassLoader(jar).loadClass(className);
92                   if (Arrays.asList(clazz.getInterfaces()).contains(java.sql.Driver JavaDoc.class)) {
93                      boolean alreadyKnown = false;
94                      driverFound = true;
95                      Iterator i = databases.iterator();
96                      while (i.hasNext()) {
97                         Database database = (Database) i.next();
98                         if (database.getDriverClass().equals(className)) {
99                            JOptionPane.showMessageDialog(null,
100                                  "The driver '" + className + "' will not be added, as it is already known!",
101                                  "Duplicate Driver", javax.swing.JOptionPane.INFORMATION_MESSAGE);
102                            alreadyKnown = true;
103                            break;
104                         }
105                      }
106
107                      if (!alreadyKnown) {
108                         Database newDb = new Database();
109                         newDb.setDriverClass(className);
110                         newDb.setFilename(driverFile.getAbsolutePath());
111                         newDatabases.add(newDb);
112                      }
113                   }
114
115                } catch (Throwable JavaDoc cnf) {
116                   System.out.println(cnf);
117                }
118             }
119          }
120
121       } catch (IOException JavaDoc e) {
122          e.printStackTrace(); //To change body of catch statement use Options | File Templates.
123
}
124
125       if (!driverFound) {
126          JOptionPane.showMessageDialog(null,
127                "JAG could not find any JDBC drivers in file: " + driverFile,
128                "No Drivers Found!", javax.swing.JOptionPane.INFORMATION_MESSAGE);
129       } else if (newDatabases.size() > 0) {
130          JOptionPane.showMessageDialog(null,
131                "Found " + newDatabases.size() + " JDBC driver" + (newDatabases.size() == 1 ? "" : "s") +
132                " in file: " + driverFile,
133                "JDBC Driver" + (newDatabases.size() == 1 ? "" : "s") + " Found!",
134                javax.swing.JOptionPane.INFORMATION_MESSAGE);
135       }
136
137       return newDatabases;
138    }
139
140    /**
141     * Gets the list of supported databases.
142     *
143     * @return an array of all currently supported databases.
144     */

145    public Database[] getSupportedDatabases() {
146       return (Database[]) databases.toArray(DATABASE_ARRAY);
147    }
148
149    /**
150     * Resets the list of supported databases (and also resets the list in the Datasource panel).
151     * @param editedValues
152     */

153    public void setDatabases(ArrayList editedValues) {
154       databases = editedValues;
155       JagGenerator.jagGenerator.root.datasource.setSupportedDatabases(getSupportedDatabases());
156    }
157
158    /**
159     * Gets the list of possible appserver typemappings.
160     * @return
161     */

162    public String JavaDoc[] getTypeMappings() {
163       return typeMappings;
164    }
165
166    /**
167     * Persists the supported database information by appending an XML element to the config Document.
168     *
169     * @param root The XML Element under which we append the XML.
170     */

171    public Element JavaDoc appendXML(Element JavaDoc root) {
172       Document JavaDoc doc = root.getOwnerDocument();
173       Element JavaDoc dbRoot = doc.createElement(SUPPORTED_DATABASES);
174       Iterator i = databases.iterator();
175       while (i.hasNext()) {
176          Database dbInfo = (Database) i.next();
177          Element JavaDoc database = doc.createElement(DATABASE);
178          Element JavaDoc child = doc.createElement(NAME);
179          if (dbInfo.getDbName() != null) {
180             child.appendChild(doc.createTextNode(dbInfo.getDbName()));
181          }
182          database.appendChild(child);
183          child = doc.createElement(DRIVER_CLASS);
184          if (dbInfo.getDriverClass() != null) {
185             child.appendChild(doc.createTextNode(dbInfo.getDriverClass()));
186          }
187          database.appendChild(child);
188          child = doc.createElement(APPSERVER_TYPEMAPPING);
189          if (dbInfo.getTypeMapping() != null) {
190             child.appendChild(doc.createTextNode(dbInfo.getTypeMapping()));
191          }
192          database.appendChild(child);
193          child = doc.createElement(FILE);
194          if (dbInfo.getFilename() != null) {
195             child.appendChild(doc.createTextNode(dbInfo.getFilename()));
196          }
197          database.appendChild(child);
198          dbRoot.appendChild(database);
199       }
200       return dbRoot;
201    }
202
203
204    /**
205     * Reads in the supported database info from the config doc.
206     */

207    private void load() {
208       databases.clear();
209       Document JavaDoc doc = ConfigManager.getInstance().getDocument();
210       NodeList JavaDoc databaseNodes = doc.getElementsByTagName(DATABASE);
211       for (int i = 0; i < databaseNodes.getLength(); i++) {
212          Database dbInfo = new Database();
213          Element JavaDoc database = (Element JavaDoc) databaseNodes.item(i);
214          NodeList JavaDoc children = database.getChildNodes();
215          for (int j = 0; j < children.getLength(); j++) {
216             if (children.item(j) instanceof Element JavaDoc) {
217                Element JavaDoc child = (Element JavaDoc) children.item(j);
218                if (NAME.equals(child.getNodeName())) {
219                   dbInfo.setDbName(child.getFirstChild().getNodeValue());
220                } else if (DRIVER_CLASS.equals(child.getNodeName())) {
221                   dbInfo.setDriverClass(child.getFirstChild().getNodeValue());
222                } else if (APPSERVER_TYPEMAPPING.equals(child.getNodeName())) {
223                   dbInfo.setTypeMapping(child.getFirstChild().getNodeValue());
224                } else if (FILE.equals(child.getNodeName())) {
225                   dbInfo.setFilename(child.getFirstChild().getNodeValue());
226                }
227             }
228          }
229          //check validity of driver file
230
File JavaDoc driver = new File JavaDoc(dbInfo.getFilename());
231          if (!driver.exists()) {
232             JagGenerator.logToConsole("Removing missing driver reference: " + dbInfo.getFilename());
233             JOptionPane.showMessageDialog(JagGenerator.jagGenerator,
234                   "The previously specified JDBC driver for '" + dbInfo.getDbName() + "' databases can not be located.\n" +
235                   "(last known location was: " + dbInfo.getFilename() + ")\n" +
236                   "The entry for this driver will be deleted.",
237                   "Missing JDBC Driver!", javax.swing.JOptionPane.ERROR_MESSAGE);
238          } else {
239
240             databases.add(dbInfo);
241          }
242       }
243
244       Map typeMappingsMap = ConfigManager.getInstance().retrievePropertiesFromXML(APPSERVER_TYPEMAPPINGS);
245       String JavaDoc[] temp = (String JavaDoc[]) typeMappingsMap.get(NAME);
246       if (temp != null) {
247          typeMappings = temp;
248       }
249    }
250
251    /**
252     * This ClassLoader is necessary for grabbing Class objects from a jar file.
253     */

254    private class JarClassLoader extends ClassLoader JavaDoc {
255       private HashMap alreadyLoaded = new HashMap();
256       private JarFile JavaDoc jar;
257
258       /**
259        * Initialises the JarClassLoader with the jar file.
260        * @param jar
261        */

262       public JarClassLoader(JarFile JavaDoc jar) {
263          this.jar = jar;
264       }
265
266       public synchronized Class JavaDoc loadClass(String JavaDoc name, boolean resolve)
267             throws ClassNotFoundException JavaDoc {
268          Class JavaDoc clazz = (Class JavaDoc) alreadyLoaded.get(name);
269          if (clazz == null) {
270             try {
271                //is it a system class?
272
return findSystemClass(name);
273             } catch (Exception JavaDoc e) {
274             }
275             try {
276                //is it already loaded?
277
return Class.forName(name);
278             } catch (Exception JavaDoc e) {
279             }
280
281             byte[] bytes = loadClassBytes(name);
282             try {
283                clazz = defineClass(name, bytes, 0, bytes.length);
284             } catch (Throwable JavaDoc t) {
285                //System.out.println("!!defineClass threw " + t);
286
}
287                alreadyLoaded.put(name, clazz);
288
289             if (clazz == null) {
290                throw new ClassNotFoundException JavaDoc(name);
291             }
292          }
293
294          if (resolve) {
295             resolveClass(clazz);
296          }
297
298          return clazz;
299       }
300
301       private byte[] loadClassBytes(String JavaDoc name) {
302          ByteArrayOutputStream JavaDoc temp = new ByteArrayOutputStream JavaDoc();
303          byte[] buffer = new byte[READ_BUFFER_SIZE];
304          String JavaDoc entryName = name.replace('.', '/') + DOT_CLASS;
305          InputStream JavaDoc in = null;
306          try {
307
308 //todo : the jars so far have not needed inflating.. is this always the case?
309
// InflaterInputStream in = new InflaterInputStream(jar.getInputStream(entry));
310

311             JarEntry JavaDoc entry = jar.getJarEntry(entryName);
312             if (entry != null) {
313                in = jar.getInputStream(entry);
314                int bytesRead = -1;
315                do {
316                   bytesRead = in.read(buffer, 0, READ_BUFFER_SIZE);
317                   if (bytesRead != -1) {
318                      temp.write(buffer, 0, bytesRead);
319                   }
320                } while (bytesRead != -1);
321             }
322
323          } catch (IOException JavaDoc e1) {
324             e1.printStackTrace();
325          }
326
327          return temp.toByteArray();
328       }
329    }
330
331 }
332
333
Popular Tags