diff --git a/openjdk/allsources.lst b/openjdk/allsources.lst index b895e545..4e25f480 100644 --- a/openjdk/allsources.lst +++ b/openjdk/allsources.lst @@ -1070,6 +1070,7 @@ java/net/SocketInputStream.java java/net/SocketOutputStream.java java/nio/Bits.java java/security/AccessController.java +java/sql/DriverManager.java java/text/Bidi.java java/util/ResourceBundle.java java/util/concurrent/locks/AbstractQueuedSynchronizer.java @@ -8056,7 +8057,6 @@ SystemProperties.java ../../openjdk6-b12/jdk/src/share/classes/java/sql/DataTruncation.java ../../openjdk6-b12/jdk/src/share/classes/java/sql/Date.java ../../openjdk6-b12/jdk/src/share/classes/java/sql/Driver.java -../../openjdk6-b12/jdk/src/share/classes/java/sql/DriverManager.java ../../openjdk6-b12/jdk/src/share/classes/java/sql/DriverPropertyInfo.java ../../openjdk6-b12/jdk/src/share/classes/java/sql/NClob.java ../../openjdk6-b12/jdk/src/share/classes/java/sql/ParameterMetaData.java diff --git a/openjdk/java/sql/DriverManager.java b/openjdk/java/sql/DriverManager.java new file mode 100644 index 00000000..31ed4d70 --- /dev/null +++ b/openjdk/java/sql/DriverManager.java @@ -0,0 +1,684 @@ +/* + * Copyright 1996-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package java.sql; + +import java.util.Iterator; +import java.sql.Driver; +import java.util.ServiceLoader; +import java.security.AccessController; +import java.security.PrivilegedAction; + + +/** + *

The basic service for managing a set of JDBC drivers.
+ * NOTE: The {@link DataSource} interface, new in the + * JDBC 2.0 API, provides another way to connect to a data source. + * The use of a DataSource object is the preferred means of + * connecting to a data source. + * + *

As part of its initialization, the DriverManager class will + * attempt to load the driver classes referenced in the "jdbc.drivers" + * system property. This allows a user to customize the JDBC Drivers + * used by their applications. For example in your + * ~/.hotjava/properties file you might specify: + *

+ * jdbc.drivers=foo.bah.Driver:wombat.sql.Driver:bad.taste.ourDriver
+ * 
+ *

The DriverManager methods getConnection and + * getDrivers have been enhanced to support the Java Standard Edition + * Service Provider mechanism. JDBC 4.0 Drivers must + * include the file META-INF/services/java.sql.Driver. This file contains the name of the JDBC drivers + * implementation of java.sql.Driver. For example, to load the my.sql.Driver class, + * the META-INF/services/java.sql.Driver file would contain the entry: + *

+ * my.sql.Driver
+ * 
+ * + *

Applications no longer need to explictly load JDBC drivers using Class.forName(). Existing programs + * which currently load JDBC drivers using Class.forName() will continue to work without + * modification. + * + *

When the method getConnection is called, + * the DriverManager will attempt to + * locate a suitable driver from amongst those loaded at + * initialization and those loaded explicitly using the same classloader + * as the current applet or application. + * + *

+ * Starting with the Java 2 SDK, Standard Edition, version 1.3, a + * logging stream can be set only if the proper + * permission has been granted. Normally this will be done with + * the tool PolicyTool, which can be used to grant permission + * java.sql.SQLPermission "setLog". + * @see Driver + * @see Connection + */ +public class DriverManager { + + + /** + * The SQLPermission constant that allows the + * setting of the logging stream. + * @since 1.3 + */ + final static SQLPermission SET_LOG_PERMISSION = + new SQLPermission("setLog"); + + //--------------------------JDBC 2.0----------------------------- + + /** + * Retrieves the log writer. + * + * The getLogWriter and setLogWriter + * methods should be used instead + * of the get/setlogStream methods, which are deprecated. + * @return a java.io.PrintWriter object + * @see #setLogWriter + * @since 1.2 + */ + public static java.io.PrintWriter getLogWriter() { + return logWriter; + } + + /** + * Sets the logging/tracing PrintWriter object + * that is used by the DriverManager and all drivers. + *

+ * There is a minor versioning problem created by the introduction + * of the method setLogWriter. The + * method setLogWriter cannot create a PrintStream object + * that will be returned by getLogStream---the Java platform does + * not provide a backward conversion. As a result, a new application + * that uses setLogWriter and also uses a JDBC 1.0 driver that uses + * getLogStream will likely not see debugging information written + * by that driver. + *

+ * Starting with the Java 2 SDK, Standard Edition, version 1.3 release, this method checks + * to see that there is an SQLPermission object before setting + * the logging stream. If a SecurityManager exists and its + * checkPermission method denies setting the log writer, this + * method throws a java.lang.SecurityException. + * + * @param out the new logging/tracing PrintStream object; + * null to disable logging and tracing + * @throws SecurityException + * if a security manager exists and its + * checkPermission method denies + * setting the log writer + * + * @see SecurityManager#checkPermission + * @see #getLogWriter + * @since 1.2 + */ + public static void setLogWriter(java.io.PrintWriter out) { + + SecurityManager sec = System.getSecurityManager(); + if (sec != null) { + sec.checkPermission(SET_LOG_PERMISSION); + } + logStream = null; + logWriter = out; + } + + + //--------------------------------------------------------------- + + /** + * Attempts to establish a connection to the given database URL. + * The DriverManager attempts to select an appropriate driver from + * the set of registered JDBC drivers. + * + * @param url a database url of the form + * jdbc:subprotocol:subname + * @param info a list of arbitrary string tag/value pairs as + * connection arguments; normally at least a "user" and + * "password" property should be included + * @return a Connection to the URL + * @exception SQLException if a database access error occurs + */ + public static Connection getConnection(String url, + java.util.Properties info) throws SQLException { + + // Gets the classloader of the code that called this method, may + // be null. + ClassLoader callerCL = DriverManager.getCallerClassLoader(); + + return (getConnection(url, info, callerCL)); + } + + /** + * Attempts to establish a connection to the given database URL. + * The DriverManager attempts to select an appropriate driver from + * the set of registered JDBC drivers. + * + * @param url a database url of the form + * jdbc:subprotocol:subname + * @param user the database user on whose behalf the connection is being + * made + * @param password the user's password + * @return a connection to the URL + * @exception SQLException if a database access error occurs + */ + public static Connection getConnection(String url, + String user, String password) throws SQLException { + java.util.Properties info = new java.util.Properties(); + + // Gets the classloader of the code that called this method, may + // be null. + ClassLoader callerCL = DriverManager.getCallerClassLoader(); + + if (user != null) { + info.put("user", user); + } + if (password != null) { + info.put("password", password); + } + + return (getConnection(url, info, callerCL)); + } + + /** + * Attempts to establish a connection to the given database URL. + * The DriverManager attempts to select an appropriate driver from + * the set of registered JDBC drivers. + * + * @param url a database url of the form + * jdbc:subprotocol:subname + * @return a connection to the URL + * @exception SQLException if a database access error occurs + */ + public static Connection getConnection(String url) + throws SQLException { + + java.util.Properties info = new java.util.Properties(); + + // Gets the classloader of the code that called this method, may + // be null. + ClassLoader callerCL = DriverManager.getCallerClassLoader(); + + return (getConnection(url, info, callerCL)); + } + + /** + * Attempts to locate a driver that understands the given URL. + * The DriverManager attempts to select an appropriate driver from + * the set of registered JDBC drivers. + * + * @param url a database URL of the form + * jdbc:subprotocol:subname + * @return a Driver object representing a driver + * that can connect to the given URL + * @exception SQLException if a database access error occurs + */ + public static Driver getDriver(String url) + throws SQLException { + java.util.Vector drivers = null; + + 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 + // be null. + ClassLoader callerCL = DriverManager.getCallerClassLoader(); + + // Walk through the loaded drivers attempting to locate someone + // who understands the given URL. + for (int i = 0; i < drivers.size(); i++) { + DriverInfo di = (DriverInfo)drivers.elementAt(i); + // If the caller does not have permission to load the driver then + // skip it. + if ( getCallerClass(callerCL, di.driverClassName ) != + di.driverClass ) { + println(" skipping: " + di); + continue; + } + try { + println(" trying " + di); + if (di.driver.acceptsURL(url)) { + // Success! + println("getDriver returning " + di); + return (di.driver); + } + } catch (SQLException ex) { + // Drop through and try the next driver. + } + } + + println("getDriver: no suitable driver"); + throw new SQLException("No suitable driver", "08001"); + } + + + /** + * Registers the given driver with the DriverManager. + * A newly-loaded driver class should call + * the method registerDriver to make itself + * known to the DriverManager. + * + * @param driver the new JDBC Driver that is to be registered with the + * DriverManager + * @exception SQLException if a database access error occurs + */ + public static synchronized void registerDriver(java.sql.Driver driver) + 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); + println("registerDriver: " + di); + + /* update the read copy of drivers vector */ + readDrivers = (java.util.Vector) writeDrivers.clone(); + + } + + /** + * Drops a driver from the DriverManager's list. + * Applets can only deregister drivers from their own classloaders. + * + * @param driver the JDBC Driver to drop + * @exception SQLException if a database access error occurs + */ + public static synchronized void deregisterDriver(Driver driver) + throws SQLException { + // Gets the classloader of the code that called this method, + // may be null. + ClassLoader callerCL = DriverManager.getCallerClassLoader(); + println("DriverManager.deregisterDriver: " + driver); + + // Walk through the loaded drivers. + int i; + DriverInfo di = null; + for (i = 0; i < writeDrivers.size(); i++) { + di = (DriverInfo)writeDrivers.elementAt(i); + if (di.driver == driver) { + break; + } + } + // If we can't find the driver just return. + if (i >= writeDrivers.size()) { + 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(); + } + + /** + * Retrieves an Enumeration with all of the currently loaded JDBC drivers + * to which the current caller has access. + * + *

Note: The classname of a driver can be found using + * d.getClass().getName() + * + * @return the list of JDBC Drivers loaded by the caller's class loader + */ + public static java.util.Enumeration getDrivers() { + java.util.Vector result = new java.util.Vector(); + 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 + // be null. + ClassLoader callerCL = DriverManager.getCallerClassLoader(); + + // Walk through the loaded drivers. + for (int i = 0; i < drivers.size(); i++) { + DriverInfo di = (DriverInfo)drivers.elementAt(i); + // If the caller does not have permission to load the driver then + // skip it. + if ( getCallerClass(callerCL, di.driverClassName ) != di.driverClass ) { + println(" skipping: " + di); + continue; + } + result.addElement(di.driver); + } + + return (result.elements()); + } + + + /** + * Sets the maximum time in seconds that a driver will wait + * while attempting to connect to a database. + * + * @param seconds the login time limit in seconds; zero means there is no limit + * @see #getLoginTimeout + */ + public static void setLoginTimeout(int seconds) { + loginTimeout = seconds; + } + + /** + * Gets the maximum time in seconds that a driver can wait + * when attempting to log in to a database. + * + * @return the driver login time limit in seconds + * @see #setLoginTimeout + */ + public static int getLoginTimeout() { + return (loginTimeout); + } + + /** + * Sets the logging/tracing PrintStream that is used + * by the DriverManager + * and all drivers. + *

+ * In the Java 2 SDK, Standard Edition, version 1.3 release, this method checks + * to see that there is an SQLPermission object before setting + * the logging stream. If a SecurityManager exists and its + * checkPermission method denies setting the log writer, this + * method throws a java.lang.SecurityException. + * + * @param out the new logging/tracing PrintStream; to disable, set to null + * @deprecated + * @throws SecurityException if a security manager exists and its + * checkPermission method denies setting the log stream + * + * @see SecurityManager#checkPermission + * @see #getLogStream + */ + public static void setLogStream(java.io.PrintStream out) { + + SecurityManager sec = System.getSecurityManager(); + if (sec != null) { + sec.checkPermission(SET_LOG_PERMISSION); + } + + logStream = out; + if ( out != null ) + logWriter = new java.io.PrintWriter(out); + else + logWriter = null; + } + + /** + * Retrieves the logging/tracing PrintStream that is used by the DriverManager + * and all drivers. + * + * @return the logging/tracing PrintStream; if disabled, is null + * @deprecated + * @see #setLogStream + */ + public static java.io.PrintStream getLogStream() { + return logStream; + } + + /** + * Prints a message to the current JDBC log stream. + * + * @param message a log or tracing message + */ + public static void println(String message) { + synchronized (logSync) { + if (logWriter != null) { + logWriter.println(message); + + // automatic flushing is never enabled, so we must do it ourselves + logWriter.flush(); + } + } + } + + //------------------------------------------------------------------------ + + // Returns the class object that would be created if the code calling the + // driver manager had loaded the driver class, or null if the class + // is inaccessible. + private static Class getCallerClass(ClassLoader callerClassLoader, + String driverClassName) { + Class callerC = null; + + try { + callerC = Class.forName(driverClassName, true, callerClassLoader); + } + catch (Exception ex) { + callerC = null; // being very careful + } + + return callerC; + } + + private static void loadInitialDrivers() { + String drivers; + try { + drivers = (String) AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + return System.getProperty("jdbc.drivers"); + } + }); + } catch (Exception ex) { + drivers = null; + } + // If the driver is packaged as a Service Provider, load it. + // Get all the drivers through the classloader + // exposed as a java.sql.Driver.class service. + // ServiceLoader.load() replaces the sun.misc.Providers() + + AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + + ServiceLoader loadedDrivers = ServiceLoader.load(Driver.class); + Iterator driversIterator = loadedDrivers.iterator(); + + /* Load these drivers, so that they can be instantiated. + * It may be the case that the driver class may not be there + * i.e. there may be a packaged driver with the service class + * as implementation of java.sql.Driver but the actual class + * may be missing. In that case a java.util.ServiceConfigurationError + * will be thrown at runtime by the VM trying to locate + * and load the service. + * + * Adding a try catch block to catch those runtime errors + * if driver not available in classpath but it's + * packaged as service and that service is there in classpath. + */ + try{ + while(driversIterator.hasNext()) { + println(" Loading done by the java.util.ServiceLoader : "+driversIterator.next()); + } + } catch(Throwable t) { + // Do nothing + } + return null; + } + }); + + println("DriverManager.initialize: jdbc.drivers = " + drivers); + if (drivers == null) { + return; + } + while (drivers.length() != 0) { + int x = drivers.indexOf(':'); + String driver; + if (x < 0) { + driver = drivers; + drivers = ""; + } else { + driver = drivers.substring(0, x); + drivers = drivers.substring(x+1); + } + if (driver.length() == 0) { + continue; + } + try { + println("DriverManager.Initialize: loading " + driver); + Class.forName(driver, true, + ClassLoader.getSystemClassLoader()); + } catch (Exception ex) { + println("DriverManager.Initialize: load failed: " + ex); + } + } + } + + + // Worker method called by the public getConnection() methods. + private static Connection getConnection( + 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 + * (which is invoking this class indirectly) + * classloader, so that the JDBC driver class outside rt.jar + * can be loaded from here. + */ + synchronized(DriverManager.class) { + // synchronize loading of the correct classloader. + if(callerCL == null) { + callerCL = Thread.currentThread().getContextClassLoader(); + } + } + + if(url == null) { + throw new SQLException("The url cannot be null", "08001"); + } + + println("DriverManager.getConnection(\"" + url + "\")"); + + if (!initialized) { + 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. + SQLException reason = null; + for (int i = 0; i < drivers.size(); i++) { + DriverInfo di = (DriverInfo)drivers.elementAt(i); + + // If the caller does not have permission to load the driver then + // skip it. + if ( getCallerClass(callerCL, di.driverClassName ) != di.driverClass ) { + println(" skipping: " + di); + continue; + } + try { + println(" trying " + di); + Connection result = di.driver.connect(url, info); + if (result != null) { + // Success! + println("getConnection returning " + di); + return (result); + } + } catch (SQLException ex) { + if (reason == null) { + reason = ex; + } + } + } + + // if we got here nobody could connect. + if (reason != null) { + println("getConnection failed: " + reason); + throw reason; + } + + println("getConnection: no suitable driver found for "+ url); + 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 */ + 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 + "]"); + } +} diff --git a/openjdk/response.txt b/openjdk/response.txt index 632f5dfa..725d3dcd 100644 --- a/openjdk/response.txt +++ b/openjdk/response.txt @@ -770,6 +770,7 @@ assembly.class -r:System.Drawing com/sun/imageio/plugins/jpeg/*.class icedtea/rt/com/sun/media/sound/*.class + java/sql/*.class sun/net/dns/*.class ServiceUI.class ../../openjdk6-b12/control/build/linux-amd64/impsrc/com/sun/activation/registries/*.class