/** Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.*********************/package java.sql;import java.util.Iterator;import java.util.ServiceLoader;import java.security.AccessController;import java.security.PrivilegedAction;import java.util.concurrent.CopyOnWriteArrayList;import sun.reflect.CallerSensitive;import sun.reflect.Reflection;/*** <P>The basic service for managing a set of JDBC drivers.<br>* <B>NOTE:</B> The {@link javax.sql.DataSource} interface, new in the* JDBC 2.0 API, provides another way to connect to a data source.* The use of a <code>DataSource</code> object is the preferred means of* connecting to a data source.** <P>As part of its initialization, the <code>DriverManager</code> 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:* <pre>* <CODE>jdbc.drivers=foo.bah.Driver:wombat.sql.Driver:bad.taste.ourDriver</CODE>* </pre>*<P> The <code>DriverManager</code> methods <code>getConnection</code> and* <code>getDrivers</code> have been enhanced to support the Java Standard Edition* <a href="../../../technotes/guides/jar/jar.html#Service%20Provider">Service Provider</a> mechanism. JDBC 4.0 Drivers must* include the file <code>META-INF/services/java.sql.Driver</code>. This file contains the name of the JDBC drivers* implementation of <code>java.sql.Driver</code>. For example, to load the <code>my.sql.Driver</code> class,* the <code>META-INF/services/java.sql.Driver</code> file would contain the entry:* <pre>* <code>my.sql.Driver</code>* </pre>** <P>Applications no longer need to explicitly load JDBC drivers using <code>Class.forName()</code>. Existing programs* which currently load JDBC drivers using <code>Class.forName()</code> will continue to work without* modification.** <P>When the method <code>getConnection</code> is called,* the <code>DriverManager</code> 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.** <P>* 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 <code>permission* java.sql.SQLPermission "setLog"</code>.* @see Driver* @see Connection*/public class DriverManager {// List of registered JDBC driversprivate final static CopyOnWriteArrayList<DriverInfo> registeredDrivers = new CopyOnWriteArrayList<>();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 logWriterprivate 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* setting of the logging stream.* @since 1.3*/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-----------------------------/*** Retrieves the log writer.** The <code>getLogWriter</code> and <code>setLogWriter</code>* methods should be used instead* of the <code>get/setlogStream</code> methods, which are deprecated.* @return a <code>java.io.PrintWriter</code> object* @see #setLogWriter* @since 1.2*/public static java.io.PrintWriter getLogWriter() {return logWriter;}/*** Sets the logging/tracing <code>PrintWriter</code> object* that is used by the <code>DriverManager</code> and all drivers.* <P>* There is a minor versioning problem created by the introduction* of the method <code>setLogWriter</code>. The* method <code>setLogWriter</code> cannot create a <code>PrintStream</code> object* that will be returned by <code>getLogStream</code>---the Java platform does* not provide a backward conversion. As a result, a new application* that uses <code>setLogWriter</code> and also uses a JDBC 1.0 driver that uses* <code>getLogStream</code> will likely not see debugging information written* by that driver.*<P>* Starting with the Java 2 SDK, Standard Edition, version 1.3 release, this method checks* to see that there is an <code>SQLPermission</code> object before setting* the logging stream. If a <code>SecurityManager</code> exists and its* <code>checkPermission</code> method denies setting the log writer, this* method throws a <code>java.lang.SecurityException</code>.** @param out the new logging/tracing <code>PrintStream</code> object;* <code>null</code> to disable logging and tracing* @throws SecurityException* if a security manager exists and its* <code>checkPermission</code> 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 <code>DriverManager</code> attempts to select an appropriate driver from* the set of registered JDBC drivers.*<p>* <B>Note:</B> If a property is specified as part of the {@code url} and* is also specified in the {@code Properties} object, it is* implementation-defined as to which value will take precedence.* For maximum portability, an application should only specify a* property once.** @param url a database url of the form* <code> jdbc:<em>subprotocol</em>:<em>subname</em></code>* @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 or the url is* {@code null}* @throws SQLTimeoutException when the driver has determined that the* timeout value specified by the {@code setLoginTimeout} method* has been exceeded and has at least tried to cancel the* current database connection attempt*/@CallerSensitivepublic static Connection getConnection(String url,java.util.Properties info) throws SQLException {return (getConnection(url, info, Reflection.getCallerClass()));}/*** Attempts to establish a connection to the given database URL.* The <code>DriverManager</code> attempts to select an appropriate driver from* the set of registered JDBC drivers.*<p>* <B>Note:</B> If the {@code user} or {@code password} property are* also specified as part of the {@code url}, it is* implementation-defined as to which value will take precedence.* For maximum portability, an application should only specify a* property once.** @param url a database url of the form* <code>jdbc:<em>subprotocol</em>:<em>subname</em></code>* @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 or the url is* {@code null}* @throws SQLTimeoutException when the driver has determined that the* timeout value specified by the {@code setLoginTimeout} method* has been exceeded and has at least tried to cancel the* current database connection attempt*/@CallerSensitivepublic static Connection getConnection(String url,String user, String password) throws SQLException {java.util.Properties info = new java.util.Properties();if (user != null) {info.put("user", user);}if (password != null) {info.put("password", password);}return (getConnection(url, info, Reflection.getCallerClass()));}/*** Attempts to establish a connection to the given database URL.* The <code>DriverManager</code> attempts to select an appropriate driver from* the set of registered JDBC drivers.** @param url a database url of the form* <code> jdbc:<em>subprotocol</em>:<em>subname</em></code>* @return a connection to the URL* @exception SQLException if a database access error occurs or the url is* {@code null}* @throws SQLTimeoutException when the driver has determined that the* timeout value specified by the {@code setLoginTimeout} method* has been exceeded and has at least tried to cancel the* current database connection attempt*/@CallerSensitivepublic static Connection getConnection(String url)throws SQLException {java.util.Properties info = new java.util.Properties();return (getConnection(url, info, Reflection.getCallerClass()));}/*** Attempts to locate a driver that understands the given URL.* The <code>DriverManager</code> attempts to select an appropriate driver from* the set of registered JDBC drivers.** @param url a database URL of the form* <code>jdbc:<em>subprotocol</em>:<em>subname</em></code>* @return a <code>Driver</code> object representing a driver* that can connect to the given URL* @exception SQLException if a database access error occurs*/@CallerSensitivepublic static Driver getDriver(String url)throws SQLException {println("DriverManager.getDriver(\"" + url + "\")");Class<?> callerClass = Reflection.getCallerClass();// Walk through the loaded registeredDrivers attempting to locate someone// who understands the given URL.for (DriverInfo aDriver : registeredDrivers) {// If the caller does not have permission to load the driver then// skip it.if(isDriverAllowed(aDriver.driver, callerClass)) {try {if(aDriver.driver.acceptsURL(url)) {// Success!println("getDriver returning " + aDriver.driver.getClass().getName());return (aDriver.driver);}} catch(SQLException sqe) {// Drop through and try the next driver.}} else {println(" skipping: " + aDriver.driver.getClass().getName());}}println("getDriver: no suitable driver");throw new SQLException("No suitable driver", "08001");}/*** 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 is currently* registered, no action is taken.** @param driver the new JDBC Driver that is to be registered with the* {@code DriverManager}* @exception SQLException if a database access error occurs* @exception NullPointerException if {@code driver} is null*/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 is currently* 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* @exception NullPointerException if {@code driver} is null* @since 1.8*/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, da));} else {// This is for compatibility with the original DriverManagerthrow new NullPointerException();}println("registerDriver: " + driver);}/*** Removes the specified driver from the {@code DriverManager}'s list of* registered drivers.* <p>* If a {@code null} value is specified for the driver to be removed, then no* action is taken.* <p>* If a security manager exists and its {@code checkPermission} denies* permission, then a {@code SecurityException} will be thrown.* <p>* 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.* <p>* 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 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*/@CallerSensitivepublic static synchronized void deregisterDriver(Driver driver)throws SQLException {if (driver == null) {return;}SecurityManager sec = System.getSecurityManager();if (sec != null) {sec.checkPermission(DEREGISTER_DRIVER_PERMISSION);}println("DriverManager.deregisterDriver: " + 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 deregisteredif(di.action() != null) {di.action().deregister();}registeredDrivers.remove(aDriver);} else {// If the caller does not have permission to load the driver then// throw a SecurityException.throw new SecurityException();}} else {println(" couldn't find driver to unload");}}/*** Retrieves an Enumeration with all of the currently loaded JDBC drivers* to which the current caller has access.** <P><B>Note:</B> The classname of a driver can be found using* <CODE>d.getClass().getName()</CODE>** @return the list of JDBC Drivers loaded by the caller's class loader*/@CallerSensitivepublic static java.util.Enumeration<Driver> getDrivers() {java.util.Vector<Driver> result = new java.util.Vector<>();Class<?> callerClass = Reflection.getCallerClass();// Walk through the loaded registeredDrivers.for(DriverInfo aDriver : registeredDrivers) {// If the caller does not have permission to load the driver then// skip it.if(isDriverAllowed(aDriver.driver, callerClass)) {result.addElement(aDriver.driver);} else {println(" skipping: " + aDriver.getClass().getName());}}return (result.elements());}/*** Sets the maximum time in seconds that a driver will wait* while attempting to connect to a database once the driver has* been identified.** @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 <code>DriverManager</code>* and all drivers.*<P>* In the Java 2 SDK, Standard Edition, version 1.3 release, this method checks* to see that there is an <code>SQLPermission</code> object before setting* the logging stream. If a <code>SecurityManager</code> exists and its* <code>checkPermission</code> method denies setting the log writer, this* method throws a <code>java.lang.SecurityException</code>.** @param out the new logging/tracing PrintStream; to disable, set to <code>null</code>* @deprecated Use {@code setLogWriter}* @throws SecurityException if a security manager exists and its* <code>checkPermission</code> method denies setting the log stream** @see SecurityManager#checkPermission* @see #getLogStream*/@Deprecatedpublic 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);elselogWriter = null;}/*** Retrieves the logging/tracing PrintStream that is used by the <code>DriverManager</code>* and all drivers.** @return the logging/tracing PrintStream; if disabled, is <code>null</code>* @deprecated Use {@code getLogWriter}* @see #setLogStream*/@Deprecatedpublic 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 ourselveslogWriter.flush();}}}//------------------------------------------------------------------------// Indicates whether the class object that would be created if the code calling// DriverManager is accessible.private static boolean isDriverAllowed(Driver driver, Class<?> caller) {ClassLoader callerCL = caller != null ? caller.getClassLoader() : null;return isDriverAllowed(driver, callerCL);}private static boolean isDriverAllowed(Driver driver, ClassLoader classLoader) {boolean result = false;if(driver != null) {Class<?> aClass = null;try {aClass = Class.forName(driver.getClass().getName(), true, classLoader);} catch (Exception ex) {result = false;}result = ( aClass == driver.getClass() ) ? true : false;}return result;}private static void loadInitialDrivers() {String drivers;try {drivers = AccessController.doPrivileged(new PrivilegedAction<String>() {public String 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<Void>() {public Void run() {ServiceLoader<Driver> loadedDrivers = ServiceLoader.load(Driver.class);Iterator<Driver> 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()) {driversIterator.next();}} catch(Throwable t) {// Do nothing}return null;}});println("DriverManager.initialize: jdbc.drivers = " + drivers);if (drivers == null || drivers.equals("")) {return;}String[] driversList = drivers.split(":");println("number of Drivers:" + driversList.length);for (String aDriver : driversList) {try {println("DriverManager.Initialize: loading " + aDriver);Class.forName(aDriver, 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, Class<?> caller) throws SQLException {/** 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.*/ClassLoader callerCL = caller != null ? caller.getClassLoader() : null;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 + "\")");// Walk through the loaded registeredDrivers attempting to make a connection.// Remember the first exception that gets raised so we can reraise it.SQLException reason = null;for(DriverInfo aDriver : registeredDrivers) {// If the caller does not have permission to load the driver then// skip it.if(isDriverAllowed(aDriver.driver, callerCL)) {try {println(" trying " + aDriver.driver.getClass().getName());Connection con = aDriver.driver.connect(url, info);if (con != null) {// Success!println("getConnection returning " + aDriver.driver.getClass().getName());return (con);}} catch (SQLException ex) {if (reason == null) {reason = ex;}}} else {println(" skipping: " + aDriver.getClass().getName());}}// 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");}}/** Wrapper class for registered Drivers in order to not expose Driver.equals()* to avoid the capture of the Driver it being compared to as it might not* normally have access.*/class DriverInfo {final Driver driver;DriverAction da;DriverInfo(Driver driver, DriverAction action) {this.driver = driver;da = action;}@Overridepublic boolean equals(Object other) {return (other instanceof DriverInfo)&& this.driver == ((DriverInfo) other).driver;}@Overridepublic int hashCode() {return driver.hashCode();}@Overridepublic String toString() {return ("driver[className=" + driver + "]");}DriverAction action() {return da;}}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。