KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > java > sql > DriverManager


1 /*
2  * @(#)DriverManager.java 1.42 04/05/18
3  *
4  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7
8 package java.sql;
9
10 /**
11  * <P>The basic service for managing a set of JDBC drivers.<br>
12  * <B>NOTE:</B> The {@link <code>DataSource</code>} interface, new in the
13  * JDBC 2.0 API, provides another way to connect to a data source.
14  * The use of a <code>DataSource</code> object is the preferred means of
15  * connecting to a data source.
16  *
17  * <P>As part of its initialization, the <code>DriverManager</code> class will
18  * attempt to load the driver classes referenced in the "jdbc.drivers"
19  * system property. This allows a user to customize the JDBC Drivers
20  * used by their applications. For example in your
21  * ~/.hotjava/properties file you might specify:
22  * <pre>
23  * <CODE>jdbc.drivers=foo.bah.Driver:wombat.sql.Driver:bad.taste.ourDriver</CODE>
24  * </pre>
25  *
26  * A program can also explicitly load JDBC drivers at any time. For
27  * example, the my.sql.Driver is loaded with the following statement:
28  * <pre>
29  * <CODE>Class.forName("my.sql.Driver");</CODE>
30  * </pre>
31  *
32  * <P>When the method <code>getConnection</code> is called,
33  * the <code>DriverManager</code> will attempt to
34  * locate a suitable driver from amongst those loaded at
35  * initialization and those loaded explicitly using the same classloader
36  * as the current applet or application.
37  * <P>
38  * Starting with the Java 2 SDK, Standard Edition, version 1.3, a
39  * logging stream can be set only if the proper
40  * permission has been granted. Normally this will be done with
41  * the tool PolicyTool, which can be used to grant <code>permission
42  * java.sql.SQLPermission "setLog"</code>.
43  * @see Driver
44  * @see Connection
45  */

46 public class DriverManager {
47
48
49     /**
50      * The <code>SQLPermission</code> constant that allows the
51      * setting of the logging stream.
52      * @since 1.3
53      */

54     final static SQLPermission JavaDoc SET_LOG_PERMISSION =
55         new SQLPermission JavaDoc("setLog");
56
57     //--------------------------JDBC 2.0-----------------------------
58

59     /**
60      * Retrieves the log writer.
61      *
62      * The <code>getLogWriter</code> and <code>setLogWriter</code>
63      * methods should be used instead
64      * of the <code>get/setlogStream</code> methods, which are deprecated.
65      * @return a <code>java.io.PrintWriter</code> object
66      * @see #setLogWriter
67      * @since 1.2
68      */

69     public static java.io.PrintWriter JavaDoc getLogWriter() {
70     synchronized (logSync) {
71         return logWriter;
72     }
73     }
74
75     /**
76      * Sets the logging/tracing <code>PrintWriter</code> object
77      * that is used by the <code>DriverManager</code> and all drivers.
78      * <P>
79      * There is a minor versioning problem created by the introduction
80      * of the method <code>setLogWriter</code>. The
81      * method <code>setLogWriter</code> cannot create a <code>PrintStream</code> object
82      * that will be returned by <code>getLogStream</code>---the Java platform does
83      * not provide a backward conversion. As a result, a new application
84      * that uses <code>setLogWriter</code> and also uses a JDBC 1.0 driver that uses
85      * <code>getLogStream</code> will likely not see debugging information written
86      * by that driver.
87      *<P>
88      * In the Java 2 SDK, Standard Edition, version 1.3 release, this method checks
89      * to see that there is an <code>SQLPermission</code> object before setting
90      * the logging stream. If a <code>SecurityManager</code> exists and its
91      * <code>checkPermission</code> method denies setting the log writer, this
92      * method throws a <code>java.lang.SecurityException</code>.
93      *
94      * @param out the new logging/tracing <code>PrintStream</code> object;
95      * <code>null</code> to disable logging and tracing
96      * @throws SecurityException
97      * if a security manager exists and its
98      * <code>checkPermission</code> method denies
99      * setting the log writer
100      *
101      * @see SecurityManager#checkPermission
102      * @see #getLogWriter
103      * @since 1.2
104      */

105     public static void setLogWriter(java.io.PrintWriter JavaDoc out) {
106
107     SecurityManager JavaDoc sec = System.getSecurityManager();
108     if (sec != null) {
109         sec.checkPermission(SET_LOG_PERMISSION);
110     }
111     synchronized (logSync) {
112         logStream = null;
113         logWriter = out;
114     }
115     }
116
117
118     //---------------------------------------------------------------
119

120     /**
121      * Attempts to establish a connection to the given database URL.
122      * The <code>DriverManager</code> attempts to select an appropriate driver from
123      * the set of registered JDBC drivers.
124      *
125      * @param url a database url of the form
126      * <code> jdbc:<em>subprotocol</em>:<em>subname</em></code>
127      * @param info a list of arbitrary string tag/value pairs as
128      * connection arguments; normally at least a "user" and
129      * "password" property should be included
130      * @return a Connection to the URL
131      * @exception SQLException if a database access error occurs
132      */

133     public static synchronized Connection JavaDoc getConnection(String JavaDoc url,
134     java.util.Properties JavaDoc info) throws SQLException JavaDoc {
135   
136         // Gets the classloader of the code that called this method, may
137
// be null.
138
ClassLoader JavaDoc callerCL = DriverManager.getCallerClassLoader();
139
140         return (getConnection(url, info, callerCL));
141     }
142
143     /**
144      * Attempts to establish a connection to the given database URL.
145      * The <code>DriverManager</code> attempts to select an appropriate driver from
146      * the set of registered JDBC drivers.
147      *
148      * @param url a database url of the form
149      * <code>jdbc:<em>subprotocol</em>:<em>subname</em></code>
150      * @param user the database user on whose behalf the connection is being
151      * made
152      * @param password the user's password
153      * @return a connection to the URL
154      * @exception SQLException if a database access error occurs
155      */

156     public static synchronized Connection JavaDoc getConnection(String JavaDoc url,
157     String JavaDoc user, String JavaDoc password) throws SQLException JavaDoc {
158         java.util.Properties JavaDoc info = new java.util.Properties JavaDoc();
159
160         // Gets the classloader of the code that called this method, may
161
// be null.
162
ClassLoader JavaDoc callerCL = DriverManager.getCallerClassLoader();
163
164     if (user != null) {
165         info.put("user", user);
166     }
167     if (password != null) {
168         info.put("password", password);
169     }
170
171         return (getConnection(url, info, callerCL));
172     }
173
174     /**
175      * Attempts to establish a connection to the given database URL.
176      * The <code>DriverManager</code> attempts to select an appropriate driver from
177      * the set of registered JDBC drivers.
178      *
179      * @param url a database url of the form
180      * <code> jdbc:<em>subprotocol</em>:<em>subname</em></code>
181      * @return a connection to the URL
182      * @exception SQLException if a database access error occurs
183      */

184     public static synchronized Connection JavaDoc getConnection(String JavaDoc url)
185     throws SQLException JavaDoc {
186
187         java.util.Properties JavaDoc info = new java.util.Properties JavaDoc();
188
189         // Gets the classloader of the code that called this method, may
190
// be null.
191
ClassLoader JavaDoc callerCL = DriverManager.getCallerClassLoader();
192
193         return (getConnection(url, info, callerCL));
194     }
195
196     /**
197      * Attempts to locate a driver that understands the given URL.
198      * The <code>DriverManager</code> attempts to select an appropriate driver from
199      * the set of registered JDBC drivers.
200      *
201      * @param url a database URL of the form
202      * <code>jdbc:<em>subprotocol</em>:<em>subname</em></code>
203      * @return a <code>Driver</code> object representing a driver
204      * that can connect to the given URL
205      * @exception SQLException if a database access error occurs
206      */

207     public static synchronized Driver JavaDoc getDriver(String JavaDoc url)
208     throws SQLException JavaDoc {
209         println("DriverManager.getDriver(\"" + url + "\")");
210
211         if (!initialized) {
212             initialize();
213         }
214
215         // Gets the classloader of the code that called this method, may
216
// be null.
217
ClassLoader JavaDoc callerCL = DriverManager.getCallerClassLoader();
218
219         // Walk through the loaded drivers attempting to locate someone
220
// who understands the given URL.
221
for (int i = 0; i < drivers.size(); i++) {
222             DriverInfo di = (DriverInfo)drivers.elementAt(i);
223         // If the caller does not have permission to load the driver then
224
// skip it.
225
if ( getCallerClass(callerCL, di.driverClassName ) !=
226          di.driverClass ) {
227                 println(" skipping: " + di);
228                 continue;
229             }
230             try {
231                 println(" trying " + di);
232         if (di.driver.acceptsURL(url)) {
233             // Success!
234
println("getDriver returning " + di);
235                     return (di.driver);
236                 }
237             } catch (SQLException JavaDoc ex) {
238         // Drop through and try the next driver.
239
}
240         }
241
242         println("getDriver: no suitable driver");
243         throw new SQLException JavaDoc("No suitable driver", "08001");
244     }
245
246
247     /**
248      * Registers the given driver with the <code>DriverManager</code>.
249      * A newly-loaded driver class should call
250      * the method <code>registerDriver</code> to make itself
251      * known to the <code>DriverManager</code>.
252      *
253      * @param driver the new JDBC Driver that is to be registered with the
254      * <code>DriverManager</code>
255      * @exception SQLException if a database access error occurs
256      */

257     public static synchronized void registerDriver(java.sql.Driver JavaDoc driver)
258     throws SQLException JavaDoc {
259     if (!initialized) {
260         initialize();
261     }
262       
263     DriverInfo di = new DriverInfo();
264     di.driver = driver;
265     di.driverClass = driver.getClass();
266     di.driverClassName = di.driverClass.getName();
267     drivers.addElement(di);
268     println("registerDriver: " + di);
269     }
270
271     /**
272      * Drops a driver from the <code>DriverManager</code>'s list. Applets can only
273      * deregister drivers from their own classloaders.
274      *
275      * @param driver the JDBC Driver to drop
276      * @exception SQLException if a database access error occurs
277      */

278     public static synchronized void deregisterDriver(Driver JavaDoc driver)
279     throws SQLException JavaDoc {
280     // Gets the classloader of the code that called this method, may
281
// be null.
282
ClassLoader JavaDoc callerCL = DriverManager.getCallerClassLoader();
283     println("DriverManager.deregisterDriver: " + driver);
284       
285     // Walk through the loaded drivers.
286
int i;
287     DriverInfo di = null;
288     for (i = 0; i < drivers.size(); i++) {
289         di = (DriverInfo)drivers.elementAt(i);
290         if (di.driver == driver) {
291         break;
292         }
293     }
294     // If we can't find the driver just return.
295
if (i >= drivers.size()) {
296         println(" couldn't find driver to unload");
297         return;
298     }
299       
300     // If the caller does not have permission to load the driver then
301
// throw a security exception.
302
if ( getCallerClass(callerCL, di.driverClassName ) != di.driverClass ) {
303         throw new SecurityException JavaDoc();
304     }
305       
306     // Remove the driver. Other entries in drivers get shuffled down.
307
drivers.removeElementAt(i);
308       
309     }
310
311     /**
312      * Retrieves an Enumeration with all of the currently loaded JDBC drivers
313      * to which the current caller has access.
314      *
315      * <P><B>Note:</B> The classname of a driver can be found using
316      * <CODE>d.getClass().getName()</CODE>
317      *
318      * @return the list of JDBC Drivers loaded by the caller's class loader
319      */

320     public static synchronized java.util.Enumeration JavaDoc<Driver JavaDoc> getDrivers() {
321         java.util.Vector JavaDoc result = new java.util.Vector JavaDoc();
322
323         if (!initialized) {
324             initialize();
325         }
326
327         // Gets the classloader of the code that called this method, may
328
// be null.
329
ClassLoader JavaDoc callerCL = DriverManager.getCallerClassLoader();
330
331         // Walk through the loaded drivers.
332
for (int i = 0; i < drivers.size(); i++) {
333             DriverInfo di = (DriverInfo)drivers.elementAt(i);
334         // If the caller does not have permission to load the driver then
335
// skip it.
336
if ( getCallerClass(callerCL, di.driverClassName ) != di.driverClass ) {
337                 println(" skipping: " + di);
338                 continue;
339             }
340             result.addElement(di.driver);
341         }
342
343         return (result.elements());
344     }
345
346
347     /**
348      * Sets the maximum time in seconds that a driver will wait
349      * while attempting to connect to a database.
350      *
351      * @param seconds the login time limit in seconds
352      * @see #getLoginTimeout
353      */

354     public static void setLoginTimeout(int seconds) {
355         loginTimeout = seconds;
356     }
357
358     /**
359      * Gets the maximum time in seconds that a driver can wait
360      * when attempting to log in to a database.
361      *
362      * @return the driver login time limit in seconds
363      * @see #setLoginTimeout
364      */

365     public static int getLoginTimeout() {
366         return (loginTimeout);
367     }
368
369     /**
370      * Sets the logging/tracing PrintStream that is used
371      * by the <code>DriverManager</code>
372      * and all drivers.
373      *<P>
374      * In the Java 2 SDK, Standard Edition, version 1.3 release, this method checks
375      * to see that there is an <code>SQLPermission</code> object before setting
376      * the logging stream. If a <code>SecurityManager</code> exists and its
377      * <code>checkPermission</code> method denies setting the log writer, this
378      * method throws a <code>java.lang.SecurityException</code>.
379      *
380      * @param out the new logging/tracing PrintStream; to disable, set to <code>null</code>
381      * @deprecated
382      * @throws SecurityException if a security manager exists and its
383      * <code>checkPermission</code> method denies setting the log stream
384      *
385      * @see SecurityManager#checkPermission
386      * @see #getLogStream
387      */

388     @Deprecated JavaDoc
389     public static synchronized void setLogStream(java.io.PrintStream JavaDoc out) {
390         
391         SecurityManager JavaDoc sec = System.getSecurityManager();
392         if (sec != null) {
393             sec.checkPermission(SET_LOG_PERMISSION);
394         }
395
396         logStream = out;
397     if ( out != null )
398         logWriter = new java.io.PrintWriter JavaDoc(out);
399     else
400         logWriter = null;
401     }
402
403     /**
404      * Retrieves the logging/tracing PrintStream that is used by the <code>DriverManager</code>
405      * and all drivers.
406      *
407      * @return the logging/tracing PrintStream; if disabled, is <code>null</code>
408      * @deprecated
409      * @see #setLogStream
410      */

411     @Deprecated JavaDoc
412     public static java.io.PrintStream JavaDoc getLogStream() {
413         return logStream;
414     }
415
416     /**
417      * Prints a message to the current JDBC log stream.
418      *
419      * @param message a log or tracing message
420      */

421     public static void println(String JavaDoc message) {
422     synchronized (logSync) {
423         if (logWriter != null) {
424         logWriter.println(message);
425         
426         // automatic flushing is never enabled, so we must do it ourselves
427
logWriter.flush();
428         }
429     }
430     }
431
432     //------------------------------------------------------------------------
433

434     // Returns the class object that would be created if the code calling the
435
// driver manager had loaded the driver class, or null if the class
436
// is inaccessible.
437
private static Class JavaDoc getCallerClass(ClassLoader JavaDoc callerClassLoader,
438                     String JavaDoc driverClassName) {
439     Class JavaDoc callerC = null;
440
441     try {
442         callerC = Class.forName(driverClassName, true, callerClassLoader);
443     }
444     catch (Exception JavaDoc ex) {
445         callerC = null; // being very careful
446
}
447
448     return callerC;
449     }
450
451     private static void loadInitialDrivers() {
452         String JavaDoc drivers;
453         try {
454         drivers = (String JavaDoc) java.security.AccessController.doPrivileged(
455         new sun.security.action.GetPropertyAction("jdbc.drivers"));
456         } catch (Exception JavaDoc ex) {
457             drivers = null;
458         }
459         println("DriverManager.initialize: jdbc.drivers = " + drivers);
460         if (drivers == null) {
461             return;
462         }
463         while (drivers.length() != 0) {
464             int x = drivers.indexOf(':');
465             String JavaDoc driver;
466             if (x < 0) {
467                 driver = drivers;
468                 drivers = "";
469             } else {
470                 driver = drivers.substring(0, x);
471                 drivers = drivers.substring(x+1);
472             }
473             if (driver.length() == 0) {
474                 continue;
475             }
476             try {
477                 println("DriverManager.Initialize: loading " + driver);
478                 Class.forName(driver, true,
479                   ClassLoader.getSystemClassLoader());
480             } catch (Exception JavaDoc ex) {
481                 println("DriverManager.Initialize: load failed: " + ex);
482             }
483         }
484     }
485
486
487     // Worker method called by the public getConnection() methods.
488
private static synchronized Connection JavaDoc getConnection(
489     String JavaDoc url, java.util.Properties JavaDoc info, ClassLoader JavaDoc callerCL) throws SQLException JavaDoc {
490     
491         /*
492      * When callerCl is null, we should check the application's
493      * (which is invoking this class indirectly)
494      * classloader, so that the JDBC driver class outside rt.jar
495      * can be loaded from here.
496      */

497     if(callerCL == null) {
498         callerCL = Thread.currentThread().getContextClassLoader();
499     }
500       
501     if(url == null) {
502         throw new SQLException JavaDoc("The url cannot be null", "08001");
503     }
504     
505     println("DriverManager.getConnection(\"" + url + "\")");
506     
507     if (!initialized) {
508         initialize();
509     }
510
511     // Walk through the loaded drivers attempting to make a connection.
512
// Remember the first exception that gets raised so we can reraise it.
513
SQLException JavaDoc reason = null;
514     for (int i = 0; i < drivers.size(); i++) {
515         DriverInfo di = (DriverInfo)drivers.elementAt(i);
516       
517         // If the caller does not have permission to load the driver then
518
// skip it.
519
if ( getCallerClass(callerCL, di.driverClassName ) != di.driverClass ) {
520         println(" skipping: " + di);
521         continue;
522         }
523         try {
524         println(" trying " + di);
525         Connection JavaDoc result = di.driver.connect(url, info);
526         if (result != null) {
527             // Success!
528
println("getConnection returning " + di);
529             return (result);
530         }
531         } catch (SQLException JavaDoc ex) {
532         if (reason == null) {
533             reason = ex;
534         }
535         }
536     }
537     
538     // if we got here nobody could connect.
539
if (reason != null) {
540         println("getConnection failed: " + reason);
541         throw reason;
542     }
543     
544     println("getConnection: no suitable driver");
545     throw new SQLException JavaDoc("No suitable driver", "08001");
546     }
547
548
549     // Class initialization.
550
static void initialize() {
551         if (initialized) {
552             return;
553         }
554         initialized = true;
555         loadInitialDrivers();
556         println("JDBC DriverManager initialized");
557     }
558
559     // Prevent the DriverManager class from being instantiated.
560
private DriverManager(){}
561
562     private static java.util.Vector JavaDoc drivers = new java.util.Vector JavaDoc();
563     private static int loginTimeout = 0;
564     private static java.io.PrintWriter JavaDoc logWriter = null;
565     private static java.io.PrintStream JavaDoc logStream = null;
566     private static boolean initialized = false;
567
568     private static Object JavaDoc logSync = new Object JavaDoc();
569
570     // Returns the caller's class loader, or null if none
571
private static native ClassLoader JavaDoc getCallerClassLoader();
572
573 }
574
575
576 // DriverInfo is a package-private support class.
577
class DriverInfo {
578     Driver JavaDoc driver;
579     Class JavaDoc driverClass;
580     String JavaDoc driverClassName;
581
582     public String JavaDoc toString() {
583     return ("driver[className=" + driverClassName + "," + driver + "]");
584     }
585 }
586
Popular Tags