home *** CD-ROM | disk | FTP | other *** search
/ Programming Languages Suite / ProgLangD.iso / VCAFE.3.0A / Main.bin / DriverManager.java < prev    next >
Text File  |  1998-09-22  |  15KB  |  417 lines

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