Save This Page
Home » apache-harmony-6.0-src-r917296-snapshot » java » sql » [javadoc | source]
    1   /* 
    2    * Licensed to the Apache Software Foundation (ASF) under one or more
    3    * contributor license agreements.  See the NOTICE file distributed with
    4    * this work for additional information regarding copyright ownership.
    5    * The ASF licenses this file to You under the Apache License, Version 2.0
    6    * (the "License"); you may not use this file except in compliance with
    7    * the License.  You may obtain a copy of the License at
    8    * 
    9    *     http://www.apache.org/licenses/LICENSE-2.0
   10    * 
   11    * Unless required by applicable law or agreed to in writing, software
   12    * distributed under the License is distributed on an "AS IS" BASIS,
   13    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   14    * See the License for the specific language governing permissions and
   15    * limitations under the License.
   16    */
   17   
   18   package java.sql;
   19   
   20   import java.util.ArrayList;
   21   import java.util.List;
   22   import java.util.Properties;
   23   import java.util.Enumeration;
   24   import java.util.Iterator;
   25   import java.io.PrintStream;
   26   import java.io.PrintWriter;
   27   import java.util.Vector;
   28   import java.security.AccessController;
   29   import org.apache.harmony.luni.util.PriviAction;
   30   import org.apache.harmony.sql.internal.nls.Messages;
   31   import org.apache.harmony.kernel.vm.VM;
   32   
   33   /**
   34    * Provides facilities for managing JDBC drivers.
   35    * <p>
   36    * The {@code DriverManager} class loads JDBC drivers during its initialization,
   37    * from the list of drivers referenced by the system property {@code
   38    * "jdbc.drivers"}.
   39    */
   40   public class DriverManager {
   41   
   42       /*
   43        * Facilities for logging. The Print Stream is deprecated but is maintained
   44        * here for compatibility.
   45        */
   46       private static PrintStream thePrintStream;
   47   
   48       private static PrintWriter thePrintWriter;
   49   
   50       // Login timeout value - by default set to 0 -> "wait forever"
   51       private static int loginTimeout = 0;
   52   
   53       /*
   54        * Set to hold Registered Drivers - initial capacity 10 drivers (will expand
   55        * automatically if necessary.
   56        */
   57       private static final List<Driver> theDrivers = new ArrayList<Driver>(10);
   58   
   59       // Permission for setting log
   60       private static final SQLPermission logPermission = new SQLPermission(
   61               "setLog"); //$NON-NLS-1$
   62   
   63       /*
   64        * Load drivers on initialization
   65        */
   66       static {
   67           loadInitialDrivers();
   68       }
   69   
   70       /*
   71        * Loads the set of JDBC drivers defined by the Property "jdbc.drivers" if
   72        * it is defined.
   73        */
   74       private static void loadInitialDrivers() {
   75           String theDriverList = AccessController
   76                   .doPrivileged(new PriviAction<String>("jdbc.drivers", null)); //$NON-NLS-1$
   77   
   78           if (theDriverList == null) {
   79               return;
   80           }
   81   
   82           /*
   83            * Get the names of the drivers as an array of Strings from the system
   84            * property by splitting the property at the separator character ':'
   85            */
   86           String[] theDriverNames = theDriverList.split(":"); //$NON-NLS-1$
   87   
   88           for (String element : theDriverNames) {
   89               try {
   90                   // Load the driver class
   91                   Class
   92                           .forName(element, true, ClassLoader
   93                                   .getSystemClassLoader());
   94               } catch (Throwable t) {
   95                   // Ignored
   96               }
   97           }
   98       }
   99   
  100       /*
  101        * A private constructor to prevent allocation
  102        */
  103       private DriverManager() {
  104           super();
  105       }
  106   
  107       /**
  108        * Removes a driver from the {@code DriverManager}'s registered driver list.
  109        * This will only succeed when the caller's class loader loaded the driver
  110        * that is to be removed. If the driver was loaded by a different class
  111        * loader, the removal of the driver fails silently.
  112        * <p>
  113        * If the removal succeeds, the {@code DriverManager} will not use this
  114        * driver in the future when asked to get a {@code Connection}.
  115        *
  116        * @param driver
  117        *            the JDBC driver to remove.
  118        * @throws SQLException
  119        *             if there is a problem interfering with accessing the
  120        *             database.
  121        */
  122       public static void deregisterDriver(Driver driver) throws SQLException {
  123           if (driver == null) {
  124               return;
  125           }
  126           ClassLoader callerClassLoader = VM.callerClassLoader();
  127   
  128           if (!DriverManager.isClassFromClassLoader(driver, callerClassLoader)) {
  129               // sql.1=DriverManager: calling class not authorized to deregister
  130               // JDBC driver
  131               throw new SecurityException(Messages.getString("sql.1")); //$NON-NLS-1$
  132           } // end if
  133           synchronized (theDrivers) {
  134               theDrivers.remove(driver);
  135           }
  136       }
  137   
  138       /**
  139        * Attempts to establish a connection to the given database URL.
  140        * 
  141        * @param url
  142        *            a URL string representing the database target to connect with.
  143        * @return a {@code Connection} to the database identified by the URL.
  144        *         {@code null} if no connection can be established.
  145        * @throws SQLException
  146        *             if there is an error while attempting to connect to the
  147        *             database identified by the URL.
  148        */
  149       public static Connection getConnection(String url) throws SQLException {
  150           return getConnection(url, new Properties());
  151       }
  152   
  153       /**
  154        * Attempts to establish a connection to the given database URL.
  155        * 
  156        * @param url
  157        *            a URL string representing the database target to connect with
  158        * @param info
  159        *            a set of properties to use as arguments to set up the
  160        *            connection. Properties are arbitrary string/value pairs.
  161        *            Normally, at least the properties {@code "user"} and {@code
  162        *            "password"} should be passed, with appropriate settings for
  163        *            the user ID and its corresponding password to get access to
  164        *            the corresponding database.
  165        * @return a {@code Connection} to the database identified by the URL.
  166        *         {@code null} if no connection can be established.
  167        * @throws SQLException
  168        *             if there is an error while attempting to connect to the
  169        *             database identified by the URL.
  170        */
  171       public static Connection getConnection(String url, Properties info)
  172               throws SQLException {
  173           // 08 - connection exception
  174           // 001 - SQL-client unable to establish SQL-connection
  175           String sqlState = "08001"; //$NON-NLS-1$
  176           if (url == null) {
  177               // sql.5=The url cannot be null
  178               throw new SQLException(Messages.getString("sql.5"), sqlState); //$NON-NLS-1$
  179           }
  180           synchronized (theDrivers) {
  181               /*
  182                * Loop over the drivers in the DriverSet checking to see if one can
  183                * open a connection to the supplied URL - return the first
  184                * connection which is returned
  185                */
  186               for (Driver theDriver : theDrivers) {
  187                   Connection theConnection = theDriver.connect(url, info);
  188                   if (theConnection != null) {
  189                       return theConnection;
  190                   }
  191               }
  192           }
  193           // If we get here, none of the drivers are able to resolve the URL
  194           // sql.6=No suitable driver
  195           throw new SQLException(Messages.getString("sql.6"), sqlState); //$NON-NLS-1$ 
  196       }
  197   
  198       /**
  199        * Attempts to establish a connection to the given database URL.
  200        * 
  201        * @param url
  202        *            a URL string representing the database target to connect with.
  203        * @param user
  204        *            a user ID used to login to the database.
  205        * @param password
  206        *            a password for the user ID to login to the database.
  207        * @return a {@code Connection} to the database identified by the URL.
  208        *         {@code null} if no connection can be established.
  209        * @throws SQLException
  210        *             if there is an error while attempting to connect to the
  211        *             database identified by the URL.
  212        */
  213       public static Connection getConnection(String url, String user,
  214               String password) throws SQLException {
  215           Properties theProperties = new Properties();
  216           if (null != user) {
  217               theProperties.setProperty("user", user); //$NON-NLS-1$
  218           }
  219           if (null != password) {
  220               theProperties.setProperty("password", password); //$NON-NLS-1$
  221           }
  222           return getConnection(url, theProperties);
  223       }
  224   
  225       /**
  226        * Tries to find a driver that can interpret the supplied URL.
  227        * 
  228        * @param url
  229        *            the URL of a database.
  230        * @return a {@code Driver} that matches the provided URL. {@code null} if
  231        *         no {@code Driver} understands the URL
  232        * @throws SQLException
  233        *             if there is any kind of problem accessing the database.
  234        */
  235       public static Driver getDriver(String url) throws SQLException {
  236           ClassLoader callerClassLoader = VM.callerClassLoader();
  237   
  238           synchronized (theDrivers) {
  239               /*
  240                * Loop over the drivers in the DriverSet checking to see if one
  241                * does understand the supplied URL - return the first driver which
  242                * does understand the URL
  243                */
  244               Iterator<Driver> theIterator = theDrivers.iterator();
  245               while (theIterator.hasNext()) {
  246                   Driver theDriver = theIterator.next();
  247                   if (theDriver.acceptsURL(url)
  248                           && DriverManager.isClassFromClassLoader(theDriver,
  249                                   callerClassLoader)) {
  250                       return theDriver;
  251                   }
  252               }
  253           }
  254           // If no drivers understand the URL, throw an SQLException
  255           // sql.6=No suitable driver
  256           // SQLState: 08 - connection exception
  257           // 001 - SQL-client unable to establish SQL-connection
  258           throw new SQLException(Messages.getString("sql.6"), "08001"); //$NON-NLS-1$ //$NON-NLS-2$
  259       }
  260   
  261       /**
  262        * Returns an {@code Enumeration} that contains all of the loaded JDBC
  263        * drivers that the current caller can access.
  264        * 
  265        * @return An {@code Enumeration} containing all the currently loaded JDBC
  266        *         {@code Drivers}.
  267        */
  268       public static Enumeration<Driver> getDrivers() {
  269           ClassLoader callerClassLoader = VM.callerClassLoader();
  270           /*
  271            * Synchronize to avoid clashes with additions and removals of drivers
  272            * in the DriverSet
  273            */
  274           synchronized (theDrivers) {
  275               /*
  276                * Create the Enumeration by building a Vector from the elements of
  277                * the DriverSet
  278                */
  279               Vector<Driver> theVector = new Vector<Driver>();
  280               Iterator<Driver> theIterator = theDrivers.iterator();
  281               while (theIterator.hasNext()) {
  282                   Driver theDriver = theIterator.next();
  283                   if (DriverManager.isClassFromClassLoader(theDriver,
  284                           callerClassLoader)) {
  285                       theVector.add(theDriver);
  286                   }
  287               }
  288               return theVector.elements();
  289           }
  290       }
  291   
  292       /**
  293        * Returns the login timeout when connecting to a database in seconds.
  294        * 
  295        * @return the login timeout in seconds.
  296        */
  297       public static int getLoginTimeout() {
  298           return loginTimeout;
  299       }
  300   
  301       /**
  302        * Gets the log {@code PrintStream} used by the {@code DriverManager} and
  303        * all the JDBC Drivers.
  304        *
  305        * @deprecated use {@link #getLogWriter()} instead.
  306        * @return the {@code PrintStream} used for logging activities.
  307        */
  308       public static PrintStream getLogStream() {
  309           return thePrintStream;
  310       }
  311   
  312       /**
  313        * Retrieves the log writer.
  314        * 
  315        * @return A {@code PrintWriter} object used as the log writer. {@code null}
  316        *         if no log writer is set.
  317        */
  318       public static PrintWriter getLogWriter() {
  319           return thePrintWriter;
  320       }
  321   
  322       /**
  323        * Prints a message to the current JDBC log stream. This is either the
  324        * {@code PrintWriter} or (deprecated) the {@code PrintStream}, if set.
  325        * 
  326        * @param message
  327        *            the message to print to the JDBC log stream.
  328        */
  329       public static void println(String message) {
  330           if (thePrintWriter != null) {
  331               thePrintWriter.println(message);
  332               thePrintWriter.flush();
  333           } else if (thePrintStream != null) {
  334               thePrintStream.println(message);
  335               thePrintStream.flush();
  336           }
  337           /*
  338            * If neither the PrintWriter not the PrintStream are set, then silently
  339            * do nothing the message is not recorded and no exception is generated.
  340            */
  341           return;
  342       }
  343   
  344       /**
  345        * Registers a given JDBC driver with the {@code DriverManager}.
  346        * <p>
  347        * A newly loaded JDBC driver class should register itself with the
  348        * {@code DriverManager} by calling this method.
  349        *
  350        * @param driver
  351        *            the {@code Driver} to register with the {@code DriverManager}.
  352        * @throws SQLException
  353        *             if a database access error occurs.
  354        */
  355       public static void registerDriver(Driver driver) throws SQLException {
  356           if (driver == null) {
  357               throw new NullPointerException();
  358           }
  359           synchronized (theDrivers) {
  360               theDrivers.add(driver);
  361           }
  362       }
  363   
  364       /**
  365        * Sets the login timeout when connecting to a database in seconds.
  366        * 
  367        * @param seconds
  368        *            seconds until timeout. 0 indicates wait forever.
  369        */
  370       public static void setLoginTimeout(int seconds) {
  371           loginTimeout = seconds;
  372           return;
  373       }
  374   
  375       /**
  376        * Sets the print stream to use for logging data from the {@code
  377        * DriverManager} and the JDBC drivers.
  378        *
  379        * @deprecated Use {@link #setLogWriter} instead.
  380        * @param out
  381        *            the {@code PrintStream} to use for logging.
  382        */
  383       @Deprecated
  384       public static void setLogStream(PrintStream out) {
  385           checkLogSecurity();
  386           thePrintStream = out;
  387       }
  388   
  389       /**
  390        * Sets the {@code PrintWriter} that is used by all loaded drivers, and also
  391        * the {@code DriverManager}.
  392        * 
  393        * @param out
  394        *            the {@code PrintWriter} to be used.
  395        */
  396       public static void setLogWriter(PrintWriter out) {
  397           checkLogSecurity();
  398           thePrintWriter = out;
  399       }
  400   
  401       /*
  402        * Method which checks to see if setting a logging stream is allowed by the
  403        * Security manager
  404        */
  405       private static void checkLogSecurity() {
  406           SecurityManager securityManager = System.getSecurityManager();
  407           if (securityManager != null) {
  408               // Throws a SecurityException if setting the log is not permitted
  409               securityManager.checkPermission(logPermission);
  410           }
  411       }
  412   
  413       /**
  414        * Determines whether the supplied object was loaded by the given {@code ClassLoader}.
  415        * 
  416        * @param theObject
  417        *            the object to check.
  418        * @param theClassLoader
  419        *            the {@code ClassLoader}.
  420        * @return {@code true} if the Object does belong to the {@code ClassLoader}
  421        *         , {@code false} otherwise
  422        */
  423       private static boolean isClassFromClassLoader(Object theObject,
  424               ClassLoader theClassLoader) {
  425   
  426           if ((theObject == null) || (theClassLoader == null)) {
  427               return false;
  428           }
  429   
  430           Class<?> objectClass = theObject.getClass();
  431   
  432           try {
  433               Class<?> checkClass = Class.forName(objectClass.getName(), true,
  434                       theClassLoader);
  435               if (checkClass == objectClass) {
  436                   return true;
  437               }
  438           } catch (Throwable t) {
  439               // Empty
  440           }
  441           return false;
  442       }
  443   }

Save This Page
Home » apache-harmony-6.0-src-r917296-snapshot » java » sql » [javadoc | source]