28 import java.util.Iterator; |
28 import java.util.Iterator; |
29 import java.util.ServiceLoader; |
29 import java.util.ServiceLoader; |
30 import java.security.AccessController; |
30 import java.security.AccessController; |
31 import java.security.PrivilegedAction; |
31 import java.security.PrivilegedAction; |
32 import java.util.concurrent.CopyOnWriteArrayList; |
32 import java.util.concurrent.CopyOnWriteArrayList; |
|
33 import sun.reflect.CallerSensitive; |
33 import sun.reflect.Reflection; |
34 import sun.reflect.Reflection; |
34 |
35 |
35 |
36 |
36 /** |
37 /** |
37 * <P>The basic service for managing a set of JDBC drivers.<br> |
38 * <P>The basic service for managing a set of JDBC drivers.<br> |
190 * @throws SQLTimeoutException when the driver has determined that the |
191 * @throws SQLTimeoutException when the driver has determined that the |
191 * timeout value specified by the {@code setLoginTimeout} method |
192 * timeout value specified by the {@code setLoginTimeout} method |
192 * has been exceeded and has at least tried to cancel the |
193 * has been exceeded and has at least tried to cancel the |
193 * current database connection attempt |
194 * current database connection attempt |
194 */ |
195 */ |
|
196 @CallerSensitive |
195 public static Connection getConnection(String url, |
197 public static Connection getConnection(String url, |
196 java.util.Properties info) throws SQLException { |
198 java.util.Properties info) throws SQLException { |
197 |
199 |
198 // Gets the classloader of the code that called this method, may |
200 return (getConnection(url, info, Reflection.getCallerClass())); |
199 // be null. |
|
200 ClassLoader callerCL = DriverManager.getCallerClassLoader(); |
|
201 |
|
202 return (getConnection(url, info, callerCL)); |
|
203 } |
201 } |
204 |
202 |
205 /** |
203 /** |
206 * Attempts to establish a connection to the given database URL. |
204 * Attempts to establish a connection to the given database URL. |
207 * The <code>DriverManager</code> attempts to select an appropriate driver from |
205 * The <code>DriverManager</code> attempts to select an appropriate driver from |
224 * @throws SQLTimeoutException when the driver has determined that the |
222 * @throws SQLTimeoutException when the driver has determined that the |
225 * timeout value specified by the {@code setLoginTimeout} method |
223 * timeout value specified by the {@code setLoginTimeout} method |
226 * has been exceeded and has at least tried to cancel the |
224 * has been exceeded and has at least tried to cancel the |
227 * current database connection attempt |
225 * current database connection attempt |
228 */ |
226 */ |
|
227 @CallerSensitive |
229 public static Connection getConnection(String url, |
228 public static Connection getConnection(String url, |
230 String user, String password) throws SQLException { |
229 String user, String password) throws SQLException { |
231 java.util.Properties info = new java.util.Properties(); |
230 java.util.Properties info = new java.util.Properties(); |
232 |
231 |
233 // Gets the classloader of the code that called this method, may |
|
234 // be null. |
|
235 ClassLoader callerCL = DriverManager.getCallerClassLoader(); |
|
236 |
|
237 if (user != null) { |
232 if (user != null) { |
238 info.put("user", user); |
233 info.put("user", user); |
239 } |
234 } |
240 if (password != null) { |
235 if (password != null) { |
241 info.put("password", password); |
236 info.put("password", password); |
242 } |
237 } |
243 |
238 |
244 return (getConnection(url, info, callerCL)); |
239 return (getConnection(url, info, Reflection.getCallerClass())); |
245 } |
240 } |
246 |
241 |
247 /** |
242 /** |
248 * Attempts to establish a connection to the given database URL. |
243 * Attempts to establish a connection to the given database URL. |
249 * The <code>DriverManager</code> attempts to select an appropriate driver from |
244 * The <code>DriverManager</code> attempts to select an appropriate driver from |
257 * @throws SQLTimeoutException when the driver has determined that the |
252 * @throws SQLTimeoutException when the driver has determined that the |
258 * timeout value specified by the {@code setLoginTimeout} method |
253 * timeout value specified by the {@code setLoginTimeout} method |
259 * has been exceeded and has at least tried to cancel the |
254 * has been exceeded and has at least tried to cancel the |
260 * current database connection attempt |
255 * current database connection attempt |
261 */ |
256 */ |
|
257 @CallerSensitive |
262 public static Connection getConnection(String url) |
258 public static Connection getConnection(String url) |
263 throws SQLException { |
259 throws SQLException { |
264 |
260 |
265 java.util.Properties info = new java.util.Properties(); |
261 java.util.Properties info = new java.util.Properties(); |
266 |
262 return (getConnection(url, info, Reflection.getCallerClass())); |
267 // Gets the classloader of the code that called this method, may |
|
268 // be null. |
|
269 ClassLoader callerCL = DriverManager.getCallerClassLoader(); |
|
270 |
|
271 return (getConnection(url, info, callerCL)); |
|
272 } |
263 } |
273 |
264 |
274 /** |
265 /** |
275 * Attempts to locate a driver that understands the given URL. |
266 * Attempts to locate a driver that understands the given URL. |
276 * The <code>DriverManager</code> attempts to select an appropriate driver from |
267 * The <code>DriverManager</code> attempts to select an appropriate driver from |
280 * <code>jdbc:<em>subprotocol</em>:<em>subname</em></code> |
271 * <code>jdbc:<em>subprotocol</em>:<em>subname</em></code> |
281 * @return a <code>Driver</code> object representing a driver |
272 * @return a <code>Driver</code> object representing a driver |
282 * that can connect to the given URL |
273 * that can connect to the given URL |
283 * @exception SQLException if a database access error occurs |
274 * @exception SQLException if a database access error occurs |
284 */ |
275 */ |
|
276 @CallerSensitive |
285 public static Driver getDriver(String url) |
277 public static Driver getDriver(String url) |
286 throws SQLException { |
278 throws SQLException { |
287 |
279 |
288 println("DriverManager.getDriver(\"" + url + "\")"); |
280 println("DriverManager.getDriver(\"" + url + "\")"); |
289 |
281 |
290 // Gets the classloader of the code that called this method, may |
282 Class<?> callerClass = Reflection.getCallerClass(); |
291 // be null. |
|
292 ClassLoader callerCL = DriverManager.getCallerClassLoader(); |
|
293 |
283 |
294 // Walk through the loaded registeredDrivers attempting to locate someone |
284 // Walk through the loaded registeredDrivers attempting to locate someone |
295 // who understands the given URL. |
285 // who understands the given URL. |
296 for (DriverInfo aDriver : registeredDrivers) { |
286 for (DriverInfo aDriver : registeredDrivers) { |
297 // If the caller does not have permission to load the driver then |
287 // If the caller does not have permission to load the driver then |
298 // skip it. |
288 // skip it. |
299 if(isDriverAllowed(aDriver.driver, callerCL)) { |
289 if(isDriverAllowed(aDriver.driver, callerClass)) { |
300 try { |
290 try { |
301 if(aDriver.driver.acceptsURL(url)) { |
291 if(aDriver.driver.acceptsURL(url)) { |
302 // Success! |
292 // Success! |
303 println("getDriver returning " + aDriver.driver.getClass().getName()); |
293 println("getDriver returning " + aDriver.driver.getClass().getName()); |
304 return (aDriver.driver); |
294 return (aDriver.driver); |
348 * Applets can only deregister drivers from their own classloaders. |
338 * Applets can only deregister drivers from their own classloaders. |
349 * |
339 * |
350 * @param driver the JDBC Driver to drop |
340 * @param driver the JDBC Driver to drop |
351 * @exception SQLException if a database access error occurs |
341 * @exception SQLException if a database access error occurs |
352 */ |
342 */ |
|
343 @CallerSensitive |
353 public static synchronized void deregisterDriver(Driver driver) |
344 public static synchronized void deregisterDriver(Driver driver) |
354 throws SQLException { |
345 throws SQLException { |
355 if (driver == null) { |
346 if (driver == null) { |
356 return; |
347 return; |
357 } |
348 } |
358 |
349 |
359 // Gets the classloader of the code that called this method, |
|
360 // may be null. |
|
361 ClassLoader callerCL = DriverManager.getCallerClassLoader(); |
|
362 println("DriverManager.deregisterDriver: " + driver); |
350 println("DriverManager.deregisterDriver: " + driver); |
363 |
351 |
364 DriverInfo aDriver = new DriverInfo(driver); |
352 DriverInfo aDriver = new DriverInfo(driver); |
365 if(registeredDrivers.contains(aDriver)) { |
353 if(registeredDrivers.contains(aDriver)) { |
366 if (isDriverAllowed(driver, callerCL)) { |
354 if (isDriverAllowed(driver, Reflection.getCallerClass())) { |
367 registeredDrivers.remove(aDriver); |
355 registeredDrivers.remove(aDriver); |
368 } else { |
356 } else { |
369 // If the caller does not have permission to load the driver then |
357 // If the caller does not have permission to load the driver then |
370 // throw a SecurityException. |
358 // throw a SecurityException. |
371 throw new SecurityException(); |
359 throw new SecurityException(); |
382 * <P><B>Note:</B> The classname of a driver can be found using |
370 * <P><B>Note:</B> The classname of a driver can be found using |
383 * <CODE>d.getClass().getName()</CODE> |
371 * <CODE>d.getClass().getName()</CODE> |
384 * |
372 * |
385 * @return the list of JDBC Drivers loaded by the caller's class loader |
373 * @return the list of JDBC Drivers loaded by the caller's class loader |
386 */ |
374 */ |
|
375 @CallerSensitive |
387 public static java.util.Enumeration<Driver> getDrivers() { |
376 public static java.util.Enumeration<Driver> getDrivers() { |
388 java.util.Vector<Driver> result = new java.util.Vector<>(); |
377 java.util.Vector<Driver> result = new java.util.Vector<>(); |
389 |
378 |
390 // Gets the classloader of the code that called this method, may |
379 Class<?> callerClass = Reflection.getCallerClass(); |
391 // be null. |
|
392 ClassLoader callerCL = DriverManager.getCallerClassLoader(); |
|
393 |
380 |
394 // Walk through the loaded registeredDrivers. |
381 // Walk through the loaded registeredDrivers. |
395 for(DriverInfo aDriver : registeredDrivers) { |
382 for(DriverInfo aDriver : registeredDrivers) { |
396 // If the caller does not have permission to load the driver then |
383 // If the caller does not have permission to load the driver then |
397 // skip it. |
384 // skip it. |
398 if(isDriverAllowed(aDriver.driver, callerCL)) { |
385 if(isDriverAllowed(aDriver.driver, callerClass)) { |
399 result.addElement(aDriver.driver); |
386 result.addElement(aDriver.driver); |
400 } else { |
387 } else { |
401 println(" skipping: " + aDriver.getClass().getName()); |
388 println(" skipping: " + aDriver.getClass().getName()); |
402 } |
389 } |
403 } |
390 } |
491 } |
478 } |
492 } |
479 } |
493 |
480 |
494 //------------------------------------------------------------------------ |
481 //------------------------------------------------------------------------ |
495 |
482 |
496 // Internal method used to get the caller's class loader. |
|
497 // Replaces the call to the native method |
|
498 private static ClassLoader getCallerClassLoader() { |
|
499 Class<?> cc = Reflection.getCallerClass(3); |
|
500 ClassLoader cl = (cc != null) ? cc.getClassLoader() : null; |
|
501 return cl; |
|
502 } |
|
503 |
|
504 |
|
505 // Indicates whether the class object that would be created if the code calling |
483 // Indicates whether the class object that would be created if the code calling |
506 // DriverManager is accessible. |
484 // DriverManager is accessible. |
|
485 private static boolean isDriverAllowed(Driver driver, Class<?> caller) { |
|
486 ClassLoader callerCL = caller != null ? caller.getClassLoader() : null; |
|
487 return isDriverAllowed(driver, callerCL); |
|
488 } |
|
489 |
507 private static boolean isDriverAllowed(Driver driver, ClassLoader classLoader) { |
490 private static boolean isDriverAllowed(Driver driver, ClassLoader classLoader) { |
508 boolean result = false; |
491 boolean result = false; |
509 if(driver != null) { |
492 if(driver != null) { |
510 Class<?> aClass = null; |
493 Class<?> aClass = null; |
511 try { |
494 try { |
584 } |
567 } |
585 |
568 |
586 |
569 |
587 // Worker method called by the public getConnection() methods. |
570 // Worker method called by the public getConnection() methods. |
588 private static Connection getConnection( |
571 private static Connection getConnection( |
589 String url, java.util.Properties info, ClassLoader callerCL) throws SQLException { |
572 String url, java.util.Properties info, Class<?> caller) throws SQLException { |
590 /* |
573 /* |
591 * When callerCl is null, we should check the application's |
574 * When callerCl is null, we should check the application's |
592 * (which is invoking this class indirectly) |
575 * (which is invoking this class indirectly) |
593 * classloader, so that the JDBC driver class outside rt.jar |
576 * classloader, so that the JDBC driver class outside rt.jar |
594 * can be loaded from here. |
577 * can be loaded from here. |
595 */ |
578 */ |
|
579 ClassLoader callerCL = caller != null ? caller.getClassLoader() : null; |
596 synchronized(DriverManager.class) { |
580 synchronized(DriverManager.class) { |
597 // synchronize loading of the correct classloader. |
581 // synchronize loading of the correct classloader. |
598 if(callerCL == null) { |
582 if (callerCL == null) { |
599 callerCL = Thread.currentThread().getContextClassLoader(); |
583 callerCL = Thread.currentThread().getContextClassLoader(); |
600 } |
584 } |
601 } |
585 } |
602 |
586 |
603 if(url == null) { |
587 if(url == null) { |
604 throw new SQLException("The url cannot be null", "08001"); |
588 throw new SQLException("The url cannot be null", "08001"); |
605 } |
589 } |