src/share/classes/java/sql/DriverManager.java

Print this page




  71  *
  72  * <P>
  73  * Starting with the Java 2 SDK, Standard Edition, version 1.3, a
  74  * logging stream can be set only if the proper
  75  * permission has been granted.  Normally this will be done with
  76  * the tool PolicyTool, which can be used to grant <code>permission
  77  * java.sql.SQLPermission "setLog"</code>.
  78  * @see Driver
  79  * @see Connection
  80  */
  81 public class DriverManager {
  82 
  83 
  84     // List of registered JDBC drivers
  85     private final static CopyOnWriteArrayList<DriverInfo> registeredDrivers = new CopyOnWriteArrayList<>();
  86     private static volatile int loginTimeout = 0;
  87     private static volatile java.io.PrintWriter logWriter = null;
  88     private static volatile java.io.PrintStream logStream = null;
  89     // Used in println() to synchronize logWriter
  90     private final static  Object logSync = new Object();



  91 
  92     /* Prevent the DriverManager class from being instantiated. */
  93     private DriverManager(){}
  94 
  95 
  96     /**
  97      * Load the initial JDBC drivers by checking the System property
  98      * jdbc.properties and then use the {@code ServiceLoader} mechanism
  99      */
 100     static {
 101         loadInitialDrivers();
 102         println("JDBC DriverManager initialized");
 103     }
 104 
 105     /**
 106      * The <code>SQLPermission</code> constant that allows the
 107      * setting of the logging stream.
 108      * @since 1.3
 109      */
 110     final static SQLPermission SET_LOG_PERMISSION =
 111         new SQLPermission("setLog");
 112 
 113     /**
 114      * The {@code SQLPermission} constant that allows the
 115      * un-register a registered JDBC driver.
 116      * @since 1.8
 117      */
 118     final static SQLPermission DEREGISTER_DRIVER_PERMISSION =
 119         new SQLPermission("deregisterDriver");
 120 
 121     //--------------------------JDBC 2.0-----------------------------
 122 
 123     /**
 124      * Retrieves the log writer.


 270         return (getConnection(url, info, Reflection.getCallerClass()));
 271     }
 272 
 273     /**
 274      * Attempts to locate a driver that understands the given URL.
 275      * The <code>DriverManager</code> attempts to select an appropriate driver from
 276      * the set of registered JDBC drivers.
 277      *
 278      * @param url a database URL of the form
 279      *     <code>jdbc:<em>subprotocol</em>:<em>subname</em></code>
 280      * @return a <code>Driver</code> object representing a driver
 281      * that can connect to the given URL
 282      * @exception SQLException if a database access error occurs
 283      */
 284     @CallerSensitive
 285     public static Driver getDriver(String url)
 286         throws SQLException {
 287 
 288         println("DriverManager.getDriver(\"" + url + "\")");
 289 


 290         Class<?> callerClass = Reflection.getCallerClass();
 291 
 292         // Walk through the loaded registeredDrivers attempting to locate someone
 293         // who understands the given URL.
 294         for (DriverInfo aDriver : registeredDrivers) {
 295             // If the caller does not have permission to load the driver then
 296             // skip it.
 297             if(isDriverAllowed(aDriver.driver, callerClass)) {
 298                 try {
 299                     if(aDriver.driver.acceptsURL(url)) {
 300                         // Success!
 301                         println("getDriver returning " + aDriver.driver.getClass().getName());
 302                     return (aDriver.driver);
 303                     }
 304 
 305                 } catch(SQLException sqe) {
 306                     // Drop through and try the next driver.
 307                 }
 308             } else {
 309                 println("    skipping: " + aDriver.driver.getClass().getName());


 311 
 312         }
 313 
 314         println("getDriver: no suitable driver");
 315         throw new SQLException("No suitable driver", "08001");
 316     }
 317 
 318 
 319     /**
 320      * Registers the given driver with the {@code DriverManager}.
 321      * A newly-loaded driver class should call
 322      * the method {@code registerDriver} to make itself
 323      * known to the {@code DriverManager}. If the driver is currently
 324      * registered, no action is taken.
 325      *
 326      * @param driver the new JDBC Driver that is to be registered with the
 327      *               {@code DriverManager}
 328      * @exception SQLException if a database access error occurs
 329      * @exception NullPointerException if {@code driver} is null
 330      */
 331     public static synchronized void registerDriver(java.sql.Driver driver)
 332         throws SQLException {
 333 
 334         registerDriver(driver, null);
 335     }
 336 
 337     /**
 338      * Registers the given driver with the {@code DriverManager}.
 339      * A newly-loaded driver class should call
 340      * the method {@code registerDriver} to make itself
 341      * known to the {@code DriverManager}. If the driver is currently
 342      * registered, no action is taken.
 343      *
 344      * @param driver the new JDBC Driver that is to be registered with the
 345      *               {@code DriverManager}
 346      * @param da     the {@code DriverAction} implementation to be used when
 347      *               {@code DriverManager#deregisterDriver} is called
 348      * @exception SQLException if a database access error occurs
 349      * @exception NullPointerException if {@code driver} is null
 350      * @since 1.8
 351      */
 352     public static synchronized void registerDriver(java.sql.Driver driver,
 353             DriverAction da)
 354         throws SQLException {
 355 
 356         /* Register the driver if it has not already been added to our list */
 357         if(driver != null) {
 358             registeredDrivers.addIfAbsent(new DriverInfo(driver, da));
 359         } else {
 360             // This is for compatibility with the original DriverManager
 361             throw new NullPointerException();
 362         }
 363 
 364         println("registerDriver: " + driver);
 365 
 366     }
 367 
 368     /**
 369      * Removes the specified driver from the {@code DriverManager}'s list of
 370      * registered drivers.
 371      * <p>
 372      * If a {@code null} value is specified for the driver to be removed, then no


 420                 throw new SecurityException();
 421             }
 422         } else {
 423             println("    couldn't find driver to unload");
 424         }
 425     }
 426 
 427     /**
 428      * Retrieves an Enumeration with all of the currently loaded JDBC drivers
 429      * to which the current caller has access.
 430      *
 431      * <P><B>Note:</B> The classname of a driver can be found using
 432      * <CODE>d.getClass().getName()</CODE>
 433      *
 434      * @return the list of JDBC Drivers loaded by the caller's class loader
 435      */
 436     @CallerSensitive
 437     public static java.util.Enumeration<Driver> getDrivers() {
 438         java.util.Vector<Driver> result = new java.util.Vector<>();
 439 


 440         Class<?> callerClass = Reflection.getCallerClass();
 441 
 442         // Walk through the loaded registeredDrivers.
 443         for(DriverInfo aDriver : registeredDrivers) {
 444             // If the caller does not have permission to load the driver then
 445             // skip it.
 446             if(isDriverAllowed(aDriver.driver, callerClass)) {
 447                 result.addElement(aDriver.driver);
 448             } else {
 449                 println("    skipping: " + aDriver.getClass().getName());
 450             }
 451         }
 452         return (result.elements());
 453     }
 454 
 455 
 456     /**
 457      * Sets the maximum time in seconds that a driver will wait
 458      * while attempting to connect to a database once the driver has
 459      * been identified.


 547         ClassLoader callerCL = caller != null ? caller.getClassLoader() : null;
 548         return isDriverAllowed(driver, callerCL);
 549     }
 550 
 551     private static boolean isDriverAllowed(Driver driver, ClassLoader classLoader) {
 552         boolean result = false;
 553         if(driver != null) {
 554             Class<?> aClass = null;
 555             try {
 556                 aClass =  Class.forName(driver.getClass().getName(), true, classLoader);
 557             } catch (Exception ex) {
 558                 result = false;
 559             }
 560 
 561              result = ( aClass == driver.getClass() ) ? true : false;
 562         }
 563 
 564         return result;
 565     }
 566 




















 567     private static void loadInitialDrivers() {
 568         String drivers;
 569         try {
 570             drivers = AccessController.doPrivileged(new PrivilegedAction<String>() {
 571                 public String run() {
 572                     return System.getProperty("jdbc.drivers");
 573                 }
 574             });
 575         } catch (Exception ex) {
 576             drivers = null;
 577         }
 578         // If the driver is packaged as a Service Provider, load it.
 579         // Get all the drivers through the classloader
 580         // exposed as a java.sql.Driver.class service.
 581         // ServiceLoader.load() replaces the sun.misc.Providers()
 582 
 583         AccessController.doPrivileged(new PrivilegedAction<Void>() {
 584             public Void run() {
 585 
 586                 ServiceLoader<Driver> loadedDrivers = ServiceLoader.load(Driver.class);


 634         /*
 635          * When callerCl is null, we should check the application's
 636          * (which is invoking this class indirectly)
 637          * classloader, so that the JDBC driver class outside rt.jar
 638          * can be loaded from here.
 639          */
 640         ClassLoader callerCL = caller != null ? caller.getClassLoader() : null;
 641         synchronized(DriverManager.class) {
 642             // synchronize loading of the correct classloader.
 643             if (callerCL == null) {
 644                 callerCL = Thread.currentThread().getContextClassLoader();
 645             }
 646         }
 647 
 648         if(url == null) {
 649             throw new SQLException("The url cannot be null", "08001");
 650         }
 651 
 652         println("DriverManager.getConnection(\"" + url + "\")");
 653 


 654         // Walk through the loaded registeredDrivers attempting to make a connection.
 655         // Remember the first exception that gets raised so we can reraise it.
 656         SQLException reason = null;
 657 
 658         for(DriverInfo aDriver : registeredDrivers) {
 659             // If the caller does not have permission to load the driver then
 660             // skip it.
 661             if(isDriverAllowed(aDriver.driver, callerCL)) {
 662                 try {
 663                     println("    trying " + aDriver.driver.getClass().getName());
 664                     Connection con = aDriver.driver.connect(url, info);
 665                     if (con != null) {
 666                         // Success!
 667                         println("getConnection returning " + aDriver.driver.getClass().getName());
 668                         return (con);
 669                     }
 670                 } catch (SQLException ex) {
 671                     if (reason == null) {
 672                         reason = ex;
 673                     }




  71  *
  72  * <P>
  73  * Starting with the Java 2 SDK, Standard Edition, version 1.3, a
  74  * logging stream can be set only if the proper
  75  * permission has been granted.  Normally this will be done with
  76  * the tool PolicyTool, which can be used to grant <code>permission
  77  * java.sql.SQLPermission "setLog"</code>.
  78  * @see Driver
  79  * @see Connection
  80  */
  81 public class DriverManager {
  82 
  83 
  84     // List of registered JDBC drivers
  85     private final static CopyOnWriteArrayList<DriverInfo> registeredDrivers = new CopyOnWriteArrayList<>();
  86     private static volatile int loginTimeout = 0;
  87     private static volatile java.io.PrintWriter logWriter = null;
  88     private static volatile java.io.PrintStream logStream = null;
  89     // Used in println() to synchronize logWriter
  90     private final static  Object logSync = new Object();
  91     // Used in initDriversIfNeeded() to synchronize driversInitialized
  92     private final static  Object driversSync = new Object();
  93     private static volatile boolean driversInitialized;
  94 
  95     /* Prevent the DriverManager class from being instantiated. */
  96     private DriverManager(){}
  97 










  98     /**
  99      * The <code>SQLPermission</code> constant that allows the
 100      * setting of the logging stream.
 101      * @since 1.3
 102      */
 103     final static SQLPermission SET_LOG_PERMISSION =
 104         new SQLPermission("setLog");
 105 
 106     /**
 107      * The {@code SQLPermission} constant that allows the
 108      * un-register a registered JDBC driver.
 109      * @since 1.8
 110      */
 111     final static SQLPermission DEREGISTER_DRIVER_PERMISSION =
 112         new SQLPermission("deregisterDriver");
 113 
 114     //--------------------------JDBC 2.0-----------------------------
 115 
 116     /**
 117      * Retrieves the log writer.


 263         return (getConnection(url, info, Reflection.getCallerClass()));
 264     }
 265 
 266     /**
 267      * Attempts to locate a driver that understands the given URL.
 268      * The <code>DriverManager</code> attempts to select an appropriate driver from
 269      * the set of registered JDBC drivers.
 270      *
 271      * @param url a database URL of the form
 272      *     <code>jdbc:<em>subprotocol</em>:<em>subname</em></code>
 273      * @return a <code>Driver</code> object representing a driver
 274      * that can connect to the given URL
 275      * @exception SQLException if a database access error occurs
 276      */
 277     @CallerSensitive
 278     public static Driver getDriver(String url)
 279         throws SQLException {
 280 
 281         println("DriverManager.getDriver(\"" + url + "\")");
 282         
 283         initDriversIfNeeded();
 284 
 285         Class<?> callerClass = Reflection.getCallerClass();
 286 
 287         // Walk through the loaded registeredDrivers attempting to locate someone
 288         // who understands the given URL.
 289         for (DriverInfo aDriver : registeredDrivers) {
 290             // If the caller does not have permission to load the driver then
 291             // skip it.
 292             if(isDriverAllowed(aDriver.driver, callerClass)) {
 293                 try {
 294                     if(aDriver.driver.acceptsURL(url)) {
 295                         // Success!
 296                         println("getDriver returning " + aDriver.driver.getClass().getName());
 297                     return (aDriver.driver);
 298                     }
 299 
 300                 } catch(SQLException sqe) {
 301                     // Drop through and try the next driver.
 302                 }
 303             } else {
 304                 println("    skipping: " + aDriver.driver.getClass().getName());


 306 
 307         }
 308 
 309         println("getDriver: no suitable driver");
 310         throw new SQLException("No suitable driver", "08001");
 311     }
 312 
 313 
 314     /**
 315      * Registers the given driver with the {@code DriverManager}.
 316      * A newly-loaded driver class should call
 317      * the method {@code registerDriver} to make itself
 318      * known to the {@code DriverManager}. If the driver is currently
 319      * registered, no action is taken.
 320      *
 321      * @param driver the new JDBC Driver that is to be registered with the
 322      *               {@code DriverManager}
 323      * @exception SQLException if a database access error occurs
 324      * @exception NullPointerException if {@code driver} is null
 325      */
 326     public static void registerDriver(java.sql.Driver driver)
 327         throws SQLException {
 328 
 329         registerDriver(driver, null);
 330     }
 331 
 332     /**
 333      * Registers the given driver with the {@code DriverManager}.
 334      * A newly-loaded driver class should call
 335      * the method {@code registerDriver} to make itself
 336      * known to the {@code DriverManager}. If the driver is currently
 337      * registered, no action is taken.
 338      *
 339      * @param driver the new JDBC Driver that is to be registered with the
 340      *               {@code DriverManager}
 341      * @param da     the {@code DriverAction} implementation to be used when
 342      *               {@code DriverManager#deregisterDriver} is called
 343      * @exception SQLException if a database access error occurs
 344      * @exception NullPointerException if {@code driver} is null
 345      * @since 1.8
 346      */
 347     public static void registerDriver(java.sql.Driver driver,
 348             DriverAction da)
 349         throws SQLException {
 350         
 351         /* Register the driver if it has not already been added to our list */
 352         if(driver != null) {
 353             registeredDrivers.addIfAbsent(new DriverInfo(driver, da));
 354         } else {
 355             // This is for compatibility with the original DriverManager
 356             throw new NullPointerException();
 357         }
 358 
 359         println("registerDriver: " + driver);
 360 
 361     }
 362 
 363     /**
 364      * Removes the specified driver from the {@code DriverManager}'s list of
 365      * registered drivers.
 366      * <p>
 367      * If a {@code null} value is specified for the driver to be removed, then no


 415                 throw new SecurityException();
 416             }
 417         } else {
 418             println("    couldn't find driver to unload");
 419         }
 420     }
 421 
 422     /**
 423      * Retrieves an Enumeration with all of the currently loaded JDBC drivers
 424      * to which the current caller has access.
 425      *
 426      * <P><B>Note:</B> The classname of a driver can be found using
 427      * <CODE>d.getClass().getName()</CODE>
 428      *
 429      * @return the list of JDBC Drivers loaded by the caller's class loader
 430      */
 431     @CallerSensitive
 432     public static java.util.Enumeration<Driver> getDrivers() {
 433         java.util.Vector<Driver> result = new java.util.Vector<>();
 434   
 435         initDriversIfNeeded();
 436 
 437         Class<?> callerClass = Reflection.getCallerClass();
 438 
 439         // Walk through the loaded registeredDrivers.
 440         for(DriverInfo aDriver : registeredDrivers) {
 441             // If the caller does not have permission to load the driver then
 442             // skip it.
 443             if(isDriverAllowed(aDriver.driver, callerClass)) {
 444                 result.addElement(aDriver.driver);
 445             } else {
 446                 println("    skipping: " + aDriver.getClass().getName());
 447             }
 448         }
 449         return (result.elements());
 450     }
 451 
 452 
 453     /**
 454      * Sets the maximum time in seconds that a driver will wait
 455      * while attempting to connect to a database once the driver has
 456      * been identified.


 544         ClassLoader callerCL = caller != null ? caller.getClassLoader() : null;
 545         return isDriverAllowed(driver, callerCL);
 546     }
 547 
 548     private static boolean isDriverAllowed(Driver driver, ClassLoader classLoader) {
 549         boolean result = false;
 550         if(driver != null) {
 551             Class<?> aClass = null;
 552             try {
 553                 aClass =  Class.forName(driver.getClass().getName(), true, classLoader);
 554             } catch (Exception ex) {
 555                 result = false;
 556             }
 557 
 558              result = ( aClass == driver.getClass() ) ? true : false;
 559         }
 560 
 561         return result;
 562     }
 563 
 564     /*
 565      * Load the initial JDBC drivers by checking the System property
 566      * jdbc.properties and then use the {@code ServiceLoader} mechanism
 567     */
 568     private static void initDriversIfNeeded() {
 569         // Drivers have been inited earleir
 570         if (driversInitialized) {
 571             return;
 572         }
 573         
 574         synchronized(driversSync) {
 575             if (driversInitialized) {
 576                 return;
 577             }
 578             loadInitialDrivers();
 579             driversInitialized = true;
 580             println("JDBC DriverManager initialized");
 581         }
 582     }
 583 
 584     private static void loadInitialDrivers() {
 585         String drivers;
 586         try {
 587             drivers = AccessController.doPrivileged(new PrivilegedAction<String>() {
 588                 public String run() {
 589                     return System.getProperty("jdbc.drivers");
 590                 }
 591             });
 592         } catch (Exception ex) {
 593             drivers = null;
 594         }
 595         // If the driver is packaged as a Service Provider, load it.
 596         // Get all the drivers through the classloader
 597         // exposed as a java.sql.Driver.class service.
 598         // ServiceLoader.load() replaces the sun.misc.Providers()
 599 
 600         AccessController.doPrivileged(new PrivilegedAction<Void>() {
 601             public Void run() {
 602 
 603                 ServiceLoader<Driver> loadedDrivers = ServiceLoader.load(Driver.class);


 651         /*
 652          * When callerCl is null, we should check the application's
 653          * (which is invoking this class indirectly)
 654          * classloader, so that the JDBC driver class outside rt.jar
 655          * can be loaded from here.
 656          */
 657         ClassLoader callerCL = caller != null ? caller.getClassLoader() : null;
 658         synchronized(DriverManager.class) {
 659             // synchronize loading of the correct classloader.
 660             if (callerCL == null) {
 661                 callerCL = Thread.currentThread().getContextClassLoader();
 662             }
 663         }
 664 
 665         if(url == null) {
 666             throw new SQLException("The url cannot be null", "08001");
 667         }
 668 
 669         println("DriverManager.getConnection(\"" + url + "\")");
 670         
 671         initDriversIfNeeded();
 672 
 673         // Walk through the loaded registeredDrivers attempting to make a connection.
 674         // Remember the first exception that gets raised so we can reraise it.
 675         SQLException reason = null;
 676 
 677         for(DriverInfo aDriver : registeredDrivers) {
 678             // If the caller does not have permission to load the driver then
 679             // skip it.
 680             if(isDriverAllowed(aDriver.driver, callerCL)) {
 681                 try {
 682                     println("    trying " + aDriver.driver.getClass().getName());
 683                     Connection con = aDriver.driver.connect(url, info);
 684                     if (con != null) {
 685                         // Success!
 686                         println("getConnection returning " + aDriver.driver.getClass().getName());
 687                         return (con);
 688                     }
 689                 } catch (SQLException ex) {
 690                     if (reason == null) {
 691                         reason = ex;
 692                     }