diff --git a/jdk/src/share/classes/java/sql/Driver.java b/jdk/src/share/classes/java/sql/Driver.java index 1682b75c910..27ad3e0407d 100644 --- a/jdk/src/share/classes/java/sql/Driver.java +++ b/jdk/src/share/classes/java/sql/Driver.java @@ -44,13 +44,16 @@ import java.util.logging.Logger; * *
When a Driver class is loaded, it should create an instance of * itself and register it with the DriverManager. This means that a - * user can load and register a driver by calling - *
- * Class.forName("foo.bah.Driver")
- *
- *
+ * user can load and register a driver by calling:
+ * + * {@code Class.forName("foo.bah.Driver")} + *
+ * A JDBC driver may create a {@linkplain DriverAction} implementation in order + * to receive notifications when {@linkplain DriverManager#deregisterDriver} has + * been called. * @see DriverManager * @see Connection + * @see DriverAction */ public interface Driver { diff --git a/jdk/src/share/classes/java/sql/DriverAction.java b/jdk/src/share/classes/java/sql/DriverAction.java new file mode 100644 index 00000000000..167168c9b85 --- /dev/null +++ b/jdk/src/share/classes/java/sql/DriverAction.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.sql; + +/** + * An interface that must be implemented when a {@linkplain Driver} wants to be + * notified by {@code DriverManager}. + *
+ * A {@code DriverAction} implementation is not intended to be used
+ * directly by applications. A JDBC Driver may choose
+ * to create its {@code DriverAction} implementation in a private class
+ * to avoid it being called directly.
+ *
+ * The {@code deregister} method is intended only to be used by JDBC Drivers
+ * and not by applications. JDBC drivers are recommended to not implement
+ * {@code DriverAction} in a public class. If there are active
+ * connections to the database at the time that the {@code deregister}
+ * method is called, it is implementation specific as to whether the
+ * connections are closed or allowed to continue. Once this method is
+ * called, it is implementation specific as to whether the driver may
+ * limit the ability to create new connections to the database, invoke
+ * other {@code Driver} methods or throw a {@code SQLException}.
+ * Consult your JDBC driver's documentation for additional information
+ * on its behavior.
+ * @see DriverManager#registerDriver(java.sql.Driver, java.sql.DriverAction)
+ * @see DriverManager#deregisterDriver(Driver)
+ * @since 1.8
+ */
+ void deregister();
+
+}
diff --git a/jdk/src/share/classes/java/sql/DriverManager.java b/jdk/src/share/classes/java/sql/DriverManager.java
index b0d8decf40b..fbe16363529 100644
--- a/jdk/src/share/classes/java/sql/DriverManager.java
+++ b/jdk/src/share/classes/java/sql/DriverManager.java
@@ -110,6 +110,14 @@ public class DriverManager {
final static SQLPermission SET_LOG_PERMISSION =
new SQLPermission("setLog");
+ /**
+ * The {@code SQLPermission} constant that allows the
+ * un-register a registered JDBC driver.
+ * @since 1.8
+ */
+ final static SQLPermission DEREGISTER_DRIVER_PERMISSION =
+ new SQLPermission("deregisterDriver");
+
//--------------------------JDBC 2.0-----------------------------
/**
@@ -309,21 +317,42 @@ public class DriverManager {
/**
- * Registers the given driver with the
+ * If a {@code null} value is specified for the driver to be removed, then no
+ * action is taken.
+ *
+ * If a security manager exists and its {@code checkPermission} denies
+ * permission, then a {@code SecurityException} will be thrown.
+ *
+ * If the specified driver is not found in the list of registered drivers,
+ * then no action is taken. If the driver was found, it will be removed
+ * from the list of registered drivers.
+ *
+ * If a {@code DriverAction} instance was specified when the JDBC driver was
+ * registered, its deregister method will be called
+ * prior to the driver being removed from the list of registered drivers.
*
- * @param driver the JDBC Driver to drop
+ * @param driver the JDBC Driver to remove
* @exception SQLException if a database access error occurs
+ * @throws SecurityException if a security manager exists and its
+ * {@code checkPermission} method denies permission to deregister a driver.
+ *
+ * @see SecurityManager#checkPermission
*/
@CallerSensitive
public static synchronized void deregisterDriver(Driver driver)
@@ -347,11 +394,22 @@ public class DriverManager {
return;
}
+ SecurityManager sec = System.getSecurityManager();
+ if (sec != null) {
+ sec.checkPermission(DEREGISTER_DRIVER_PERMISSION);
+ }
+
println("DriverManager.deregisterDriver: " + driver);
- DriverInfo aDriver = new DriverInfo(driver);
+ DriverInfo aDriver = new DriverInfo(driver, null);
if(registeredDrivers.contains(aDriver)) {
if (isDriverAllowed(driver, Reflection.getCallerClass())) {
+ DriverInfo di = registeredDrivers.get(registeredDrivers.indexOf(aDriver));
+ // If a DriverAction was specified, Call it to notify the
+ // driver that it has been deregistered
+ if(di.action() != null) {
+ di.action().deregister();
+ }
registeredDrivers.remove(aDriver);
} else {
// If the caller does not have permission to load the driver then
@@ -639,8 +697,10 @@ public class DriverManager {
class DriverInfo {
final Driver driver;
- DriverInfo(Driver driver) {
+ DriverAction da;
+ DriverInfo(Driver driver, DriverAction action) {
this.driver = driver;
+ da = action;
}
@Override
@@ -658,4 +718,8 @@ class DriverInfo {
public String toString() {
return ("driver[className=" + driver + "]");
}
+
+ DriverAction action() {
+ return da;
+ }
}
diff --git a/jdk/src/share/classes/java/sql/SQLPermission.java b/jdk/src/share/classes/java/sql/SQLPermission.java
index e2207db3262..3aa5a42860b 100644
--- a/jdk/src/share/classes/java/sql/SQLPermission.java
+++ b/jdk/src/share/classes/java/sql/SQLPermission.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -30,8 +30,9 @@ import java.security.*;
/**
* The permission for which the
- * The person running an applet decides what permissions to allow
- * and will run the DriverManager
.
+ * Registers the given driver with the {@code DriverManager}.
* A newly-loaded driver class should call
- * the method registerDriver
to make itself
- * known to the DriverManager
.
+ * the method {@code registerDriver} to make itself
+ * known to the {@code DriverManager}. If the driver had previously been
+ * registered, no action is taken.
*
* @param driver the new JDBC Driver that is to be registered with the
- * DriverManager
+ * {@code DriverManager}
* @exception SQLException if a database access error occurs
*/
public static synchronized void registerDriver(java.sql.Driver driver)
throws SQLException {
+ registerDriver(driver, null);
+ }
+
+ /**
+ * Registers the given driver with the {@code DriverManager}.
+ * A newly-loaded driver class should call
+ * the method {@code registerDriver} to make itself
+ * known to the {@code DriverManager}. If the driver had previously been
+ * registered, no action is taken.
+ *
+ * @param driver the new JDBC Driver that is to be registered with the
+ * {@code DriverManager}
+ * @param da the {@code DriverAction} implementation to be used when
+ * {@code DriverManager#deregisterDriver} is called
+ * @exception SQLException if a database access error occurs
+ */
+ public static synchronized void registerDriver(java.sql.Driver driver,
+ DriverAction da)
+ throws SQLException {
+
/* Register the driver if it has not already been added to our list */
if(driver != null) {
- registeredDrivers.addIfAbsent(new DriverInfo(driver));
+ registeredDrivers.addIfAbsent(new DriverInfo(driver, da));
} else {
// This is for compatibility with the original DriverManager
throw new NullPointerException();
@@ -334,11 +363,29 @@ public class DriverManager {
}
/**
- * Drops a driver from the DriverManager
's list.
- * Applets can only deregister drivers from their own classloaders.
+ * Removes the specified driver from the {@code DriverManager}'s list of
+ * registered drivers.
+ * SecurityManager
will check
- * when code that is running in an applet, or an application with a
+ * when code that is running an application with a
* SecurityManager
enabled, calls the
+ * {@code DriverManager.deregisterDriver} method,
* DriverManager.setLogWriter
method,
* DriverManager.setLogStream
(deprecated) method,
* {@code SyncFactory.setJNDIContext} method,
@@ -95,14 +96,16 @@ import java.security.*;
* Connection
or
* objects created from the Connection
* will wait for the database to reply to any one request.
+ *
+ *
*
*
*deregisterDriver
+ * Allows the invocation of the {@code DriverManager}
+ * method {@code deregisterDriver}
+ * Permits an application to remove a JDBC driver from the list of
+ * registered Drivers and release its resources.
+ * Policy Tool
to create an
- * SQLPermission
in a policy file. A programmer does
- * not use a constructor directly to create an instance of SQLPermission
- * but rather uses a tool.
* @since 1.3
* @see java.security.BasicPermission
* @see java.security.Permission