home *** CD-ROM | disk | FTP | other *** search
/ Java 1.2 How-To / JavaHowTo.iso / 3rdParty / jbuilder / unsupported / JDK1.2beta3 / SOURCE / SRC.ZIP / java / sql / DriverManager.java < prev    next >
Encoding:
Java Source  |  1998-03-20  |  15.4 KB  |  461 lines

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