1 /* |
1 /* |
2 * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved. |
2 * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * |
4 * |
5 * This code is free software; you can redistribute it and/or modify it |
5 * This code is free software; you can redistribute it and/or modify it |
6 * under the terms of the GNU General Public License version 2 only, as |
6 * under the terms of the GNU General Public License version 2 only, as |
7 * published by the Free Software Foundation. Oracle designates this |
7 * published by the Free Software Foundation. Oracle designates this |
24 */ |
24 */ |
25 |
25 |
26 package java.sql; |
26 package java.sql; |
27 |
27 |
28 import java.util.Iterator; |
28 import java.util.Iterator; |
29 import java.sql.Driver; |
|
30 import java.util.ServiceLoader; |
29 import java.util.ServiceLoader; |
31 import java.security.AccessController; |
30 import java.security.AccessController; |
32 import java.security.PrivilegedAction; |
31 import java.security.PrivilegedAction; |
|
32 import java.util.concurrent.CopyOnWriteArrayList; |
33 |
33 |
34 |
34 |
35 /** |
35 /** |
36 * <P>The basic service for managing a set of JDBC drivers.<br> |
36 * <P>The basic service for managing a set of JDBC drivers.<br> |
37 * <B>NOTE:</B> The {@link <code>DataSource</code>} interface, new in the |
37 * <B>NOTE:</B> The {@link <code>DataSource</code>} interface, new in the |
77 * @see Connection |
77 * @see Connection |
78 */ |
78 */ |
79 public class DriverManager { |
79 public class DriverManager { |
80 |
80 |
81 |
81 |
|
82 // List of registered JDBC drivers |
|
83 private final static CopyOnWriteArrayList<Driver> registeredDrivers = new CopyOnWriteArrayList<Driver>(); |
|
84 private static volatile int loginTimeout = 0; |
|
85 private static volatile java.io.PrintWriter logWriter = null; |
|
86 private static volatile java.io.PrintStream logStream = null; |
|
87 // Used in println() to synchronize logWriter |
|
88 private final static Object logSync = new Object(); |
|
89 |
|
90 /* Prevent the DriverManager class from being instantiated. */ |
|
91 private DriverManager(){} |
|
92 |
|
93 |
|
94 /** |
|
95 * Load the initial JDBC drivers by checking the System property |
|
96 * jdbc.properties and then use the {@code ServiceLoader} mechanism |
|
97 */ |
|
98 static { |
|
99 loadInitialDrivers(); |
|
100 println("JDBC DriverManager initialized"); |
|
101 } |
|
102 |
82 /** |
103 /** |
83 * The <code>SQLPermission</code> constant that allows the |
104 * The <code>SQLPermission</code> constant that allows the |
84 * setting of the logging stream. |
105 * setting of the logging stream. |
85 * @since 1.3 |
106 * @since 1.3 |
86 */ |
107 */ |
233 * that can connect to the given URL |
254 * that can connect to the given URL |
234 * @exception SQLException if a database access error occurs |
255 * @exception SQLException if a database access error occurs |
235 */ |
256 */ |
236 public static Driver getDriver(String url) |
257 public static Driver getDriver(String url) |
237 throws SQLException { |
258 throws SQLException { |
238 java.util.Vector drivers = null; |
|
239 |
259 |
240 println("DriverManager.getDriver(\"" + url + "\")"); |
260 println("DriverManager.getDriver(\"" + url + "\")"); |
241 |
|
242 if (!initialized) { |
|
243 initialize(); |
|
244 } |
|
245 |
|
246 synchronized (DriverManager.class){ |
|
247 // use the read copy of the drivers vector |
|
248 drivers = readDrivers; |
|
249 } |
|
250 |
261 |
251 // Gets the classloader of the code that called this method, may |
262 // Gets the classloader of the code that called this method, may |
252 // be null. |
263 // be null. |
253 ClassLoader callerCL = DriverManager.getCallerClassLoader(); |
264 ClassLoader callerCL = DriverManager.getCallerClassLoader(); |
254 |
265 |
255 // Walk through the loaded drivers attempting to locate someone |
266 // Walk through the loaded registeredDrivers attempting to locate someone |
256 // who understands the given URL. |
267 // who understands the given URL. |
257 for (int i = 0; i < drivers.size(); i++) { |
268 for (Driver aDriver : registeredDrivers) { |
258 DriverInfo di = (DriverInfo)drivers.elementAt(i); |
|
259 // If the caller does not have permission to load the driver then |
269 // If the caller does not have permission to load the driver then |
260 // skip it. |
270 // skip it. |
261 if ( getCallerClass(callerCL, di.driverClassName ) != |
271 if(isDriverAllowed(aDriver, callerCL)) { |
262 di.driverClass ) { |
272 try { |
263 println(" skipping: " + di); |
273 if(aDriver.acceptsURL(url)) { |
264 continue; |
274 // Success! |
265 } |
275 println("getDriver returning " + aDriver.getClass().getName()); |
266 try { |
276 return (aDriver); |
267 println(" trying " + di); |
277 } |
268 if (di.driver.acceptsURL(url)) { |
278 |
269 // Success! |
279 } catch(SQLException sqe) { |
270 println("getDriver returning " + di); |
280 // Drop through and try the next driver. |
271 return (di.driver); |
|
272 } |
281 } |
273 } catch (SQLException ex) { |
282 } else { |
274 // Drop through and try the next driver. |
283 println(" skipping: " + aDriver.getClass().getName()); |
275 } |
284 } |
|
285 |
276 } |
286 } |
277 |
287 |
278 println("getDriver: no suitable driver"); |
288 println("getDriver: no suitable driver"); |
279 throw new SQLException("No suitable driver", "08001"); |
289 throw new SQLException("No suitable driver", "08001"); |
280 } |
290 } |
290 * <code>DriverManager</code> |
300 * <code>DriverManager</code> |
291 * @exception SQLException if a database access error occurs |
301 * @exception SQLException if a database access error occurs |
292 */ |
302 */ |
293 public static synchronized void registerDriver(java.sql.Driver driver) |
303 public static synchronized void registerDriver(java.sql.Driver driver) |
294 throws SQLException { |
304 throws SQLException { |
295 if (!initialized) { |
305 |
296 initialize(); |
306 /* Register the driver if it has not already been added to our list */ |
297 } |
307 if(driver != null) { |
298 |
308 registeredDrivers.addIfAbsent(driver); |
299 DriverInfo di = new DriverInfo(); |
309 } else { |
300 |
310 // This is for compatibility with the original DriverManager |
301 di.driver = driver; |
311 throw new NullPointerException(); |
302 di.driverClass = driver.getClass(); |
312 } |
303 di.driverClassName = di.driverClass.getName(); |
313 |
304 |
314 println("registerDriver: " + driver); |
305 // Not Required -- drivers.addElement(di); |
|
306 |
|
307 writeDrivers.addElement(di); |
|
308 println("registerDriver: " + di); |
|
309 |
|
310 /* update the read copy of drivers vector */ |
|
311 readDrivers = (java.util.Vector) writeDrivers.clone(); |
|
312 |
315 |
313 } |
316 } |
314 |
317 |
315 /** |
318 /** |
316 * Drops a driver from the <code>DriverManager</code>'s list. |
319 * Drops a driver from the <code>DriverManager</code>'s list. |
319 * @param driver the JDBC Driver to drop |
322 * @param driver the JDBC Driver to drop |
320 * @exception SQLException if a database access error occurs |
323 * @exception SQLException if a database access error occurs |
321 */ |
324 */ |
322 public static synchronized void deregisterDriver(Driver driver) |
325 public static synchronized void deregisterDriver(Driver driver) |
323 throws SQLException { |
326 throws SQLException { |
|
327 if (driver == null) { |
|
328 return; |
|
329 } |
|
330 |
324 // Gets the classloader of the code that called this method, |
331 // Gets the classloader of the code that called this method, |
325 // may be null. |
332 // may be null. |
326 ClassLoader callerCL = DriverManager.getCallerClassLoader(); |
333 ClassLoader callerCL = DriverManager.getCallerClassLoader(); |
327 println("DriverManager.deregisterDriver: " + driver); |
334 println("DriverManager.deregisterDriver: " + driver); |
328 |
335 |
329 // Walk through the loaded drivers. |
336 if(registeredDrivers.contains(driver)) { |
330 int i; |
337 if (isDriverAllowed(driver, callerCL)) { |
331 DriverInfo di = null; |
338 registeredDrivers.remove(driver); |
332 for (i = 0; i < writeDrivers.size(); i++) { |
339 } else { |
333 di = (DriverInfo)writeDrivers.elementAt(i); |
340 // If the caller does not have permission to load the driver then |
334 if (di.driver == driver) { |
341 // throw a SecurityException. |
335 break; |
342 throw new SecurityException(); |
336 } |
343 } |
337 } |
344 } else { |
338 // If we can't find the driver just return. |
|
339 if (i >= writeDrivers.size()) { |
|
340 println(" couldn't find driver to unload"); |
345 println(" couldn't find driver to unload"); |
341 return; |
346 } |
342 } |
|
343 |
|
344 // If the caller does not have permission to load the driver then |
|
345 // throw a security exception. |
|
346 if (getCallerClass(callerCL, di.driverClassName ) != di.driverClass ) { |
|
347 throw new SecurityException(); |
|
348 } |
|
349 |
|
350 // Remove the driver. Other entries in drivers get shuffled down. |
|
351 writeDrivers.removeElementAt(i); |
|
352 |
|
353 /* update the read copy of drivers vector */ |
|
354 readDrivers = (java.util.Vector) writeDrivers.clone(); |
|
355 } |
347 } |
356 |
348 |
357 /** |
349 /** |
358 * Retrieves an Enumeration with all of the currently loaded JDBC drivers |
350 * Retrieves an Enumeration with all of the currently loaded JDBC drivers |
359 * to which the current caller has access. |
351 * to which the current caller has access. |
362 * <CODE>d.getClass().getName()</CODE> |
354 * <CODE>d.getClass().getName()</CODE> |
363 * |
355 * |
364 * @return the list of JDBC Drivers loaded by the caller's class loader |
356 * @return the list of JDBC Drivers loaded by the caller's class loader |
365 */ |
357 */ |
366 public static java.util.Enumeration<Driver> getDrivers() { |
358 public static java.util.Enumeration<Driver> getDrivers() { |
367 java.util.Vector<Driver> result = new java.util.Vector<>(); |
359 java.util.Vector<Driver> result = new java.util.Vector<Driver>(); |
368 java.util.Vector drivers = null; |
|
369 |
|
370 if (!initialized) { |
|
371 initialize(); |
|
372 } |
|
373 |
|
374 synchronized (DriverManager.class){ |
|
375 // use the readcopy of drivers |
|
376 drivers = readDrivers; |
|
377 } |
|
378 |
360 |
379 // Gets the classloader of the code that called this method, may |
361 // Gets the classloader of the code that called this method, may |
380 // be null. |
362 // be null. |
381 ClassLoader callerCL = DriverManager.getCallerClassLoader(); |
363 ClassLoader callerCL = DriverManager.getCallerClassLoader(); |
382 |
364 |
383 // Walk through the loaded drivers. |
365 // Walk through the loaded registeredDrivers. |
384 for (int i = 0; i < drivers.size(); i++) { |
366 for(Driver aDriver : registeredDrivers) { |
385 DriverInfo di = (DriverInfo)drivers.elementAt(i); |
|
386 // If the caller does not have permission to load the driver then |
367 // If the caller does not have permission to load the driver then |
387 // skip it. |
368 // skip it. |
388 if ( getCallerClass(callerCL, di.driverClassName ) != di.driverClass ) { |
369 if(isDriverAllowed(aDriver, callerCL)) { |
389 println(" skipping: " + di); |
370 result.addElement(aDriver); |
390 continue; |
371 } else { |
391 } |
372 println(" skipping: " + aDriver.getClass().getName()); |
392 result.addElement(di.driver); |
373 } |
393 } |
374 } |
394 |
|
395 return (result.elements()); |
375 return (result.elements()); |
396 } |
376 } |
397 |
377 |
398 |
378 |
399 /** |
379 /** |
479 } |
459 } |
480 } |
460 } |
481 |
461 |
482 //------------------------------------------------------------------------ |
462 //------------------------------------------------------------------------ |
483 |
463 |
484 // Returns the class object that would be created if the code calling the |
464 // Indicates whether the class object that would be created if the code calling |
485 // driver manager had loaded the driver class, or null if the class |
465 // DriverManager is accessible. |
486 // is inaccessible. |
466 private static boolean isDriverAllowed(Driver driver, ClassLoader classLoader) { |
487 private static Class getCallerClass(ClassLoader callerClassLoader, |
467 boolean result = false; |
488 String driverClassName) { |
468 if(driver != null) { |
489 Class callerC = null; |
469 Class<?> aClass = null; |
490 |
470 try { |
491 try { |
471 aClass = Class.forName(driver.getClass().getName(), true, classLoader); |
492 callerC = Class.forName(driverClassName, true, callerClassLoader); |
472 } catch (Exception ex) { |
493 } |
473 result = false; |
494 catch (Exception ex) { |
474 } |
495 callerC = null; // being very careful |
475 |
496 } |
476 result = ( aClass == driver.getClass() ) ? true : false; |
497 |
477 } |
498 return callerC; |
478 |
|
479 return result; |
499 } |
480 } |
500 |
481 |
501 private static void loadInitialDrivers() { |
482 private static void loadInitialDrivers() { |
502 String drivers; |
483 String drivers; |
503 try { |
484 try { |
542 return null; |
523 return null; |
543 } |
524 } |
544 }); |
525 }); |
545 |
526 |
546 println("DriverManager.initialize: jdbc.drivers = " + drivers); |
527 println("DriverManager.initialize: jdbc.drivers = " + drivers); |
547 if (drivers == null) { |
528 |
|
529 if (drivers == null || drivers.equals("")) { |
548 return; |
530 return; |
549 } |
531 } |
550 while (drivers.length() != 0) { |
532 String[] driversList = drivers.split(":"); |
551 int x = drivers.indexOf(':'); |
533 println("number of Drivers:" + driversList.length); |
552 String driver; |
534 for (String aDriver : driversList) { |
553 if (x < 0) { |
|
554 driver = drivers; |
|
555 drivers = ""; |
|
556 } else { |
|
557 driver = drivers.substring(0, x); |
|
558 drivers = drivers.substring(x+1); |
|
559 } |
|
560 if (driver.length() == 0) { |
|
561 continue; |
|
562 } |
|
563 try { |
535 try { |
564 println("DriverManager.Initialize: loading " + driver); |
536 println("DriverManager.Initialize: loading " + aDriver); |
565 Class.forName(driver, true, |
537 Class.forName(aDriver, true, |
566 ClassLoader.getSystemClassLoader()); |
538 ClassLoader.getSystemClassLoader()); |
567 } catch (Exception ex) { |
539 } catch (Exception ex) { |
568 println("DriverManager.Initialize: load failed: " + ex); |
540 println("DriverManager.Initialize: load failed: " + ex); |
569 } |
541 } |
570 } |
542 } |
571 } |
543 } |
572 |
544 |
573 |
545 |
574 // Worker method called by the public getConnection() methods. |
546 // Worker method called by the public getConnection() methods. |
575 private static Connection getConnection( |
547 private static Connection getConnection( |
576 String url, java.util.Properties info, ClassLoader callerCL) throws SQLException { |
548 String url, java.util.Properties info, ClassLoader callerCL) throws SQLException { |
577 java.util.Vector drivers = null; |
|
578 /* |
549 /* |
579 * When callerCl is null, we should check the application's |
550 * When callerCl is null, we should check the application's |
580 * (which is invoking this class indirectly) |
551 * (which is invoking this class indirectly) |
581 * classloader, so that the JDBC driver class outside rt.jar |
552 * classloader, so that the JDBC driver class outside rt.jar |
582 * can be loaded from here. |
553 * can be loaded from here. |
592 throw new SQLException("The url cannot be null", "08001"); |
563 throw new SQLException("The url cannot be null", "08001"); |
593 } |
564 } |
594 |
565 |
595 println("DriverManager.getConnection(\"" + url + "\")"); |
566 println("DriverManager.getConnection(\"" + url + "\")"); |
596 |
567 |
597 if (!initialized) { |
568 // Walk through the loaded registeredDrivers attempting to make a connection. |
598 initialize(); |
|
599 } |
|
600 |
|
601 synchronized (DriverManager.class){ |
|
602 // use the readcopy of drivers |
|
603 drivers = readDrivers; |
|
604 } |
|
605 |
|
606 // Walk through the loaded drivers attempting to make a connection. |
|
607 // Remember the first exception that gets raised so we can reraise it. |
569 // Remember the first exception that gets raised so we can reraise it. |
608 SQLException reason = null; |
570 SQLException reason = null; |
609 for (int i = 0; i < drivers.size(); i++) { |
571 |
610 DriverInfo di = (DriverInfo)drivers.elementAt(i); |
572 for(Driver aDriver : registeredDrivers) { |
611 |
|
612 // If the caller does not have permission to load the driver then |
573 // If the caller does not have permission to load the driver then |
613 // skip it. |
574 // skip it. |
614 if ( getCallerClass(callerCL, di.driverClassName ) != di.driverClass ) { |
575 if(isDriverAllowed(aDriver, callerCL)) { |
615 println(" skipping: " + di); |
576 try { |
616 continue; |
577 println(" trying " + aDriver.getClass().getName()); |
617 } |
578 Connection con = aDriver.connect(url, info); |
618 try { |
579 if (con != null) { |
619 println(" trying " + di); |
580 // Success! |
620 Connection result = di.driver.connect(url, info); |
581 println("getConnection returning " + aDriver.getClass().getName()); |
621 if (result != null) { |
582 return (con); |
622 // Success! |
583 } |
623 println("getConnection returning " + di); |
584 } catch (SQLException ex) { |
624 return (result); |
585 if (reason == null) { |
|
586 reason = ex; |
|
587 } |
625 } |
588 } |
626 } catch (SQLException ex) { |
589 |
627 if (reason == null) { |
590 } else { |
628 reason = ex; |
591 println(" skipping: " + aDriver.getClass().getName()); |
629 } |
592 } |
630 } |
593 |
631 } |
594 } |
632 |
595 |
633 // if we got here nobody could connect. |
596 // if we got here nobody could connect. |
634 if (reason != null) { |
597 if (reason != null) { |
635 println("getConnection failed: " + reason); |
598 println("getConnection failed: " + reason); |
638 |
601 |
639 println("getConnection: no suitable driver found for "+ url); |
602 println("getConnection: no suitable driver found for "+ url); |
640 throw new SQLException("No suitable driver found for "+ url, "08001"); |
603 throw new SQLException("No suitable driver found for "+ url, "08001"); |
641 } |
604 } |
642 |
605 |
643 |
|
644 // Class initialization. |
|
645 static void initialize() { |
|
646 if (initialized) { |
|
647 return; |
|
648 } |
|
649 initialized = true; |
|
650 loadInitialDrivers(); |
|
651 println("JDBC DriverManager initialized"); |
|
652 } |
|
653 |
|
654 /* Prevent the DriverManager class from being instantiated. */ |
|
655 private DriverManager(){} |
|
656 |
|
657 /* write copy of the drivers vector */ |
|
658 private static java.util.Vector writeDrivers = new java.util.Vector(); |
|
659 |
|
660 /* write copy of the drivers vector */ |
|
661 private static java.util.Vector readDrivers = new java.util.Vector(); |
|
662 |
|
663 private static int loginTimeout = 0; |
|
664 private static java.io.PrintWriter logWriter = null; |
|
665 private static java.io.PrintStream logStream = null; |
|
666 private static boolean initialized = false; |
|
667 |
|
668 private static Object logSync = new Object(); |
|
669 |
|
670 /* Returns the caller's class loader, or null if none */ |
606 /* Returns the caller's class loader, or null if none */ |
671 private static native ClassLoader getCallerClassLoader(); |
607 private static native ClassLoader getCallerClassLoader(); |
672 |
608 |
673 } |
609 } |
674 |
|
675 // DriverInfo is a package-private support class. |
|
676 class DriverInfo { |
|
677 Driver driver; |
|
678 Class driverClass; |
|
679 String driverClassName; |
|
680 |
|
681 public String toString() { |
|
682 return ("driver[className=" + driverClassName + "," + driver + "]"); |
|
683 } |
|
684 } |
|