jdk/src/share/classes/java/sql/DriverManager.java
changeset 8797 e8507464a69d
parent 7803 56bc97d69d93
child 9239 f4bedba1a211
equal deleted inserted replaced
8796:604a43386301 8797:e8507464a69d
     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 }