KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > derby > api > DerbyDatabases


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.modules.derby.api;
21
22 import java.io.File JavaDoc;
23 import java.io.IOException JavaDoc;
24 import java.net.MalformedURLException JavaDoc;
25 import java.net.URL JavaDoc;
26 import java.sql.Connection JavaDoc;
27 import java.sql.Driver JavaDoc;
28 import java.sql.PreparedStatement JavaDoc;
29 import java.sql.SQLException JavaDoc;
30 import java.util.Properties JavaDoc;
31 import org.netbeans.api.db.explorer.ConnectionManager;
32 import org.netbeans.api.db.explorer.DatabaseConnection;
33 import org.netbeans.api.db.explorer.DatabaseException;
34 import org.netbeans.api.db.explorer.JDBCDriver;
35 import org.netbeans.api.db.explorer.JDBCDriverManager;
36 import org.netbeans.modules.derby.DbURLClassLoader;
37 import org.netbeans.modules.derby.DerbyOptions;
38 import org.netbeans.modules.derby.Util;
39 import org.netbeans.modules.derby.RegisterDerby;
40 import org.netbeans.modules.derby.spi.support.DerbySupport;
41 import org.openide.filesystems.FileObject;
42 import org.openide.filesystems.FileUtil;
43 import org.openide.modules.InstalledFileLocator;
44
45 /**
46  *
47  * @author Andrei Badea
48  *
49  * @since 1.7
50  */

51 public final class DerbyDatabases {
52
53     private DerbyDatabases() {
54     }
55
56     /**
57      * Checks if the Derby database is registered and the Derby system
58      * home is set.
59      *
60      * @return true if Derby is registered, false otherwise.
61      */

62     public static boolean isDerbyRegistered() {
63         return DerbySupport.getLocation().length() > 0 && DerbySupport.getSystemHome().length() > 0; // NOI18N
64
}
65     
66     /**
67      * Returns the Derby system home.
68      *
69      * @return the Derby system home or null if it is not known.
70      */

71     public static File JavaDoc getSystemHome() {
72         String JavaDoc systemHome = DerbyOptions.getDefault().getSystemHome();
73         if (systemHome.length() >= 0) {
74             return new File JavaDoc(systemHome);
75         }
76         return null;
77     }
78
79     /**
80      * Checks if the given database exists in the Derby system home.
81      *
82      * @return true if the database exists, false otherwise.
83      *
84      * @throws NullPointerException if <code>databaseName</code> is null.
85      */

86     public static boolean databaseExists(String JavaDoc databaseName) {
87         if (databaseName == null) {
88             throw new NullPointerException JavaDoc("The databaseName parameter cannot be null"); // NOI18N
89
}
90         // just because it makes sense, not really needed anywhere probably
91
if ("".equals(databaseName)) { // NOI18N
92
return false;
93         }
94
95         String JavaDoc systemHome = DerbySupport.getSystemHome();
96         if (systemHome.length() <= 0) { // NOI18N
97
return false;
98         }
99         File JavaDoc databaseFile = new File JavaDoc(systemHome, databaseName);
100         return databaseFile.exists();
101     }
102
103     /**
104      * Returns the first free database name using the specified base name.
105      * The method attempts to create a database name by appending numbers to
106      * the base name, like in "base1", "base2", etc. and returns the
107      * first free name found.
108      *
109      * @return a database name or null if a free database name could not be found.
110      *
111      * @throws NullPointerException in the <code>baseDatabaseName</code> parameter
112      * could not be found.
113      */

114     public static String JavaDoc getFirstFreeDatabaseName(String JavaDoc baseDatabaseName) {
115         if (baseDatabaseName == null) {
116             throw new NullPointerException JavaDoc("The baseDatabaseName parameter cannot be null"); // NOI18N
117
}
118
119         String JavaDoc systemHome = DerbySupport.getSystemHome();
120         if (systemHome.length() <= 0) { // NOI18N
121
return baseDatabaseName;
122         }
123         File JavaDoc databaseFile = new File JavaDoc(systemHome, baseDatabaseName);
124         if (!databaseFile.exists()) {
125             return baseDatabaseName;
126         }
127
128         int i = 1;
129         while (i <= Integer.MAX_VALUE) {
130             String JavaDoc databaseName = baseDatabaseName + String.valueOf(i);
131             databaseFile = new File JavaDoc(systemHome, databaseName);
132             if (!databaseFile.exists()) {
133                 return databaseName;
134             }
135             i++;
136         }
137         return null;
138     }
139
140     /**
141      * Returns the code point of the first illegal character in the given database
142      * name.
143      *
144      * @return the code point of the first illegal character or -1 if all characters
145      * are valid.
146      *
147      * @throws NullPointerException if <code>databaseName</code> is null.
148      */

149     public static int getFirstIllegalCharacter(String JavaDoc databaseName) {
150         if (databaseName == null) {
151             throw new NullPointerException JavaDoc("The databaseName parameter cannot be null"); // NOI18N
152
}
153
154         for (int i = 0; i < databaseName.length(); i++) {
155             char ch = databaseName.charAt(i);
156             if (ch == '/') {
157                 return (int)ch;
158             }
159             if (ch == File.separatorChar) {
160                 return (int)ch;
161             }
162         }
163
164         return -1;
165     }
166
167     /**
168      * Creates a new empty database in the Derby system and registers
169      * it in the Database Explorer. A <code>DatabaseException</code> is thrown
170      * if a database with the given name already exists.
171      *
172      * <p>This method requires at least the Derby network driver to be registered.
173      * Otherwise it will throw an IllegalStateException.</p>
174      *
175      * <p>This method might take a long time to perform. It is advised that
176      * clients do not call this method from the event dispatching thread,
177      * where it would block the UI.</p>
178      *
179      * @param databaseName the name of the database to created; cannot be nul.
180      * @param user the user to set up authentication for. No authentication
181      * will be set up if <code>user</code> is null or an empty string.
182      * @param password the password for authentication.
183      *
184      * @throws NullPointerException if <code>databaseName</code> is null.
185      * @throws IllegalStateException if the Derby network driver is not registered.
186      * @throws DatabaseException if an error occurs while creating the database
187      * or registering it in the Database Explorer.
188      * @throws IOException if the Derby system home directory does not exist
189      * and it cannot be created.
190      */

191     public static DatabaseConnection createDatabase(String JavaDoc databaseName, String JavaDoc user, String JavaDoc password) throws DatabaseException, IOException JavaDoc, IllegalStateException JavaDoc {
192         if (databaseName == null) {
193             throw new NullPointerException JavaDoc("The databaseName parameter cannot be null"); // NOI18N
194
}
195
196         ensureSystemHome();
197         RegisterDerby.getDefault().ensureStarted();
198
199         Driver JavaDoc driver = loadDerbyNetDriver();
200         Properties JavaDoc props = new Properties JavaDoc();
201         boolean setupAuthentication = (user != null && user.length() >= 0);
202
203         try {
204             String JavaDoc url = "jdbc:derby://localhost:" + RegisterDerby.getDefault().getPort() + "/" + databaseName; // NOI18N
205
String JavaDoc urlForCreation = url + ";create=true"; // NOI18N
206
Connection JavaDoc connection = driver.connect(urlForCreation, props);
207
208
209             try {
210                 if (setupAuthentication) {
211                     setupDatabaseAuthentication(connection, user, password);
212                 }
213             } finally {
214                 connection.close();
215             }
216
217             if (setupAuthentication) {
218                 // we have to reboot the database for the authentication properties
219
// to take effect
220
try {
221                     connection = driver.connect(url + ";shutdown=true", props); // NOI18N
222
} catch (SQLException JavaDoc e) {
223                     // OK, will always occur
224
}
225             }
226         } catch (SQLException JavaDoc sqle) {
227             DatabaseException dbe = new DatabaseException(sqle.getMessage());
228             dbe.initCause(sqle);
229             throw dbe;
230         }
231
232         return registerDatabase(databaseName, user,
233                 setupAuthentication ? user.toUpperCase() : "APP", // NOI18N
234
setupAuthentication ? password : null, setupAuthentication);
235     }
236
237     /**
238      * Creates the sample database in the Derby system home
239      * using the default user and password ("app", resp. "app") and registers
240      * it in the Database Explorer. If the sample database already exists
241      * it is just registered.
242      *
243      * <p>This method requires at least the Derby network driver to be registered.
244      * Otherwise it will throw an IllegalStateException.</p>
245      *
246      * <p>This method might take a long time to perform. It is advised that
247      * clients do not call this method from the event dispatching thread,
248      * where it would block the UI.</p>
249      *
250      * @throws IllegalStateException if the Derby network driver is not registered.
251      * @throws DatabaseException if an error occurs while creating the database
252      * or registering it in the Database Explorer.
253      * @throws IOException if the Derby system home directory does not exist
254      * and it cannot be created.
255      */

256     public static DatabaseConnection createSampleDatabase() throws DatabaseException, IOException JavaDoc, IllegalStateException JavaDoc {
257         extractSampleDatabase("sample"); // NOI18N
258
return registerDatabase("sample", "app", "APP", "app", true); // NOI18N
259
}
260
261     /**
262      * Creates the sample database in the Derby system home using the
263      * given database name and the default user and password ("app", resp. "app") and registers
264      * it in the Database Explorer. A <code>DatabaseException</code> is thrown
265      * if a database with the given name already exists.
266      *
267      * <p>This method requires at least the Derby network driver to be registered.
268      * Otherwise it will throw an IllegalStateException.</p>
269      *
270      * <p>This method might take a long time to perform. It is advised that
271      * clients do not call this method from the event dispatching thread,
272      * where it would block the UI.</p>
273      *
274      * @throws NullPointerException if <code>databaseName</code> is null.
275      * @throws IllegalStateException if the Derby network driver is not registered.
276      * @throws DatabaseException if an error occurs while registering
277      * the new database in the Database Explorer.
278      * @throws IOException if the Derby system home directory does not exist
279      * and it cannot be created.
280      */

281     public static DatabaseConnection createSampleDatabase(String JavaDoc databaseName) throws DatabaseException, IOException JavaDoc {
282         if (databaseName == null) {
283             throw new NullPointerException JavaDoc("The databaseName parameter cannot be null"); // NOI18N
284
}
285
286         extractSampleDatabase(databaseName);
287         return registerDatabase(databaseName, "app", "APP", "app", true); // NOI18N
288
}
289
290     /**
291      * Extracts the sample database under the given name in the Derby system home.
292      * Does not overwrite an existing database.
293      *
294      * <p>Not public because used in tests.</p>
295      */

296     static void extractSampleDatabase(String JavaDoc databaseName) throws IOException JavaDoc{
297         File JavaDoc systemHomeFile = ensureSystemHome();
298         File JavaDoc sourceFO = InstalledFileLocator.getDefault().locate("modules/ext/derbysampledb.zip", null, false); // NOI18N
299
FileObject systemHomeFO = FileUtil.toFileObject(systemHomeFile);
300         FileObject sampleFO = systemHomeFO.getFileObject(databaseName);
301         if (sampleFO == null) {
302             sampleFO = systemHomeFO.createFolder(databaseName);
303             Util.extractZip(sourceFO, sampleFO);
304         }
305     }
306
307     /**
308      * Tries to ensure the Derby system home exists (attempts to create it if necessary).
309      */

310     private static File JavaDoc ensureSystemHome() throws IOException JavaDoc {
311         String JavaDoc systemHome = DerbySupport.getSystemHome();
312         boolean noSystemHome = false;
313         if (systemHome.length() <= 0) { // NOI18N
314
noSystemHome = true;
315             systemHome = DerbySupport.getDefaultSystemHome();
316         }
317         File JavaDoc systemHomeFile = new File JavaDoc(systemHome);
318         if (!systemHomeFile.exists()){
319             if (!systemHomeFile.mkdirs()) {
320                 throw new IOException JavaDoc("Could not create the derby.system.home directory"); // NOI18N
321
}
322         }
323         if (noSystemHome) {
324             DerbySupport.setSystemHome(systemHome);
325         }
326         return systemHomeFile;
327     }
328
329     /**
330      * Registers in the Database Explorer the specified database
331      * on the local Derby server.
332      */

333     private static DatabaseConnection registerDatabase(String JavaDoc databaseName, String JavaDoc user, String JavaDoc schema, String JavaDoc password, boolean rememberPassword) throws DatabaseException {
334         JDBCDriver drivers[] = JDBCDriverManager.getDefault().getDrivers(DerbyOptions.DRIVER_CLASS_NET);
335         if (drivers.length == 0) {
336             throw new IllegalStateException JavaDoc("The " + DerbyOptions.DRIVER_DISP_NAME_NET + " driver was not found"); // NOI18N
337
}
338         DatabaseConnection dbconn = DatabaseConnection.create(drivers[0], "jdbc:derby://localhost:" + RegisterDerby.getDefault().getPort() + "/" + databaseName, user, schema, password, rememberPassword); // NOI18N
339
ConnectionManager.getDefault().addConnection(dbconn);
340         return dbconn;
341     }
342
343     /**
344      * Sets up authentication for the database to which the given connection
345      * is connected.
346      */

347     private static void setupDatabaseAuthentication(Connection JavaDoc conn, String JavaDoc user, String JavaDoc password) throws SQLException JavaDoc {
348         PreparedStatement JavaDoc stmt = conn.prepareStatement("{call SYSCS_UTIL.SYSCS_SET_DATABASE_PROPERTY(?, ?)}"); // NOI18N
349
try {
350             stmt.setString(1, "derby.connection.requireAuthentication"); // NOI18N
351
stmt.setString(2, "true"); // NOI18N
352
stmt.execute();
353
354             stmt.clearParameters();
355             stmt.setString(1, "derby.authentication.provider"); // NOI18N
356
stmt.setString(2, "BUILTIN"); // NOI18N
357
stmt.execute();
358
359             stmt.clearParameters();
360             stmt.setString(1, "derby.user." + user); // NOI18N
361
stmt.setString(2, password); // NOI18N
362
stmt.execute();
363         } finally {
364             stmt.close();
365         }
366     }
367
368     /**
369      * Loads the Derby network driver.
370      */

371     private static Driver JavaDoc loadDerbyNetDriver() throws DatabaseException, IllegalStateException JavaDoc {
372         Exception JavaDoc exception = null;
373         try {
374             File JavaDoc derbyClient = Util.getDerbyFile("lib/derbyclient.jar"); // NOI18N
375
if (derbyClient == null || !derbyClient.exists()) {
376                 throw new IllegalStateException JavaDoc("The " + DerbyOptions.DRIVER_DISP_NAME_NET + " driver was not found"); // NOI18N
377
}
378             URL JavaDoc[] driverURLs = new URL JavaDoc[] { derbyClient.toURI().toURL() }; // NOI18N
379
DbURLClassLoader l = new DbURLClassLoader(driverURLs);
380             Class JavaDoc c = Class.forName(DerbyOptions.DRIVER_CLASS_NET, true, l);
381             return (Driver JavaDoc)c.newInstance();
382         } catch (MalformedURLException JavaDoc e) {
383             exception = e;
384         } catch (IllegalAccessException JavaDoc e) {
385             exception = e;
386         } catch (ClassNotFoundException JavaDoc e) {
387             exception = e;
388         } catch (InstantiationException JavaDoc e) {
389             exception = e;
390         }
391         if (exception != null) {
392             DatabaseException dbe = new DatabaseException(exception.getMessage());
393             dbe.initCause(exception);
394             throw dbe;
395         }
396         // should never get here
397
return null;
398     }
399 }
400
Popular Tags