1 /**Managing a collection of JDBC driven basic services 2 Note: The implementation of the new DataSource interface in the new JDBC 2.0 API provides another way to link data sources. 3 The object of using DataSource is the preferred solution. 4 */ 5 public class DriverManager { 6 7 // Register the JDBC driver collection. 8 private final static CopyOnWriteArrayList<DriverInfo> registeredDrivers = new CopyOnWriteArrayList<>(); 9 10 /** 11 Initialize JDBC driver by checking jdcb.properties loading 12 */ 13 static { 14 loadInitialDrivers(); 15 println("JDBC DriverManager initialized"); 16 } 17 18 /* 19 *The method of providing database connection for external use. 20 *The Reflection.getCallerClass () method is highlighted, which returns the class of the caller. 21 */ 22 @CallerSensitive 23 public static Connection getConnection(String url) 24 throws SQLException { 25 26 java.util.Properties info = new java.util.Properties(); 27 return (getConnection(url, info, Reflection.getCallerClass())); 28 } 29 30 // Create database links based on urls, corresponding attribute information, and finding the appropriate registered driver in registered Drivers 31 private static Connection getConnection( 32 String url, java.util.Properties info, Class<?> caller) throws SQLException { 33 /* 34 * When callerCl is null, we should check the application's 35 * (which is invoking this class indirectly) 36 * classloader, so that the JDBC driver class outside rt.jar 37 * can be loaded from here. 38 */ 39 ClassLoader callerCL = caller != null ? caller.getClassLoader() : null; 40 synchronized(DriverManager.class) { 41 // synchronize loading of the correct classloader. 42 if (callerCL == null) { 43 callerCL = Thread.currentThread().getContextClassLoader(); 44 } 45 } 46 47 if(url == null) { 48 throw new SQLException("The url cannot be null", "08001"); 49 } 50 51 println("DriverManager.getConnection(\"" + url + "\")"); 52 53 // Walk through the loaded registeredDrivers attempting to make a connection. 54 // Remember the first exception that gets raised so we can reraise it. 55 SQLException reason = null; 56 57 for(DriverInfo aDriver : registeredDrivers) { 58 // If the caller does not have permission to load the driver then 59 // skip it. 60 //There may be multiple database drivers in an application that need to determine whether the caller of the database connection (the object that calls the getConnection () method) matches the driver 61 if(isDriverAllowed(aDriver.driver, callerCL)) { 62 try { 63 println(" trying " + aDriver.driver.getClass().getName()); 64 Connection con = aDriver.driver.connect(url, info); 65 if (con != null) { 66 // Success! 67 println("getConnection returning " + aDriver.driver.getClass().getName()); 68 return (con); 69 } 70 } catch (SQLException ex) { 71 if (reason == null) { 72 reason = ex; 73 } 74 } 75 76 } else { 77 println(" skipping: " + aDriver.getClass().getName()); 78 } 79 80 } 81 82 // if we got here nobody could connect. 83 if (reason != null) { 84 println("getConnection failed: " + reason); 85 throw reason; 86 } 87 88 println("getConnection: no suitable driver found for "+ url); 89 throw new SQLException("No suitable driver found for "+ url, "08001"); 90 } 91 } 92 93 //There may be multiple database drivers in an application that need to determine whether the caller of the database connection (the object that calls the getConnection () method) matches the driver 94 private static boolean isDriverAllowed(Driver driver, ClassLoader classLoader) { 95 boolean result = false; 96 if(driver != null) { 97 Class<?> aClass = null; 98 try { 99 aClass = Class.forName(driver.getClass().getName(), true, classLoader); 100 } catch (Exception ex) { 101 result = false; 102 } 103 104 result = ( aClass == driver.getClass() ) ? true : false; 105 } 106 107 return result; 108 } 109 110 //Get the driver from registeredDrivers based on the URL, and match in registeredDrivers based on the caller class returned by Reflection. getCallerClass () 111 @CallerSensitive 112 public static Driver getDriver(String url) 113 throws SQLException { 114 115 println("DriverManager.getDriver(\"" + url + "\")"); 116 117 Class<?> callerClass = Reflection.getCallerClass(); 118 119 // Walk through the loaded registeredDrivers attempting to locate someone 120 // who understands the given URL. 121 for (DriverInfo aDriver : registeredDrivers) { 122 // If the caller does not have permission to load the driver then 123 // skip it. 124 if(isDriverAllowed(aDriver.driver, callerClass)) { 125 try { 126 if(aDriver.driver.acceptsURL(url)) { 127 // Success! 128 println("getDriver returning " + aDriver.driver.getClass().getName()); 129 return (aDriver.driver); 130 } 131 132 } catch(SQLException sqe) { 133 // Drop through and try the next driver. 134 } 135 } else { 136 println(" skipping: " + aDriver.driver.getClass().getName()); 137 } 138 139 } 140 141 println("getDriver: no suitable driver"); 142 throw new SQLException("No suitable driver", "08001"); 143 } 144 145 146 /* 147 *Registration data-driven, using synchronous mode, and finally saved in CopyOnWriteArrayList collection.148 */ 149 public static synchronized void registerDriver(java.sql.Driver driver, 150 DriverAction da) 151 throws SQLException { 152 153 /* Register the driver if it has not already been added to our list */ 154 if(driver != null) { 155 registeredDrivers.addIfAbsent(new DriverInfo(driver, da)); 156 } else { 157 // This is for compatibility with the original DriverManager 158 throw new NullPointerException(); 159 } 160 161 println("registerDriver: " + driver); 162 163 }