Main Page | Packages | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | Related Pages

DriverManager.java

00001 /**
00002  * C-JDBC: Clustered JDBC.
00003  * Copyright (C) 2002-2004 French National Institute For Research In Computer
00004  * Science And Control (INRIA).
00005  * Contact: c-jdbc@objectweb.org
00006  * 
00007  * This library is free software; you can redistribute it and/or modify it
00008  * under the terms of the GNU Lesser General Public License as published by the
00009  * Free Software Foundation; either version 2.1 of the License, or any later
00010  * version.
00011  * 
00012  * This library is distributed in the hope that it will be useful, but WITHOUT
00013  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00014  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
00015  * for more details.
00016  * 
00017  * You should have received a copy of the GNU Lesser General Public License
00018  * along with this library; if not, write to the Free Software Foundation,
00019  * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
00020  *
00021  * Initial developer(s): Marc Wick.
00022  * Contributor(s): ______________________.
00023  */
00024 
00025 package org.objectweb.cjdbc.controller.connection;
00026 
00027 import java.io.File;
00028 import java.io.IOException;
00029 import java.net.URL;
00030 import java.sql.Connection;
00031 import java.sql.Driver;
00032 import java.sql.SQLException;
00033 import java.util.HashMap;
00034 import java.util.HashSet;
00035 import java.util.Map;
00036 import java.util.Set;
00037 
00038 import org.objectweb.cjdbc.common.i18n.Translate;
00039 import org.objectweb.cjdbc.common.log.Trace;
00040 import org.objectweb.cjdbc.controller.core.Controller;
00041 import org.objectweb.cjdbc.controller.core.ControllerConstants;
00042 
00043 /**
00044  * This class defines a DriverManager. In contrast to java.sql.DriverManager
00045  * this class allows to use Drivers with the same name but with different
00046  * versions, if no drivername is used it is a wrapper around
00047  * java.sql.DriverManager.
00048  * 
00049  * @author <a href="mailto:Emmanuel.Cecchet@inria.fr">Emmanuel Cecchet </a>
00050  * @version 1.0
00051  */
00052 public class DriverManager
00053 {
00054 
00055   /** Logger instance. */
00056   static Trace       logger         = Trace
00057                                         .getLogger("org.objectweb.cjdbc.controller.connection.DriverManager");
00058 
00059   /**
00060    * Driver class names read from default drivers, without driverPath
00061    */
00062   private static Set defaultDrivers = new HashSet();
00063 
00064   /**
00065    * We keep a reference to already loaded named drivers. Each named driver has
00066    * been loaded with a separate classloader.
00067    */
00068   private static Map namedDrivers   = new HashMap();
00069 
00070   /**
00071    * Attempts to establish a connection to the given database URL. The
00072    * <code>DriverManager</code> attempts to select an appropriate driver from
00073    * the set of registered JDBC drivers.
00074    * 
00075    * @param url a database url of the form
00076    *          <code>jdbc:<em>subprotocol</em>:<em>subname</em></code>
00077    * @param user the database user on whose behalf the connection is being made
00078    * @param password the user's password
00079    * @param driverPathName the path where the driver classes are located, null
00080    *          if default directory
00081    * @param driverClassName the class name of the driver
00082    * @return a connection to the URL
00083    * @exception SQLException if a database access error occurs
00084    */
00085   public static Connection getConnection(String url, String user,
00086       String password, String driverPathName, String driverClassName)
00087       throws SQLException
00088   {
00089     Driver driver = null;
00090     boolean isDefaultPath = false;
00091 
00092     if (driverPathName == null)
00093     {
00094       // no path specified
00095       // have we already loaded this driver
00096       driver = (Driver) namedDrivers.get(driverClassName);
00097       if (driver == null)
00098       {
00099         // the driver has not yet been loaded
00100         // first we try to load class from classpath
00101         try
00102         {
00103           if (driverClassName != null)
00104           {
00105             loadDriverClass(driverClassName);
00106           }
00107           return java.sql.DriverManager.getConnection(url, user, password);
00108         }
00109         catch (ClassNotFoundException e)
00110         {
00111           if (driverClassName == null)
00112           {
00113             throw new SQLException(
00114                 "could not load driver as no class name is specified ");
00115           }
00116           try
00117           {
00118             driverPathName = getDriversDir().getAbsolutePath();
00119             isDefaultPath = true;
00120           }
00121           catch (IOException ioExc)
00122           {
00123             throw new SQLException("could not find default drivers directory");
00124           }
00125         }
00126       }
00127     }
00128 
00129     if (driver == null)
00130     {
00131       // have we already loaded this named driver ?
00132       driver = (Driver) namedDrivers.get(driverPathName);
00133     }
00134 
00135     if (driver == null)
00136     {
00137       // no driver with this name has been loaded so far
00138       try
00139       {
00140         File path = convertToAbsolutePath(driverPathName);
00141         // we load the driver now
00142         if (logger.isDebugEnabled())
00143         {
00144           logger.debug("loading driver with name " + driverPathName
00145               + " for class " + driverClassName);
00146         }
00147         driver = loadDriver(path, driverClassName);
00148       }
00149       catch (Exception e)
00150       {
00151         if (logger.isDebugEnabled())
00152         {
00153           logger.debug("could not load driver for class " + driverClassName, e);
00154         }
00155         throw new SQLException("could not load driver for class name "
00156             + driverClassName + " and driverPath " + driverPathName);
00157       }
00158 
00159       // driver has been loaded successfully, we cache it for
00160       // further use
00161       if (isDefaultPath)
00162       {// we cache it with the class name
00163         namedDrivers.put(driverClassName, driver);
00164       }
00165       else
00166       {
00167         // we cache it with the pathName
00168         namedDrivers.put(driverPathName, driver);
00169       }
00170     }
00171 
00172     return getConnectionForDriver(url, user, password, driver);
00173   }
00174 
00175   /**
00176    * Load the driver class
00177    * 
00178    * @param driverClassName the class name of the driver
00179    * @throws ClassNotFoundException if the class could not be found
00180    */
00181   public static void loadDriverClass(String driverClassName)
00182       throws ClassNotFoundException
00183   {
00184     if (!defaultDrivers.contains(driverClassName))
00185     {
00186       if (logger.isDebugEnabled())
00187       {
00188         logger.debug("we are using default classloader and driverClassName ="
00189             + driverClassName);
00190       }
00191       Class.forName(driverClassName);
00192       if (logger.isDebugEnabled())
00193         logger.debug(Translate.get("backend.driver.loaded", driverClassName));
00194       // the driver was successfully loaded
00195       defaultDrivers.add(driverClassName);
00196     }
00197   }
00198 
00199   /**
00200    * convert a path into an absolute path if the path is already an absolute
00201    * path, it is just returned otherwise a relative path is considered to be
00202    * relative to the drivers directory
00203    * 
00204    * @param pathName the relativ or absolute path
00205    * @return the converted path
00206    * @throws IOException if the converted path does not exist
00207    */
00208   public static File convertToAbsolutePath(String pathName) throws IOException
00209   {
00210     File dir = null;
00211 
00212     if (pathName != null)
00213     {
00214       File path = new File(pathName);
00215       if (path.canRead())
00216         return path;
00217       else
00218         throw new IOException("Invalid path name " + pathName);
00219     }
00220     else
00221     {
00222       dir = getDriversDir();
00223     }
00224 
00225     if (!dir.canRead())
00226     {
00227       String msg = Translate.get("controller.driver.dir.not.found");
00228       logger.error(msg);
00229       throw new IOException(msg);
00230     }
00231 
00232     return dir;
00233   }
00234 
00235   private static File getDriversDir() throws IOException
00236   {
00237     URL url = Controller.class
00238         .getResource(ControllerConstants.C_JDBC_DRIVER_JAR_FILE);
00239     File driversDir = new File(url.getFile()).getParentFile();
00240 
00241     if (!driversDir.exists())
00242     {
00243       String msg = Translate.get("controller.driver.dir.not.found");
00244       logger.error(msg);
00245       throw new IOException(msg);
00246     }
00247     return driversDir;
00248   }
00249 
00250   private static Connection getConnectionForDriver(String url, String user,
00251       String password, Driver driver) throws SQLException
00252   {
00253     java.util.Properties info = new java.util.Properties();
00254     if (user != null)
00255     {
00256       info.put("user", user);
00257     }
00258     if (password != null)
00259     {
00260       info.put("password", password);
00261     }
00262 
00263     return driver.connect(url, info);
00264   }
00265 
00266   private static Driver loadDriver(File path, String driverClassName)
00267       throws ClassNotFoundException, InstantiationException,
00268       IllegalAccessException
00269   {
00270     ClassLoader loader = new DriverClassLoader(null, path);
00271 
00272     // load java.sql.DriverManager with the new classloader
00273     // Driver instances register with the DriverManager and we want the new
00274     // Driver to register with its own DriverManager
00275     // Otherwise the new Driver would register with the default DriverManager
00276     // and possibly overwrite an other driver with the same name
00277     Class.forName(java.sql.DriverManager.class.getName(), true, loader);
00278 
00279     // load class
00280     Class driverClass = Class.forName(driverClassName, true, loader);
00281 
00282     if (logger.isDebugEnabled())
00283       logger.debug(Translate.get("backend.driver.loaded", driverClassName));
00284 
00285     // get an instance of the class and return it
00286     return (Driver) driverClass.newInstance();
00287 
00288   }
00289 
00290 }

Generated on Mon Apr 11 22:01:31 2005 for C-JDBC by  doxygen 1.3.9.1