home *** CD-ROM | disk | FTP | other *** search
/ Apple Developer Connection Student Program / ADC Tools Sampler CD Disk 3 1999.iso / Metrowerks CodeWarrior / Java Support / Java_Source / Java2 / src / java / sql / DriverManager.java < prev    next >
Encoding:
Java Source  |  1999-05-28  |  16.3 KB  |  516 lines  |  [TEXT/CWIE]

  1. /*
  2.  * @(#)DriverManager.java    1.21 98/09/22
  3.  *
  4.  * Copyright 1996-1998 by Sun Microsystems, Inc.,
  5.  * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
  6.  * All rights reserved.
  7.  *
  8.  * This software is the confidential and proprietary information
  9.  * of Sun Microsystems, Inc. ("Confidential Information").  You
  10.  * shall not disclose such Confidential Information and shall use
  11.  * it only in accordance with the terms of the license agreement
  12.  * you entered into with Sun.
  13.  */
  14.  
  15. package java.sql;
  16.  
  17. /**
  18.  * <P>The basic service for managing a set of JDBC drivers.
  19.  *
  20.  * <P>As part of its initialization, the DriverManager class will
  21.  * attempt to load the driver classes referenced in the "jdbc.drivers"
  22.  * system property. This allows a user to customize the JDBC Drivers
  23.  * used by their applications. For example in your
  24.  * ~/.hotjava/properties file you might specify:
  25.  * <pre>
  26.  * <CODE>jdbc.drivers=foo.bah.Driver:wombat.sql.Driver:bad.taste.ourDriver</CODE>
  27.  * </pre>
  28.  *
  29.  * A program can also explicitly load JDBC drivers at any time. For
  30.  * example, the my.sql.Driver is loaded with the following statement:
  31.  * <pre>
  32.  * <CODE>Class.forName("my.sql.Driver");</CODE>
  33.  * </pre>
  34.  *
  35.  * <P>When the method <code>getConnection</code> is called,
  36.  * the DriverManager will attempt to
  37.  * locate a suitable driver from amongst those loaded at
  38.  * initialization and those loaded explicitly using the same classloader
  39.  * as the current applet or application.
  40.  *
  41.  * @see Driver
  42.  * @see Connection 
  43.  */
  44. public class DriverManager {
  45.  
  46.     //--------------------------JDBC 2.0-----------------------------
  47.  
  48.     /**
  49.      * JDBC 2.0
  50.      *
  51.      * Gets the log writer.  
  52.      *
  53.      * The <code>getLogWriter</code> and <code>setLogWriter</code> 
  54.      * methods should be used instead
  55.      * of the old <code>get/setlogStream</code> methods.
  56.      */
  57.     public static java.io.PrintWriter getLogWriter() {
  58.       return logWriter;
  59.     }
  60.  
  61.     /**
  62.      * JDBC 2.0
  63.      *
  64.      * Sets the logging/tracing Writer that is used by the DriverManager
  65.      * and all drivers.
  66.      *
  67.      * There is a minor versioning problem introduced by the introduction
  68.      * of the method </code>setLogWriter</code>.  The 
  69.      * method <code>setLogWriter</code> cannot create a PrintStream
  70.      * that will be returned by <code>getLogStream</code>---the Java platform does
  71.      * not provide a backward conversion.  So, a new application
  72.      * that uses <code>setLogWriter</code> and also uses a JDBC 1.0 driver that uses
  73.      * <code>getLogStream</code> will likely not see debugging information written 
  74.      * by that driver.
  75.      *
  76.      * @param out the new logging/tracing PrintStream; to disable, set to null
  77.      */
  78.     public static synchronized void setLogWriter(java.io.PrintWriter out) {
  79.       logStream = null;
  80.       logWriter = out;
  81.     }
  82.  
  83.  
  84.     //---------------------------------------------------------------
  85.  
  86.     /**
  87.      * Attempts to establish a connection to the given database URL.
  88.      * The DriverManager attempts to select an appropriate driver from
  89.      * the set of registered JDBC drivers.
  90.      *
  91.      * @param url a database url of the form 
  92.      * <code> jdbc:<em>subprotocol</em>:<em>subname</em></code>
  93.      * @param info a list of arbitrary string tag/value pairs as
  94.      * connection arguments; normally at least a "user" and
  95.      * "password" property should be included
  96.      * @return a Connection to the URL 
  97.      * @exception SQLException if a database access error occurs
  98.      */
  99.     public static synchronized Connection getConnection(String url, 
  100.             java.util.Properties info) throws SQLException {
  101.   
  102.         // Gets the classloader of the code that called this method, may 
  103.     // be null.
  104.     ClassLoader callerCL = DriverManager.getCallerClassLoader();
  105.  
  106.         return (getConnection(url, info, callerCL));
  107.     }
  108.  
  109.     /**
  110.      * Attempts to establish a connection to the given database URL.
  111.      * The DriverManager attempts to select an appropriate driver from
  112.      * the set of registered JDBC drivers.
  113.      *
  114.      * @param url a database url of the form 
  115.      * <code>jdbc:<em>subprotocol</em>:<em>subname</em></code>
  116.      * @param user the database user on whose behalf the Connection is being
  117.      *   made
  118.      * @param password the user's password
  119.      * @return a Connection to the URL 
  120.      * @exception SQLException if a database access error occurs
  121.      */
  122.     public static synchronized Connection getConnection(String url, 
  123.                     String user, String password) throws SQLException {
  124.         java.util.Properties info = new java.util.Properties();
  125.  
  126.         // Gets the classloader of the code that called this method, may 
  127.     // be null.
  128.     ClassLoader callerCL = DriverManager.getCallerClassLoader();
  129.  
  130.     if (user != null) {
  131.         info.put("user", user);
  132.     }
  133.     if (password != null) {
  134.         info.put("password", password);
  135.     }
  136.  
  137.         return (getConnection(url, info, callerCL));
  138.     }
  139.  
  140.     /**
  141.      * Attempts to establish a connection to the given database URL.
  142.      * The DriverManager attempts to select an appropriate driver from
  143.      * the set of registered JDBC drivers.
  144.      *
  145.      * @param url a database url of the form 
  146.      *  <code> jdbc:<em>subprotocol</em>:<em>subname</em></code>
  147.      * @return a Connection to the URL 
  148.      * @exception SQLException if a database access error occurs
  149.      */
  150.     public static synchronized Connection getConnection(String url) 
  151.                                     throws SQLException {
  152.  
  153.         java.util.Properties info = new java.util.Properties();
  154.  
  155.         // Gets the classloader of the code that called this method, may 
  156.     // be null.
  157.     ClassLoader callerCL = DriverManager.getCallerClassLoader();
  158.  
  159.         return (getConnection(url, info, callerCL));
  160.     }
  161.  
  162.     /**
  163.      * Attempts to locate a driver that understands the given URL.
  164.      * The DriverManager attempts to select an appropriate driver from
  165.      * the set of registered JDBC drivers. 
  166.      *
  167.      * @param url a database url of the form 
  168.      *  jdbc:<em>subprotocol</em>:<em>subname</em>
  169.      * @return a Driver that can connect to the URL 
  170.      * @exception SQLException if a database access error occurs
  171.      */
  172.     public static synchronized Driver getDriver(String url) 
  173.       throws SQLException {
  174.         println("DriverManager.getDriver(\"" + url + "\")");
  175.  
  176.         if (!initialized) {
  177.             initialize();
  178.         }
  179.  
  180.         // Gets the classloader of the code that called this method, may 
  181.     // be null.
  182.     ClassLoader callerCL = DriverManager.getCallerClassLoader();
  183.  
  184.         // Walk through the loaded drivers attempting to locate someone
  185.     // who understands the given URL.
  186.         for (int i = 0; i < drivers.size(); i++) {
  187.             DriverInfo di = (DriverInfo)drivers.elementAt(i);
  188.         // If the caller does not have permission to load the driver then 
  189.         // skip it.
  190.             if ( getCallerClass(callerCL, di.driverClassName ) != 
  191.          di.driverClass ) {
  192.                 println("    skipping: " + di);
  193.                 continue;
  194.             }
  195.             try {
  196.                 println("    trying " + di);
  197.         if (di.driver.acceptsURL(url)) {
  198.             // Success!
  199.                     println("getDriver returning " + di);
  200.                     return (di.driver);
  201.                 }
  202.             } catch (SQLException ex) {
  203.         // Drop through and try the next driver.
  204.             }
  205.         }
  206.  
  207.         println("getDriver: no suitable driver");
  208.         throw new SQLException("No suitable driver", "08001");
  209.     }
  210.  
  211.  
  212.   /**
  213.    * Registers the given driver with the DriverManager.
  214.    * A newly-loaded driver class should call
  215.    * the method <code>registerDriver</code> to make itself
  216.    * known to the DriverManager.
  217.    *
  218.    * @param driver the new JDBC Driver that is to be registered with the
  219.    *               DriverManager
  220.    * @exception SQLException if a database access error occurs
  221.    */
  222.   public static synchronized void registerDriver(java.sql.Driver driver)
  223.     throws SQLException {
  224.       if (!initialized) {
  225.     initialize();
  226.       }
  227.       
  228.       DriverInfo di = new DriverInfo();
  229.       di.driver = driver;
  230.       di.driverClass = driver.getClass();
  231.       di.driverClassName = di.driverClass.getName();
  232.       drivers.addElement(di);
  233.       println("registerDriver: " + di);
  234.   }
  235.  
  236.   /**
  237.    * Drops a Driver from the DriverManager's list.  Applets can only
  238.    * deregister Drivers from their own classloaders.
  239.    *
  240.    * @param driver the JDBC Driver to drop 
  241.    * @exception SQLException if a database access error occurs
  242.    */
  243.   public static synchronized void deregisterDriver(Driver driver) 
  244.     throws SQLException {
  245.       // Gets the classloader of the code that called this method, may 
  246.       // be null.
  247.       ClassLoader callerCL = DriverManager.getCallerClassLoader();
  248.       println("DriverManager.deregisterDriver: " + driver);
  249.       
  250.       // Walk through the loaded drivers.
  251.       int i;
  252.       DriverInfo di = null;
  253.       for (i = 0; i < drivers.size(); i++) {
  254.     di = (DriverInfo)drivers.elementAt(i);
  255.     if (di.driver == driver) {
  256.       break;
  257.     }
  258.       }
  259.       // If we can't find the driver just return.
  260.       if (i >= drivers.size()) {
  261.     println("    couldn't find driver to unload");
  262.     return;
  263.       }
  264.       
  265.       // If the caller does not have permission to load the driver then 
  266.       // throw a security exception.
  267.       if ( getCallerClass(callerCL, di.driverClassName ) != di.driverClass ) {
  268.     throw new SecurityException();
  269.       }
  270.       
  271.       // Remove the driver.  Other entries in drivers get shuffled down.
  272.       drivers.removeElementAt(i);
  273.       
  274.   }
  275.  
  276.     /**
  277.      * Retrieves an Enumeration with all of the currently loaded JDBC drivers
  278.      * to which the current caller has access.
  279.      *
  280.      * <P><B>Note:</B> The classname of a driver can be found using
  281.      * <CODE>d.getClass().getName()</CODE>
  282.      *
  283.      * @return the list of JDBC Drivers loaded by the caller's class loader
  284.      */
  285.     public static synchronized java.util.Enumeration getDrivers() {
  286.         java.util.Vector result = new java.util.Vector();
  287.  
  288.         if (!initialized) {
  289.             initialize();
  290.         }
  291.  
  292.         // Gets the classloader of the code that called this method, may 
  293.     // be null.
  294.     ClassLoader callerCL = DriverManager.getCallerClassLoader();
  295.  
  296.         // Walk through the loaded drivers.
  297.         for (int i = 0; i < drivers.size(); i++) {
  298.             DriverInfo di = (DriverInfo)drivers.elementAt(i);
  299.         // If the caller does not have permission to load the driver then 
  300.         // skip it.
  301.             if ( getCallerClass(callerCL, di.driverClassName ) != di.driverClass ) {
  302.                 println("    skipping: " + di);
  303.                 continue;
  304.             }
  305.             result.addElement(di.driver);
  306.         }
  307.  
  308.         return (result.elements());
  309.     }
  310.  
  311.  
  312.     /**
  313.      * <p>Sets the maximum time in seconds that a driver will wait
  314.      * while attempting to connect to a database.  
  315.      *
  316.      * @param seconds the login time limit in seconds
  317.      */
  318.     public static void setLoginTimeout(int seconds) { 
  319.         loginTimeout = seconds;
  320.     }
  321.  
  322.     /**
  323.      * Gets the maximum time in seconds that a driver can wait
  324.      * when attempting to log in to a database.
  325.      *
  326.      * @return the driver login time limit in seconds
  327.      */
  328.     public static int getLoginTimeout() {
  329.         return (loginTimeout);
  330.     }
  331.  
  332.     /**
  333.      * Sets the logging/tracing PrintStream that is used by the DriverManager
  334.      * and all drivers.
  335.      *
  336.      * @param out the new logging/tracing PrintStream; to disable, set to null
  337.      * @deprecated
  338.      */
  339.     public static synchronized void setLogStream(java.io.PrintStream out) {
  340.         logStream = out;
  341.     if ( out != null )
  342.       logWriter = new java.io.PrintWriter(out);
  343.     else
  344.       logWriter = null;
  345.     }
  346.  
  347.     /**
  348.      * Gets the logging/tracing PrintStream that is used by the DriverManager
  349.      * and all drivers.
  350.      *
  351.      * @return the logging/tracing PrintStream; if disabled, is null
  352.      * @deprecated
  353.      */
  354.     public static java.io.PrintStream getLogStream() {
  355.         return logStream;
  356.     }
  357.  
  358.     /**
  359.      * Prints a message to the current JDBC log stream.
  360.      *
  361.      * @param message a log or tracing message
  362.      */
  363.     public static synchronized void println(String message) {
  364.         if (logWriter != null) {
  365.             logWriter.println(message);
  366.  
  367.         // automatic flushing is never enabled, so we must do it ourselves
  368.         logWriter.flush();
  369.         }
  370.     }
  371.  
  372.     //------------------------------------------------------------------------
  373.  
  374.     // Returns the class object that would be created if the code calling the 
  375.     // driver manager had loaded the driver class, or null if the class
  376.     // is inaccessible.
  377.     private static Class getCallerClass(ClassLoader callerClassLoader, 
  378.                     String driverClassName) {
  379.       Class callerC = null;
  380.  
  381.       try {
  382.     callerC = Class.forName(driverClassName, true, callerClassLoader);
  383.       }
  384.       catch (Exception ex) {
  385.     callerC = null;           // being very careful 
  386.       }
  387.  
  388.       return callerC;
  389.     }
  390.  
  391.     private static void loadInitialDrivers() {
  392.         String drivers;
  393.         try {
  394.         drivers = (String) java.security.AccessController.doPrivileged(
  395.                 new sun.security.action.GetPropertyAction("jdbc.drivers"));
  396.         } catch (Exception ex) {
  397.             drivers = null;
  398.         }
  399.         println("DriverManager.initialize: jdbc.drivers = " + drivers);
  400.         if (drivers == null) {
  401.             return;
  402.         }
  403.         while (drivers.length() != 0) {
  404.             int x = drivers.indexOf(':');
  405.             String driver;
  406.             if (x < 0) {
  407.                 driver = drivers;
  408.                 drivers = "";
  409.             } else {
  410.                 driver = drivers.substring(0, x);
  411.                 drivers = drivers.substring(x+1);
  412.             }
  413.             if (driver.length() == 0) {
  414.                 continue;
  415.             }
  416.             try {
  417.                 println("DriverManager.Initialize: loading " + driver);
  418.                 Class.forName(driver, true,
  419.                   ClassLoader.getSystemClassLoader());
  420.             } catch (Exception ex) {
  421.                 println("DriverManager.Initialize: load failed: " + ex);
  422.             }
  423.         }
  424.     }
  425.  
  426.  
  427.   //  Worker method called by the public getConnection() methods.
  428.   private static synchronized Connection getConnection(
  429.            String url, 
  430.            java.util.Properties info, 
  431.            ClassLoader callerCL) throws SQLException 
  432.   {
  433.     if(url == null) {
  434.       throw new SQLException("The url cannot be null", "08001");
  435.     }
  436.     
  437.     println("DriverManager.getConnection(\"" + url + "\")");
  438.     
  439.     if (!initialized) {
  440.       initialize();
  441.     }
  442.  
  443.     // Walk through the loaded drivers attempting to make a connection.
  444.     // Remember the first exception that gets raised so we can reraise it.
  445.     SQLException reason = null;
  446.     for (int i = 0; i < drivers.size(); i++) {
  447.       DriverInfo di = (DriverInfo)drivers.elementAt(i);
  448.       
  449.       // If the caller does not have permission to load the driver then 
  450.       // skip it.
  451.       if ( getCallerClass(callerCL, di.driverClassName ) != di.driverClass ) {
  452.     println("    skipping: " + di);
  453.     continue;
  454.       }
  455.       try {
  456.     println("    trying " + di);
  457.     Connection result = di.driver.connect(url, info);
  458.     if (result != null) {
  459.       // Success!
  460.       println("getConnection returning " + di);
  461.       return (result);
  462.     }
  463.       } catch (SQLException ex) {
  464.     if (reason == null) {
  465.       reason = ex;
  466.     }
  467.       }
  468.     }
  469.     
  470.     // if we got here nobody could connect.
  471.     if (reason != null)    {
  472.       println("getConnection failed: " + reason);
  473.       throw reason;
  474.     }
  475.     
  476.     println("getConnection: no suitable driver");
  477.     throw new SQLException("No suitable driver", "08001");
  478.   }
  479.  
  480.  
  481.     // Class initialization.
  482.     static void initialize() {
  483.         if (initialized) {
  484.             return;
  485.         }
  486.         initialized = true;
  487.         loadInitialDrivers();
  488.         println("JDBC DriverManager initialized");
  489.     }
  490.  
  491.     // Prevent the DriverManager class from being instantiated.
  492.     private DriverManager(){}
  493.  
  494.     private static java.util.Vector drivers = new java.util.Vector();
  495.     private static int loginTimeout = 0;
  496.     private static java.io.PrintWriter logWriter = null;
  497.     private static java.io.PrintStream logStream = null;
  498.     private static boolean initialized = false;
  499.  
  500.     // Returns the caller's class loader, or null if none
  501.     private static native ClassLoader getCallerClassLoader();
  502.  
  503. }
  504.  
  505.  
  506. // DriverInfo is a package-private support class.
  507. class DriverInfo {
  508.   Driver         driver;
  509.   Class          driverClass;
  510.   String         driverClassName;
  511.  
  512.   public String toString() {
  513.     return ("driver[className=" + driverClassName + "," + driver + "]");
  514.   }
  515. }
  516.