Index: jackrabbit-core/pom.xml
===================================================================
--- jackrabbit-core/pom.xml (revision 774850)
+++ jackrabbit-core/pom.xml (working copy)
@@ -154,6 +154,11 @@
commons-io
+ commons-dbcp
+ commons-dbcp
+ 1.2.2
+
+
javax.jcr
jcr
Index: jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/util/ConnectionFactory.java
===================================================================
--- jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/util/ConnectionFactory.java (revision 774850)
+++ jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/util/ConnectionFactory.java (working copy)
@@ -17,7 +17,6 @@
package org.apache.jackrabbit.core.persistence.bundle.util;
import java.sql.Connection;
-import java.sql.DriverManager;
import java.sql.SQLException;
import javax.jcr.RepositoryException;
@@ -25,6 +24,8 @@
import javax.naming.NamingException;
import javax.sql.DataSource;
+import org.apache.commons.dbcp.BasicDataSource;
+
/**
* A factory for new database connections.
* Supported are regular JDBC drivers, as well as
@@ -53,43 +54,115 @@
* @throws RepositoryException if the driver could not be loaded
* @throws SQLException if the connection could not be established
*/
- public static Connection getConnection(String driver, String url,
- String user, String password) throws RepositoryException,
- SQLException {
- if (driver != null && driver.length() > 0) {
+ @SuppressWarnings("unchecked")
+ public static Connection getConnection(
+ String driver, String url, String user, String password)
+ throws RepositoryException, SQLException {
+ DataSource database;
+
+ Class> driverClass = getDriverClass(driver);
+ if (driverClass != null
+ && Context.class.isAssignableFrom(driverClass)) {
+ database = getJndiDataSource((Class) driverClass, url);
+ } else {
+ database = getDriverDataSource(driverClass, url);
+ }
+
+ if (user == null && password == null) {
+ return database.getConnection();
+ } else {
+ return database.getConnection(user, password);
+ }
+ }
+
+ /**
+ * Loads and returns the given JDBC driver (or JNDI context) class.
+ * Returns null if a class name is not given.
+ *
+ * @param driver driver class name
+ * @return driver class, or null
+ * @throws RepositoryException if the class can not be loaded
+ */
+ private static Class> getDriverClass(String driver)
+ throws RepositoryException {
+ try {
+ if (driver != null && driver.length() > 0) {
+ return Class.forName(driver);
+ } else {
+ return null;
+ }
+ } catch (ClassNotFoundException e) {
+ throw new RepositoryException(
+ "Could not load JDBC driver class " + driver, e);
+ }
+ }
+
+ /**
+ * Returns the JDBC {@link DataSource} bound to the given name in
+ * the JNDI {@link Context} identified by the given class.
+ *
+ * @param contextClass class that is instantiated to get the JNDI context
+ * @param name name of the DataSource within the JNDI context
+ * @return the DataSource bound in JNDI
+ * @throws RepositoryException if the JNDI context can not be accessed,
+ * or if the named DataSource is not found
+ */
+ private static DataSource getJndiDataSource(
+ Class contextClass, String name)
+ throws RepositoryException {
+ try {
+ Object object = contextClass.newInstance().lookup(name);
+ if (object instanceof DataSource) {
+ return (DataSource) object;
+ } else {
+ throw new RepositoryException(
+ "Object " + object + " with JNDI name "
+ + name + " is not a JDBC DataSource");
+ }
+ } catch (InstantiationException e) {
+ throw new RepositoryException(
+ "Invalid JNDI context: " + contextClass.getName(), e);
+ } catch (IllegalAccessException e) {
+ throw new RepositoryException(
+ "Invalid JNDI context: " + contextClass.getName(), e);
+ } catch (NamingException e) {
+ throw new RepositoryException(
+ "JNDI name not found: " + name, e);
+ }
+ }
+
+ /**
+ * Creates and returns a pooling JDBC {@link DataSource} for accessing
+ * the database identified by the given driver class and JDBC
+ * connection URL. The driver class can be null if
+ * a specific driver has not been configured.
+ *
+ * @param driverClass the JDBC driver class, or null
+ * @param url the JDBC connection URL
+ * @return pooling DataSource for accessing the specified database
+ */
+ private static DataSource getDriverDataSource(
+ Class> driverClass, String url) {
+ BasicDataSource database = new BasicDataSource();
+
+ if (driverClass != null) {
try {
- Class< ? > d = Class.forName(driver);
- if (javax.naming.Context.class.isAssignableFrom(d)) {
- // JNDI context
- Context context = (Context) d.newInstance();
- DataSource ds = (DataSource) context.lookup(url);
- if (user == null && password == null) {
- return ds.getConnection();
- } else {
- return ds.getConnection(user, password);
- }
- } else {
- try {
- // Workaround for Apache Derby:
- // The JDBC specification recommends the Class.forName method without the .newInstance() method call,
- // but it is required after a Derby 'shutdown'.
- d.newInstance();
- } catch (Throwable e) {
- // Ignore exceptions
- // There's no requirement that a JDBC driver class has a public default constructor
- }
- }
- } catch (ClassNotFoundException e) {
- throw new RepositoryException("Could not load class " + driver, e);
- } catch (InstantiationException e) {
- throw new RepositoryException("Could not instantiate context " + driver, e);
- } catch (IllegalAccessException e) {
- throw new RepositoryException("Could not instantiate context " + driver, e);
- } catch (NamingException e) {
- throw new RepositoryException("Naming exception using " + driver + " url: " + url, e);
+ // Workaround for Apache Derby:
+ // The JDBC specification recommends the Class.forName
+ // method without the .newInstance() method call,
+ // but it is required after a Derby 'shutdown'
+ driverClass.newInstance();
+ } catch (Throwable e) {
+ // Ignore exceptions as there's no requirement for
+ // a JDBC driver class to have a public default constructor
}
+
+ database.setDriverClassName(driverClass.getName());
}
- return DriverManager.getConnection(url, user, password);
+
+ database.setUrl(url);
+
+ return database;
}
}