Source for java.sql.DriverManager

   1: /* DriverManager.java -- Manage JDBC drivers
   2:    Copyright (C) 1999, 2000, 2001, 2003, 2004, 2006
   3:    Free Software Foundation, Inc.
   4: 
   5: This file is part of GNU Classpath.
   6: 
   7: GNU Classpath is free software; you can redistribute it and/or modify
   8: it under the terms of the GNU General Public License as published by
   9: the Free Software Foundation; either version 2, or (at your option)
  10: any later version.
  11: 
  12: GNU Classpath is distributed in the hope that it will be useful, but
  13: WITHOUT ANY WARRANTY; without even the implied warranty of
  14: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15: General Public License for more details.
  16: 
  17: You should have received a copy of the GNU General Public License
  18: along with GNU Classpath; see the file COPYING.  If not, write to the
  19: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  20: 02110-1301 USA.
  21: 
  22: Linking this library statically or dynamically with other modules is
  23: making a combined work based on this library.  Thus, the terms and
  24: conditions of the GNU General Public License cover the whole
  25: combination.
  26: 
  27: As a special exception, the copyright holders of this library give you
  28: permission to link this library with independent modules to produce an
  29: executable, regardless of the license terms of these independent
  30: modules, and to copy and distribute the resulting executable under
  31: terms of your choice, provided that you also meet, for each linked
  32: independent module, the terms and conditions of the license of that
  33: module.  An independent module is a module which is not derived from
  34: or based on this library.  If you modify this library, you may extend
  35: this exception to your version of the library, but you are not
  36: obligated to do so.  If you do not wish to do so, delete this
  37: exception statement from your version. */
  38: 
  39: package java.sql;
  40: 
  41: import java.io.PrintStream;
  42: import java.io.PrintWriter;
  43: import java.util.Enumeration;
  44: import java.util.Properties;
  45: import java.util.StringTokenizer;
  46: import java.util.Vector;
  47: 
  48: /**
  49:   * This class manages the JDBC drivers in the system. It maintains a
  50:   * registry of drivers and locates the appropriate driver to handle a
  51:   * JDBC database URL.
  52:   * <p>
  53:   * On startup, <code>DriverManager</code> loads all the managers specified
  54:   * by the system property <code>jdbc.drivers</code>.  The value of this
  55:   * property should be a colon separated list of fully qualified driver
  56:   * class names.  Additional drivers can be loaded at any time by
  57:   * simply loading the driver class with <code>class.forName(String)</code>.
  58:   * The driver should automatically register itself in a static
  59:   * initializer.
  60:   * <p>
  61:   * The methods in this class are all <code>static</code>. This class
  62:   * cannot be instantiated.
  63:   *
  64:   * @author Aaron M. Renn (arenn@urbanophile.com)
  65:   */
  66: public class DriverManager
  67: {
  68:   /**
  69:    * This is the log stream for JDBC drivers.
  70:    */
  71:   private static PrintStream log_stream;
  72: 
  73:   /**
  74:    * This is the log writer for JDBC drivers.
  75:    */
  76:   private static PrintWriter log_writer;
  77: 
  78:   /**
  79:    * This is the login timeout used by JDBC drivers.
  80:    */
  81:   private static int login_timeout;
  82: 
  83:   /**
  84:    * This is the list of JDBC drivers that are loaded.
  85:    */
  86:   private static Vector drivers;
  87:    // Hmm, seems like we might want to do a Hashtable and lookup by something,
  88:    // but what would it be?
  89: 
  90:   // Load all drivers on startup
  91:   static
  92:   {
  93:     drivers = new Vector();
  94: 
  95:     String driver_string = System.getProperty("jdbc.drivers");
  96:     if (driver_string != null)
  97:       {
  98:         StringTokenizer st = new StringTokenizer(driver_string);
  99:         while (st.hasMoreTokens())
 100:           {
 101:             String driver_classname = st.nextToken();
 102: 
 103:             try
 104:               {
 105:                 Class.forName(driver_classname); // The driver registers itself
 106:               }
 107:             catch (Exception e)
 108:               {
 109:                 // Ignore not founds
 110:               }
 111:           }
 112:       }
 113: 
 114:   }
 115: 
 116:   /** Can't be instantiated. */
 117:   private DriverManager()
 118:   {
 119:   }
 120: 
 121:   /**
 122:    * This method returns the log writer being used by all JDBC drivers.
 123:    * This method should be used in place of the deprecated
 124:    * <code>getLogStream</code> method.
 125:    *
 126:    * @return The log writer in use by JDBC drivers.
 127:    */
 128:   public static PrintWriter getLogWriter()
 129:   {
 130:     return log_writer;
 131:   }
 132: 
 133:   /**
 134:    * This method sets the log writer being used by JDBC drivers.  This is a
 135:    * system-wide parameter that affects all drivers.  Note that since there
 136:    * is no way to retrieve a <code>PrintStream</code> from a
 137:    * <code>PrintWriter</code>, this method cannot set the log stream in
 138:    * use by JDBC.  Thus any older drivers may not see this setting.
 139:    *
 140:    * @param out The new log writer for JDBC.
 141:    */
 142:   public static void setLogWriter(PrintWriter out)
 143:   {
 144:     DriverManager.log_writer = out;
 145:   }
 146: 
 147: /**
 148:   * This method attempts to return a connection to the specified
 149:   * JDBC URL string using the specified connection properties.
 150:   *
 151:   * @param url The JDBC URL string to connect to.
 152:   * @param properties The connection properties.
 153:   *
 154:   * @return A <code>Connection</code> to that URL.
 155:   *
 156:   * @exception SQLException If an error occurs.
 157:   */
 158:   public static Connection getConnection(String url, Properties properties)
 159:     throws SQLException
 160:   {
 161:     Driver d = getDriver(url);
 162:     if (d == null)
 163:       throw new SQLException("Driver not found for URL: " + url);
 164: 
 165:     return d.connect(url, properties);
 166:   }
 167: 
 168: 
 169:   /**
 170:    * This method attempts to return a connection to the specified
 171:    * JDBC URL string using the specified username and password.
 172:    *
 173:    * @param url The JDBC URL string to connect to.
 174:    * @param user The username to connect with.
 175:    * @param password The password to connect with.
 176:    * @return A <code>Connection</code> to that URL.
 177:    * @exception SQLException If an error occurs.
 178:    */
 179:   public static Connection getConnection(String url, String user,
 180:     String password) throws SQLException
 181:   {
 182:     Properties p = new Properties();
 183: 
 184:     if (user != null)
 185:       p.setProperty("user", user);
 186:     if (password != null)
 187:       p.setProperty("password", password);
 188: 
 189:     return getConnection(url, p);
 190:   }
 191: 
 192:   /**
 193:    * This method attempts to return a connection to the specified
 194:    * JDBC URL string.
 195:    *
 196:    * @param url The JDBC URL string to connect to.
 197:    *
 198:    * @return A <code>Connection</code> to that URL.
 199:    *
 200:    * @exception SQLException If an error occurs.
 201:    */
 202:   public static Connection getConnection(String url) throws SQLException
 203:   {
 204:     return getConnection(url, new Properties());
 205:   }
 206: 
 207:   /**
 208:    * This method returns a driver that can connect to the specified
 209:    * JDBC URL string.  This will be selected from among drivers loaded
 210:    * at initialization time and those drivers manually loaded by the
 211:    * same class loader as the caller.
 212:    *
 213:    * @param url The JDBC URL string to find a driver for.
 214:    *
 215:    * @return A <code>Driver</code> that can connect to the specified
 216:    * URL.
 217:    *
 218:    * @exception SQLException If an error occurs, or no suitable driver can be found.
 219:    */
 220:   public static Driver getDriver(String url) throws SQLException
 221:   {
 222:     // FIXME: Limit driver search to the appropriate subset of loaded drivers.
 223:     Enumeration e = drivers.elements();
 224:     while(e.hasMoreElements())
 225:       {
 226:         Driver d = (Driver)e.nextElement();
 227:         if (d.acceptsURL(url))
 228:           return d;
 229:       }
 230: 
 231:     throw new SQLException("No driver found for " + url);
 232:   }
 233: 
 234:   /**
 235:    * This method registers a new driver with the manager.  This is normally
 236:    * called by the driver itself in a static initializer.
 237:    *
 238:    * @param driver The new <code>Driver</code> to add.
 239:    *
 240:    * @exception SQLException If an error occurs.
 241:    */
 242:   public static void registerDriver(Driver driver) throws SQLException
 243:   {
 244:     if (! drivers.contains(driver))
 245:       drivers.addElement(driver);
 246:   }
 247: 
 248: /**
 249:   * This method de-registers a driver from the manager.
 250:   *
 251:   * @param driver The <code>Driver</code> to unregister.
 252:   *
 253:   * @exception SQLException If an error occurs.
 254:   */
 255:   public static void deregisterDriver(Driver driver) throws SQLException
 256:   {
 257:     if (drivers.contains(driver))
 258:       drivers.removeElement(driver);
 259:   }
 260: 
 261:   /**
 262:    * This method returns a list of all the currently registered JDBC drivers
 263:    * that were loaded by the current <code>ClassLoader</code>.
 264:    *
 265:    * @return An <code>Enumeration</code> of all currently loaded JDBC drivers.
 266:    */
 267:   public static Enumeration<Driver> getDrivers()
 268:   {
 269:     Vector v = new Vector();
 270:     Enumeration e = drivers.elements();
 271: 
 272:     // Is this right?
 273:     ClassLoader cl = Thread.currentThread().getContextClassLoader();
 274: 
 275:     while(e.hasMoreElements())
 276:       {
 277:         Object obj = e.nextElement();
 278: 
 279:         ClassLoader loader = obj.getClass().getClassLoader();
 280: 
 281:         if (loader == null)
 282:           loader = ClassLoader.getSystemClassLoader();
 283:         if (! loader.equals(cl))
 284:           continue;
 285: 
 286:         v.addElement(obj);
 287:       }
 288: 
 289:     return v.elements();
 290:   }
 291: 
 292:   /**
 293:    * This method set the login timeout used by JDBC drivers.  This is a
 294:    * system-wide parameter that applies to all drivers.
 295:    *
 296:    * @param seconds The new login timeout value.
 297:    */
 298:   public static void setLoginTimeout(int seconds)
 299:   {
 300:     DriverManager.login_timeout = seconds;
 301:   }
 302: 
 303:   /**
 304:    * This method returns the login timeout in use by JDBC drivers systemwide.
 305:    *
 306:    * @return The login timeout.
 307:    */
 308:   public static int getLoginTimeout()
 309:   {
 310:     return login_timeout;
 311:   }
 312: 
 313:   /**
 314:    * This method sets the log stream in use by JDBC.
 315:    *
 316:    * @param stream The log stream in use by JDBC.
 317:    * @deprecated Use <code>setLogWriter</code> instead.
 318:    */
 319:   public static void setLogStream(PrintStream stream)
 320:   {
 321:     DriverManager.log_stream = stream;
 322:   }
 323: 
 324:   /**
 325:    * This method returns the log stream in use by JDBC.
 326:    *
 327:    * @return The log stream in use by JDBC.
 328:    * @deprecated Use <code>getLogWriter()</code> instead.
 329:    */
 330:   public static PrintStream getLogStream()
 331:   {
 332:     return log_stream;
 333:   }
 334: 
 335:   /**
 336:    * This method prints the specified line to the log stream.
 337:    *
 338:    * @param message The string to write to the log stream.
 339:    */
 340:   public static void println(String message)
 341:   {
 342:     if (log_stream != null) // Watch for user not using logging
 343:       log_stream.println(message);
 344:   }
 345: }