提交 f5e53fe2 编写于 作者: L lancea

7026898: DriverManager to now use CopyOnWriteArrayList

Reviewed-by: alanb, briangoetz
上级 fa319f58
/* /*
* Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -26,10 +26,10 @@ ...@@ -26,10 +26,10 @@
package java.sql; package java.sql;
import java.util.Iterator; import java.util.Iterator;
import java.sql.Driver;
import java.util.ServiceLoader; import java.util.ServiceLoader;
import java.security.AccessController; import java.security.AccessController;
import java.security.PrivilegedAction; import java.security.PrivilegedAction;
import java.util.concurrent.CopyOnWriteArrayList;
/** /**
...@@ -79,6 +79,27 @@ import java.security.PrivilegedAction; ...@@ -79,6 +79,27 @@ import java.security.PrivilegedAction;
public class DriverManager { public class DriverManager {
// List of registered JDBC drivers
private final static CopyOnWriteArrayList<Driver> registeredDrivers = new CopyOnWriteArrayList<Driver>();
private static volatile int loginTimeout = 0;
private static volatile java.io.PrintWriter logWriter = null;
private static volatile java.io.PrintStream logStream = null;
// Used in println() to synchronize logWriter
private final static Object logSync = new Object();
/* Prevent the DriverManager class from being instantiated. */
private DriverManager(){}
/**
* Load the initial JDBC drivers by checking the System property
* jdbc.properties and then use the {@code ServiceLoader} mechanism
*/
static {
loadInitialDrivers();
println("JDBC DriverManager initialized");
}
/** /**
* The <code>SQLPermission</code> constant that allows the * The <code>SQLPermission</code> constant that allows the
* setting of the logging stream. * setting of the logging stream.
...@@ -235,44 +256,33 @@ public class DriverManager { ...@@ -235,44 +256,33 @@ public class DriverManager {
*/ */
public static Driver getDriver(String url) public static Driver getDriver(String url)
throws SQLException { throws SQLException {
java.util.Vector drivers = null;
println("DriverManager.getDriver(\"" + url + "\")"); println("DriverManager.getDriver(\"" + url + "\")");
if (!initialized) {
initialize();
}
synchronized (DriverManager.class){
// use the read copy of the drivers vector
drivers = readDrivers;
}
// Gets the classloader of the code that called this method, may // Gets the classloader of the code that called this method, may
// be null. // be null.
ClassLoader callerCL = DriverManager.getCallerClassLoader(); ClassLoader callerCL = DriverManager.getCallerClassLoader();
// Walk through the loaded drivers attempting to locate someone // Walk through the loaded registeredDrivers attempting to locate someone
// who understands the given URL. // who understands the given URL.
for (int i = 0; i < drivers.size(); i++) { for (Driver aDriver : registeredDrivers) {
DriverInfo di = (DriverInfo)drivers.elementAt(i);
// If the caller does not have permission to load the driver then // If the caller does not have permission to load the driver then
// skip it. // skip it.
if ( getCallerClass(callerCL, di.driverClassName ) != if(isDriverAllowed(aDriver, callerCL)) {
di.driverClass ) { try {
println(" skipping: " + di); if(aDriver.acceptsURL(url)) {
continue; // Success!
} println("getDriver returning " + aDriver.getClass().getName());
try { return (aDriver);
println(" trying " + di); }
if (di.driver.acceptsURL(url)) {
// Success! } catch(SQLException sqe) {
println("getDriver returning " + di); // Drop through and try the next driver.
return (di.driver);
} }
} catch (SQLException ex) { } else {
// Drop through and try the next driver. println(" skipping: " + aDriver.getClass().getName());
} }
} }
println("getDriver: no suitable driver"); println("getDriver: no suitable driver");
...@@ -292,23 +302,16 @@ public class DriverManager { ...@@ -292,23 +302,16 @@ public class DriverManager {
*/ */
public static synchronized void registerDriver(java.sql.Driver driver) public static synchronized void registerDriver(java.sql.Driver driver)
throws SQLException { throws SQLException {
if (!initialized) {
initialize();
}
DriverInfo di = new DriverInfo();
di.driver = driver;
di.driverClass = driver.getClass();
di.driverClassName = di.driverClass.getName();
// Not Required -- drivers.addElement(di);
writeDrivers.addElement(di); /* Register the driver if it has not already been added to our list */
println("registerDriver: " + di); if(driver != null) {
registeredDrivers.addIfAbsent(driver);
} else {
// This is for compatibility with the original DriverManager
throw new NullPointerException();
}
/* update the read copy of drivers vector */ println("registerDriver: " + driver);
readDrivers = (java.util.Vector) writeDrivers.clone();
} }
...@@ -321,37 +324,26 @@ public class DriverManager { ...@@ -321,37 +324,26 @@ public class DriverManager {
*/ */
public static synchronized void deregisterDriver(Driver driver) public static synchronized void deregisterDriver(Driver driver)
throws SQLException { throws SQLException {
if (driver == null) {
return;
}
// Gets the classloader of the code that called this method, // Gets the classloader of the code that called this method,
// may be null. // may be null.
ClassLoader callerCL = DriverManager.getCallerClassLoader(); ClassLoader callerCL = DriverManager.getCallerClassLoader();
println("DriverManager.deregisterDriver: " + driver); println("DriverManager.deregisterDriver: " + driver);
// Walk through the loaded drivers. if(registeredDrivers.contains(driver)) {
int i; if (isDriverAllowed(driver, callerCL)) {
DriverInfo di = null; registeredDrivers.remove(driver);
for (i = 0; i < writeDrivers.size(); i++) { } else {
di = (DriverInfo)writeDrivers.elementAt(i); // If the caller does not have permission to load the driver then
if (di.driver == driver) { // throw a SecurityException.
break; throw new SecurityException();
} }
} } else {
// If we can't find the driver just return.
if (i >= writeDrivers.size()) {
println(" couldn't find driver to unload"); println(" couldn't find driver to unload");
return;
} }
// If the caller does not have permission to load the driver then
// throw a security exception.
if (getCallerClass(callerCL, di.driverClassName ) != di.driverClass ) {
throw new SecurityException();
}
// Remove the driver. Other entries in drivers get shuffled down.
writeDrivers.removeElementAt(i);
/* update the read copy of drivers vector */
readDrivers = (java.util.Vector) writeDrivers.clone();
} }
/** /**
...@@ -364,34 +356,22 @@ public class DriverManager { ...@@ -364,34 +356,22 @@ public class DriverManager {
* @return the list of JDBC Drivers loaded by the caller's class loader * @return the list of JDBC Drivers loaded by the caller's class loader
*/ */
public static java.util.Enumeration<Driver> getDrivers() { public static java.util.Enumeration<Driver> getDrivers() {
java.util.Vector<Driver> result = new java.util.Vector<>(); java.util.Vector<Driver> result = new java.util.Vector<Driver>();
java.util.Vector drivers = null;
if (!initialized) {
initialize();
}
synchronized (DriverManager.class){
// use the readcopy of drivers
drivers = readDrivers;
}
// Gets the classloader of the code that called this method, may // Gets the classloader of the code that called this method, may
// be null. // be null.
ClassLoader callerCL = DriverManager.getCallerClassLoader(); ClassLoader callerCL = DriverManager.getCallerClassLoader();
// Walk through the loaded drivers. // Walk through the loaded registeredDrivers.
for (int i = 0; i < drivers.size(); i++) { for(Driver aDriver : registeredDrivers) {
DriverInfo di = (DriverInfo)drivers.elementAt(i);
// If the caller does not have permission to load the driver then // If the caller does not have permission to load the driver then
// skip it. // skip it.
if ( getCallerClass(callerCL, di.driverClassName ) != di.driverClass ) { if(isDriverAllowed(aDriver, callerCL)) {
println(" skipping: " + di); result.addElement(aDriver);
continue; } else {
println(" skipping: " + aDriver.getClass().getName());
} }
result.addElement(di.driver);
} }
return (result.elements()); return (result.elements());
} }
...@@ -481,21 +461,22 @@ public class DriverManager { ...@@ -481,21 +461,22 @@ public class DriverManager {
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Returns the class object that would be created if the code calling the // Indicates whether the class object that would be created if the code calling
// driver manager had loaded the driver class, or null if the class // DriverManager is accessible.
// is inaccessible. private static boolean isDriverAllowed(Driver driver, ClassLoader classLoader) {
private static Class getCallerClass(ClassLoader callerClassLoader, boolean result = false;
String driverClassName) { if(driver != null) {
Class callerC = null; Class<?> aClass = null;
try {
aClass = Class.forName(driver.getClass().getName(), true, classLoader);
} catch (Exception ex) {
result = false;
}
try { result = ( aClass == driver.getClass() ) ? true : false;
callerC = Class.forName(driverClassName, true, callerClassLoader);
}
catch (Exception ex) {
callerC = null; // being very careful
} }
return callerC; return result;
} }
private static void loadInitialDrivers() { private static void loadInitialDrivers() {
...@@ -544,26 +525,17 @@ public class DriverManager { ...@@ -544,26 +525,17 @@ public class DriverManager {
}); });
println("DriverManager.initialize: jdbc.drivers = " + drivers); println("DriverManager.initialize: jdbc.drivers = " + drivers);
if (drivers == null) {
if (drivers == null || drivers.equals("")) {
return; return;
} }
while (drivers.length() != 0) { String[] driversList = drivers.split(":");
int x = drivers.indexOf(':'); println("number of Drivers:" + driversList.length);
String driver; for (String aDriver : driversList) {
if (x < 0) {
driver = drivers;
drivers = "";
} else {
driver = drivers.substring(0, x);
drivers = drivers.substring(x+1);
}
if (driver.length() == 0) {
continue;
}
try { try {
println("DriverManager.Initialize: loading " + driver); println("DriverManager.Initialize: loading " + aDriver);
Class.forName(driver, true, Class.forName(aDriver, true,
ClassLoader.getSystemClassLoader()); ClassLoader.getSystemClassLoader());
} catch (Exception ex) { } catch (Exception ex) {
println("DriverManager.Initialize: load failed: " + ex); println("DriverManager.Initialize: load failed: " + ex);
} }
...@@ -574,7 +546,6 @@ public class DriverManager { ...@@ -574,7 +546,6 @@ public class DriverManager {
// Worker method called by the public getConnection() methods. // Worker method called by the public getConnection() methods.
private static Connection getConnection( private static Connection getConnection(
String url, java.util.Properties info, ClassLoader callerCL) throws SQLException { String url, java.util.Properties info, ClassLoader callerCL) throws SQLException {
java.util.Vector drivers = null;
/* /*
* When callerCl is null, we should check the application's * When callerCl is null, we should check the application's
* (which is invoking this class indirectly) * (which is invoking this class indirectly)
...@@ -594,40 +565,32 @@ public class DriverManager { ...@@ -594,40 +565,32 @@ public class DriverManager {
println("DriverManager.getConnection(\"" + url + "\")"); println("DriverManager.getConnection(\"" + url + "\")");
if (!initialized) { // Walk through the loaded registeredDrivers attempting to make a connection.
initialize();
}
synchronized (DriverManager.class){
// use the readcopy of drivers
drivers = readDrivers;
}
// Walk through the loaded drivers attempting to make a connection.
// Remember the first exception that gets raised so we can reraise it. // Remember the first exception that gets raised so we can reraise it.
SQLException reason = null; SQLException reason = null;
for (int i = 0; i < drivers.size(); i++) {
DriverInfo di = (DriverInfo)drivers.elementAt(i);
for(Driver aDriver : registeredDrivers) {
// If the caller does not have permission to load the driver then // If the caller does not have permission to load the driver then
// skip it. // skip it.
if ( getCallerClass(callerCL, di.driverClassName ) != di.driverClass ) { if(isDriverAllowed(aDriver, callerCL)) {
println(" skipping: " + di); try {
continue; println(" trying " + aDriver.getClass().getName());
} Connection con = aDriver.connect(url, info);
try { if (con != null) {
println(" trying " + di); // Success!
Connection result = di.driver.connect(url, info); println("getConnection returning " + aDriver.getClass().getName());
if (result != null) { return (con);
// Success! }
println("getConnection returning " + di); } catch (SQLException ex) {
return (result); if (reason == null) {
} reason = ex;
} catch (SQLException ex) { }
if (reason == null) {
reason = ex;
} }
} else {
println(" skipping: " + aDriver.getClass().getName());
} }
} }
// if we got here nobody could connect. // if we got here nobody could connect.
...@@ -640,45 +603,7 @@ public class DriverManager { ...@@ -640,45 +603,7 @@ public class DriverManager {
throw new SQLException("No suitable driver found for "+ url, "08001"); throw new SQLException("No suitable driver found for "+ url, "08001");
} }
// Class initialization.
static void initialize() {
if (initialized) {
return;
}
initialized = true;
loadInitialDrivers();
println("JDBC DriverManager initialized");
}
/* Prevent the DriverManager class from being instantiated. */
private DriverManager(){}
/* write copy of the drivers vector */
private static java.util.Vector writeDrivers = new java.util.Vector();
/* write copy of the drivers vector */
private static java.util.Vector readDrivers = new java.util.Vector();
private static int loginTimeout = 0;
private static java.io.PrintWriter logWriter = null;
private static java.io.PrintStream logStream = null;
private static boolean initialized = false;
private static Object logSync = new Object();
/* Returns the caller's class loader, or null if none */ /* Returns the caller's class loader, or null if none */
private static native ClassLoader getCallerClassLoader(); private static native ClassLoader getCallerClassLoader();
} }
// DriverInfo is a package-private support class.
class DriverInfo {
Driver driver;
Class driverClass;
String driverClassName;
public String toString() {
return ("driver[className=" + driverClassName + "," + driver + "]");
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册