KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > lib > ddl > impl > SpecificationFactory


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.lib.ddl.impl;
21
22 import java.sql.Connection JavaDoc;
23 import java.sql.DatabaseMetaData JavaDoc;
24 import java.sql.SQLException JavaDoc;
25 import java.io.InputStream JavaDoc;
26 import java.text.MessageFormat JavaDoc;
27 import java.util.Iterator JavaDoc;
28 import java.util.HashMap JavaDoc;
29 import java.util.Set JavaDoc;
30 import java.util.Vector JavaDoc;
31
32 import org.openide.util.NbBundle;
33
34 import org.netbeans.lib.ddl.DatabaseProductNotFoundException;
35 import org.netbeans.lib.ddl.DatabaseSpecification;
36 import org.netbeans.lib.ddl.DatabaseSpecificationFactory;
37 import org.netbeans.lib.ddl.DBConnection;
38 import org.netbeans.lib.ddl.DDLException;
39 import org.netbeans.lib.ddl.DriverSpecificationFactory;
40
41 /**
42 * The factory used for creating instances of Specification class.
43 * SpecificationFactory collects information about available database
44 * description files and is able to specify if system can control
45 * the database (specified by product name or live connection) or not.
46 * It also provides a list of supported databases. Information about databases
47 * reads from file org/netbeans/lib/ddl/DatabaseSpecification.plist. It's possible to replace it
48 * by setting db.specifications.file system property pointing to another one.
49 *
50 * @author Slavek Psenicka
51 */

52 public class SpecificationFactory implements DatabaseSpecificationFactory, DriverSpecificationFactory {
53
54     /** Database description file
55     * You should use PListReader to parse it.
56     */

57     private static final String JavaDoc dbFile = "org/netbeans/lib/ddl/resources/dbspec.plist";
58
59     /** Driver description file
60     * You should use PListReader to parse it.
61     */

62     private static final String JavaDoc drvFile = "org/netbeans/lib/ddl/resources/driverspec.plist";
63
64     /** Array of SpecificationFiles, found (but not read) files
65     * which describes database products.
66     */

67     private HashMap JavaDoc dbSpecs;
68
69     /** Array of SpecificationFiles, found (but not read) files
70     * which describes driver products.
71     */

72     private HashMap JavaDoc drvSpecs;
73
74     /** Debug information
75     */

76     private boolean debug = false;
77     
78     /** Constructor.
79     * Reads a bunch of specification files and prepares sfiles array. Files should
80     * be read from default place or from folder specified by system property named
81     * "db.specifications.folder".
82     */

83     public SpecificationFactory () throws DDLException {
84         String JavaDoc fileDB = System.getProperty("db.specifications.file");
85         String JavaDoc fileDrv = System.getProperty("driver.specifications.file");
86         SpecificationParser parser;
87
88         try {
89             if (fileDB == null) {
90                 ClassLoader JavaDoc cl = getClass().getClassLoader();
91                 InputStream JavaDoc stream = cl.getResourceAsStream(dbFile);
92                 if (stream == null) {
93                     String JavaDoc message = MessageFormat.format(NbBundle.getBundle("org.netbeans.lib.ddl.resources.Bundle").getString("EXC_UnableToOpenStream"), new String JavaDoc[] {dbFile}); // NOI18N
94
throw new Exception JavaDoc(message);
95                 }
96                 parser = new SpecificationParser(stream);
97                 dbSpecs = parser.getData();
98                 stream.close();
99             } else {
100                 parser = new SpecificationParser(fileDB);
101                 dbSpecs = parser.getData();
102             }
103         } catch (Exception JavaDoc e) {
104             if (fileDB != null)
105                 throw new DDLException("unable to read specifications file " + fileDB + ", " + e.getMessage());
106             else
107                 throw new DDLException("unable to read default specifications file, " + e.getMessage());
108         }
109
110         try {
111             if (fileDrv == null) {
112                 ClassLoader JavaDoc cl = getClass().getClassLoader();
113                 InputStream JavaDoc stream = cl.getResourceAsStream(drvFile);
114                 if (stream == null) {
115                     String JavaDoc message = MessageFormat.format(NbBundle.getBundle("org.netbeans.lib.ddl.resources.Bundle").getString("EXC_UnableToOpenStream"), new String JavaDoc[] {drvFile}); // NOI18N
116
throw new Exception JavaDoc(message);
117                 }
118                 parser = new SpecificationParser(stream);
119                 drvSpecs = parser.getData();
120                 stream.close();
121             } else {
122                 parser = new SpecificationParser(fileDrv);
123                 drvSpecs = parser.getData();
124             }
125         } catch (Exception JavaDoc e) {
126             if (fileDrv != null)
127                 throw new DDLException("unable to read specifications file " + fileDrv + ", " + e.getMessage());
128             else
129                 throw new DDLException("unable to read default specifications file, " + e.getMessage());
130         }
131     }
132
133     /** Returns array of database products supported by system.
134     * It returns string array only, if you need a Specification instance, use
135     * appropriate createSpecification method.
136     */

137     public Set JavaDoc supportedDatabases() {
138         return dbSpecs.keySet();
139     }
140
141     /** Returns true if database (specified by databaseProductName) is
142     * supported by system. Does not throw exception if it doesn't.
143     */

144     public boolean isDatabaseSupported(String JavaDoc databaseProductName) {
145         return (dbSpecs.containsKey(databaseProductName));
146     }
147
148     /** Creates instance of DatabaseSpecification class; a database-specification
149     * class. This object knows about used database and can be used as
150     * factory for db-manipulating commands. It connects to the database
151     * and reads database metadata. Throws DatabaseProductNotFoundException if database
152     * (obtained from database metadata) is not supported. Uses given Connection
153     */

154     public DatabaseSpecification createSpecification(DBConnection dbcon, Connection JavaDoc jdbccon) throws DatabaseProductNotFoundException, DDLException {
155         String JavaDoc pn = null;
156         try {
157             boolean close = (jdbccon != null ? false : true);
158             Connection JavaDoc con = (jdbccon != null ? jdbccon : dbcon.createJDBCConnection());
159             DatabaseMetaData JavaDoc dmd = con.getMetaData();
160             pn = dmd.getDatabaseProductName().trim();
161
162             DatabaseSpecification spec = createSpecification(dbcon, pn, con);
163             if (close) con.close();
164             return spec;
165         } catch (SQLException JavaDoc e) {
166             throw new DDLException("unable to connect to server");
167         } catch (Exception JavaDoc e) {
168             throw new DatabaseProductNotFoundException(pn, "unable to create specification, "+e.getMessage());
169         }
170     }
171
172     /** Creates instance of DatabaseSpecification class; a database-specification
173     * class. This object knows about used database and can be used as
174     * factory for db-manipulating commands. It connects to database and
175     * reads metadata as createSpecification(DBConnection connection), but always
176     * uses specified databaseProductName. This is not recommended technique.
177     */

178     public DatabaseSpecification createSpecification(DBConnection connection, String JavaDoc databaseProductName, Connection JavaDoc c) throws DatabaseProductNotFoundException {
179         //IBM DB2 hack
180
if (databaseProductName.toUpperCase().startsWith("DB2/")) //NOI18N
181
databaseProductName = "DB2/"; //NOI18N
182

183         HashMap JavaDoc product = (HashMap JavaDoc) dbSpecs.get(databaseProductName);
184
185         if (product == null)
186             throw new DatabaseProductNotFoundException(databaseProductName);
187         HashMap JavaDoc specmap = deepUnion(product, (HashMap JavaDoc) dbSpecs.get("GenericDatabaseSystem"), true);
188         specmap.put("connection", connection);
189         DatabaseSpecification spec = new Specification(specmap, c);
190         specmap.put("dbproduct", databaseProductName);
191         spec.setSpecificationFactory(this);
192
193         return spec;
194     }
195
196     /** Creates instance of DatabaseSpecification class; a database-specification
197     * class. This object knows about used database and can be used as
198     * factory for db-manipulating commands. It connects to database and
199     * reads metadata as createSpecification(DBConnection connection), but always
200     * uses specified databaseProductName. This is not recommended technique.
201     */

202     public DatabaseSpecification createSpecification(String JavaDoc databaseProductName, Connection JavaDoc c) throws DatabaseProductNotFoundException {
203         //IBM DB2 hack
204
if (databaseProductName.toUpperCase().startsWith("DB2/")) //NOI18N
205
databaseProductName = "DB2/"; //NOI18N
206

207         HashMap JavaDoc product = (HashMap JavaDoc) dbSpecs.get(databaseProductName);
208         if (product == null) throw new DatabaseProductNotFoundException(databaseProductName);
209         HashMap JavaDoc specmap = deepUnion(product, (HashMap JavaDoc) dbSpecs.get("GenericDatabaseSystem"), true);
210         specmap.put("dbproduct", databaseProductName);
211         return new Specification(specmap, c);
212     }
213
214     public DatabaseSpecification createSpecification(Connection JavaDoc c) throws DatabaseProductNotFoundException, SQLException JavaDoc {
215         return createSpecification(c, c.getMetaData().getDatabaseProductName().trim());
216     }
217
218     public DatabaseSpecification createSpecification(Connection JavaDoc c, String JavaDoc databaseProductName) throws DatabaseProductNotFoundException {
219         //IBM DB2 hack
220
if (databaseProductName.toUpperCase().startsWith("DB2/")) //NOI18N
221
databaseProductName = "DB2/"; //NOI18N
222

223         HashMap JavaDoc product = (HashMap JavaDoc) dbSpecs.get(databaseProductName);
224         if (product == null) throw new DatabaseProductNotFoundException(databaseProductName);
225         HashMap JavaDoc specmap = deepUnion(product, (HashMap JavaDoc) dbSpecs.get("GenericDatabaseSystem"), true);
226         DatabaseSpecification spec = new Specification(specmap, c);
227         spec.setSpecificationFactory(this);
228         return spec;
229     }
230
231     /** Returns debug-mode flag
232     */

233     public boolean isDebugMode() {
234         return debug;
235     }
236
237     /** Sets debug-mode flag
238     */

239     public void setDebugMode(boolean mode) {
240         debug = mode;
241     }
242
243     /** Returns array of driver products supported by system.
244     * It returns string array only, if you need a Specification instance, use
245     * appropriate createDriverSpecification method.
246     */

247     public Set JavaDoc supportedDrivers() {
248         return drvSpecs.keySet();
249     }
250
251     /** Returns true if driver (specified by driverName) is
252     * supported by system. Does not throw exception if it doesn't.
253     */

254     public boolean isDriverSupported(String JavaDoc driverName) {
255         return (drvSpecs.containsKey(driverName));
256     }
257
258     /** Creates instance of DriverSpecification class; a driver-specification
259     * class. This object knows about used driver.
260      */

261     public DriverSpecification createDriverSpecification(String JavaDoc driverName) {
262         HashMap JavaDoc product = (HashMap JavaDoc) drvSpecs.get(driverName);
263         if (product == null)
264             product = (HashMap JavaDoc) drvSpecs.get("DefaultDriver");
265         HashMap JavaDoc specmap = deepUnion(product, (HashMap JavaDoc) drvSpecs.get("DefaultDriver"), true);
266         DriverSpecification spec = new DriverSpecification(specmap);
267         spec.setDriverSpecificationFactory(this);
268
269         return spec;
270     }
271
272     /** Creates deep copy of Map.
273     * All items will be cloned. Used internally in this object.
274     */

275     private HashMap JavaDoc deepClone(HashMap JavaDoc map) {
276         HashMap JavaDoc newone = (HashMap JavaDoc)map.clone();
277         Iterator JavaDoc it = newone.keySet().iterator();
278         while (it.hasNext()) {
279             Object JavaDoc newkey = it.next();
280             Object JavaDoc deepobj = null, newobj = newone.get(newkey);
281             if (newobj instanceof HashMap JavaDoc)
282                 deepobj = deepClone((HashMap JavaDoc)newobj);
283             else if (newobj instanceof String JavaDoc)
284                 deepobj = (Object JavaDoc)new String JavaDoc((String JavaDoc)newobj);
285             else if (newobj instanceof Vector JavaDoc)
286                 deepobj = ((Vector JavaDoc)newobj).clone();
287             newone.put(newkey, deepobj);
288         }
289
290         return newone;
291     }
292
293     /** Joins base map with additional one.
294     * Copies keys only if not present in base map. Used internally in this object.
295     */

296     private HashMap JavaDoc deepUnion(HashMap JavaDoc base, HashMap JavaDoc additional, boolean deep) {
297         Iterator JavaDoc it = additional.keySet().iterator();
298         while (it.hasNext()) {
299             Object JavaDoc addkey = it.next();
300             Object JavaDoc addobj = additional.get(addkey);
301
302             //SQL92 types will be not added into databese type list
303
if (addkey.equals("TypeMap"))
304                 continue;
305
306             if (base.containsKey(addkey)) {
307                 Object JavaDoc baseobj = base.get(addkey);
308                 if (deep && (baseobj instanceof HashMap JavaDoc) && (addobj instanceof HashMap JavaDoc)) {
309                     deepUnion((HashMap JavaDoc)baseobj, (HashMap JavaDoc)addobj, deep);
310                 }
311             } else {
312                 if (addobj instanceof HashMap JavaDoc)
313                     addobj = deepClone((HashMap JavaDoc)addobj);
314                 else if (addobj instanceof String JavaDoc)
315                     addobj = (Object JavaDoc)new String JavaDoc((String JavaDoc)addobj);
316                 else if (addobj instanceof Vector JavaDoc)
317                     addobj = ((Vector JavaDoc)addobj).clone();
318                 base.put(addkey, addobj);
319             }
320         }
321
322         return base;
323     }
324
325 }
326
Popular Tags