You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by ma...@apache.org on 2009/09/10 10:35:34 UTC
svn commit: r813305 - in /jackrabbit/sandbox/JCR-1456/jackrabbit-core/src:
main/java/org/apache/jackrabbit/core/config/
main/java/org/apache/jackrabbit/core/util/db/
test/java/org/apache/jackrabbit/core/config/
test/java/org/apache/jackrabbit/core/util...
Author: martijnh
Date: Thu Sep 10 08:35:34 2009
New Revision: 813305
URL: http://svn.apache.org/viewvc?rev=813305&view=rev
Log:
JCR 1456 Database connection pooling
* Improved unit tests
Modified:
jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/DataSourceConfig.java
jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/util/db/ConnectionFactory.java
jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/config/DataSourceConfigTest.java
jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/util/db/ConnectionFactoryTest.java
Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/DataSourceConfig.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/DataSourceConfig.java?rev=813305&r1=813304&r2=813305&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/DataSourceConfig.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/DataSourceConfig.java Thu Sep 10 08:35:34 2009
@@ -113,7 +113,7 @@
this.dbType = (String) props.getProperty(DB_TYPE);
this.validationQuery = (String) props.getProperty(VALIDATION_QUERY);
try {
- this.maxPoolSize = Integer.parseInt((String) props.getProperty(MAX_POOL_SIZE, "0"));
+ this.maxPoolSize = Integer.parseInt((String) props.getProperty(MAX_POOL_SIZE, "-1"));
} catch (NumberFormatException e) {
throw new ConfigurationException("failed to parse " + MAX_POOL_SIZE
+ " property for DataSource " + logicalName);
Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/util/db/ConnectionFactory.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/util/db/ConnectionFactory.java?rev=813305&r1=813304&r2=813305&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/util/db/ConnectionFactory.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/util/db/ConnectionFactory.java Thu Sep 10 08:35:34 2009
@@ -16,7 +16,6 @@
*/
package org.apache.jackrabbit.core.util.db;
-import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.HashMap;
@@ -31,6 +30,8 @@
import org.apache.commons.dbcp.DelegatingConnection;
import org.apache.jackrabbit.core.config.DataSourceConfig;
import org.apache.jackrabbit.core.config.DataSourceConfig.DataSourceDefinition;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
* A factory for new database connections.
@@ -42,6 +43,8 @@
*/
public class ConnectionFactory {
+ private static Logger log = LoggerFactory.getLogger(ConnectionFactory.class);
+
/**
* The lock to protect the registries.
*/
@@ -82,7 +85,9 @@
if (def.getMaxPoolSize() > 0) {
bds.setMaxActive(def.getMaxPoolSize());
}
- bds.setValidationQuery(def.getValidationQuery());
+ if (def.getValidationQuery() != null && !"".equals(def.getValidationQuery().trim())) {
+ bds.setValidationQuery(def.getValidationQuery());
+ }
nameToDataSource.put(def.getLogicalName(), bds);
nameToDataSourceDef.put(def.getLogicalName(), def);
}
@@ -152,20 +157,15 @@
*
* This method actually assumes that we are using commons DBCP 1.2.2.
*
- * @param con the commons-DBCP {@code PoolableConnection} to unwrap
+ * @param con the commons-DBCP {@code DelegatingConnection} to unwrap
* @return the unwrapped connection
*/
public static Connection unwrap(Connection con) throws SQLException {
- try {
- Field f = DelegatingConnection.class.getDeclaredField("_conn");
- f.setAccessible(true);
- return (Connection) f.get(con);
- } catch (IllegalArgumentException e) {
- throw new SQLException("failed to unwrap connection: " + e.getMessage());
- } catch (NoSuchFieldException e) {
- throw new SQLException("failed to unwrap connection: " + e.getMessage());
- } catch (IllegalAccessException e) {
- throw new SQLException("failed to unwrap connection: " + e.getMessage());
+ if (con instanceof DelegatingConnection) {
+ return ((DelegatingConnection)con).getInnermostDelegate();
+ } else {
+ throw new SQLException("failed to unwrap connection of class " + con.getClass().getName() +
+ ", expected it to be a " + DelegatingConnection.class.getName());
}
}
@@ -264,7 +264,7 @@
*/
private static BasicDataSource getDriverDataSource(
Class<?> driverClass, String url, String user, String password) {
- BasicDataSource database = new BasicDataSource();
+ BasicDataSource ds = new BasicDataSource();
if (driverClass != null) {
try {
@@ -278,19 +278,33 @@
// a JDBC driver class to have a public default constructor
}
- database.setDriverClassName(driverClass.getName());
+ ds.setDriverClassName(driverClass.getName());
}
- database.setUrl(url);
- database.setUsername(user);
- database.setPassword(password);
- database.setDefaultAutoCommit(true);
- database.setTestOnBorrow(true);
- database.setMaxActive(10);
- // FIXME: we could pass the databaseType and derive a validation query from that
-// database.setValidationQuery("select 1");
-
- return database;
+ ds.setUrl(url);
+ ds.setUsername(user);
+ ds.setPassword(password);
+ ds.setDefaultAutoCommit(true);
+ ds.setTestOnBorrow(true);
+ ds.setMaxActive(-1); // unlimited
+ ds.setValidationQuery(guessValidationQuery(url));
+ ds.setAccessToUnderlyingConnectionAllowed(true);
+ ds.setPoolPreparedStatements(true);
+ ds.setMaxOpenPreparedStatements(-1); // unlimited
+ return ds;
}
+ private static String guessValidationQuery(String url) {
+ if (url.contains("derby")) {
+ return "values(1)";
+ } else if (url.contains("mysql")) {
+ return "select 1";
+ } else if (url.contains("sqlserver") || url.contains("jtds")) {
+ return "select 1";
+ } else if (url.contains("oracle")) {
+ return "select 'validationQuery' from dual";
+ }
+ log.warn("Failed to guess validation query for URL " + url);
+ return null;
+ }
}
Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/config/DataSourceConfigTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/config/DataSourceConfigTest.java?rev=813305&r1=813304&r2=813305&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/config/DataSourceConfigTest.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/config/DataSourceConfigTest.java Thu Sep 10 08:35:34 2009
@@ -60,7 +60,7 @@
assertNull(def.getUser());
assertNull(def.getPassword());
assertNull(def.getValidationQuery());
- assertEquals(0, def.getMaxPoolSize());
+ assertEquals(-1, def.getMaxPoolSize()); // unlimited
}
public void testMultipleDefs() throws ConfigurationException {
Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/util/db/ConnectionFactoryTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/util/db/ConnectionFactoryTest.java?rev=813305&r1=813304&r2=813305&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/util/db/ConnectionFactoryTest.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/util/db/ConnectionFactoryTest.java Thu Sep 10 08:35:34 2009
@@ -16,34 +16,136 @@
*/
package org.apache.jackrabbit.core.util.db;
+import java.sql.Connection;
+import java.util.Properties;
+
+import javax.jcr.RepositoryException;
import javax.sql.DataSource;
import junit.framework.TestCase;
+import org.apache.commons.dbcp.BasicDataSource;
+import org.apache.derby.iapi.jdbc.EngineConnection;
+import org.apache.jackrabbit.core.config.ConfigurationException;
+import org.apache.jackrabbit.core.config.DataSourceConfig;
+
/**
*
*/
public class ConnectionFactoryTest extends TestCase {
- private static final String DERBY_DRIVER = "org.apache.derby.jdbc.EmbeddedDriver";
+ private static final String DRIVER = "org.apache.derby.jdbc.EmbeddedDriver";
private static final String DERBY_URL = "jdbc:derby:target/connection-factory-test/db;create=true";
- public void testIdentity() throws Exception {
- DataSource ds1 = ConnectionFactory.getDataSource(DERBY_DRIVER, DERBY_URL, "user", "password");
- DataSource ds2 = ConnectionFactory.getDataSource(DERBY_DRIVER, DERBY_URL, "user", "password");
+ private static final String MYSQL_URL = "jdbc:mysql://localhost:3306/dbName?autoReconnect=true";
+
+ private static final String MSSQL_URL_1 = "jdbc:jtds:sqlserver://localhost:2433/dbName";
+
+ private static final String MSSQL_URL_2 = "jdbc:sqlserver://localhost:1433;databaseName=dbName";
+
+ private static final String ORACLE_URL = "jdbc:oracle:thin:@localhost:1521:xe";
+
+ @Override
+ public void setUp() {
+ System.setProperty("derby.stream.error.file", "target/derby-connectionfactorytest.log");
+ }
+
+ public void testGetDataSource_defaults_Derby() throws Exception {
+ DataSource ds1 = ConnectionFactory.getDataSource(DRIVER, DERBY_URL, "user", "password");
+ assertTrue(ds1 instanceof BasicDataSource);
+ BasicDataSource ds = (BasicDataSource) ds1;
+ assertEquals(-1, ds.getMaxActive());
+ assertEquals("values(1)", ds.getValidationQuery());
+ assertTrue(ds.getDefaultAutoCommit());
+ assertTrue(ds.getTestOnBorrow());
+ assertTrue(ds.isPoolPreparedStatements());
+ assertEquals(-1, ds.getMaxOpenPreparedStatements());
+ }
+
+ public void testGuessValidationQuery_MYSQL() throws Exception {
+ DataSource ds1 = ConnectionFactory.getDataSource(DRIVER, MYSQL_URL, "user", "password");
+ assertEquals("select 1", ((BasicDataSource) ds1).getValidationQuery());
+ }
+
+ public void testGuessValidationQuery_MSSQL() throws Exception {
+ DataSource ds1 = ConnectionFactory.getDataSource(DRIVER, MSSQL_URL_1, "user", "password");
+ assertEquals("select 1", ((BasicDataSource) ds1).getValidationQuery());
+ DataSource ds2 = ConnectionFactory.getDataSource(DRIVER, MSSQL_URL_2, "user", "password");
+ assertEquals("select 1", ((BasicDataSource) ds2).getValidationQuery());
+ }
+
+ public void testGuessValidationQuery_ORACLE() throws Exception {
+ DataSource ds1 = ConnectionFactory.getDataSource(DRIVER, ORACLE_URL, "user", "password");
+ assertEquals("select 'validationQuery' from dual", ((BasicDataSource) ds1).getValidationQuery());
+ }
+
+ public void testRegisterDataSources_defaultValues() throws Exception {
+ BasicDataSource ds = registerAndGet(DERBY_URL, "overwrite");
+ assertEquals(10, ds.getMaxActive());
+ assertEquals("overwrite", ds.getValidationQuery());
+ assertTrue(ds.getDefaultAutoCommit());
+ assertTrue(ds.getTestOnBorrow());
+ assertTrue(ds.isPoolPreparedStatements());
+ assertEquals(-1, ds.getMaxOpenPreparedStatements());
+ }
+
+ public void testRegisterDataSources_noValidationQuery() throws Exception {
+ BasicDataSource ds = registerAndGet(MYSQL_URL, "");
+ assertEquals("select 1", ds.getValidationQuery());
+ }
+
+ public void testGetDatabaseType() throws Exception {
+ String name = register(MYSQL_URL, "");
+ assertEquals("dbType", ConnectionFactory.getDataBaseType(name));
+ }
+
+ public void testGetDataSource_identity() throws Exception {
+ DataSource ds1 = ConnectionFactory.getDataSource(DRIVER, DERBY_URL, "user", "password");
+ DataSource ds2 = ConnectionFactory.getDataSource(DRIVER, DERBY_URL, "user", "password");
assertSame(ds1, ds2);
}
- public void testIdentity_differentPasswords() throws Exception {
- DataSource ds1 = ConnectionFactory.getDataSource(DERBY_DRIVER, DERBY_URL, "user", "password");
- DataSource ds2 = ConnectionFactory.getDataSource(DERBY_DRIVER, DERBY_URL, "user", "password2");
+ public void testGetDataSource_identity_differentPasswords() throws Exception {
+ DataSource ds1 = ConnectionFactory.getDataSource(DRIVER, DERBY_URL, "user", "password");
+ DataSource ds2 = ConnectionFactory.getDataSource(DRIVER, DERBY_URL, "user", "password2");
assertSame(ds1, ds2);
}
- public void testNonIdentity() throws Exception {
- DataSource ds1 = ConnectionFactory.getDataSource(DERBY_DRIVER, DERBY_URL, "user", "password");
- DataSource ds2 = ConnectionFactory.getDataSource(DERBY_DRIVER, DERBY_URL, "user2", "password");
+ public void testGetDataSource_noIdentity() throws Exception {
+ DataSource ds1 = ConnectionFactory.getDataSource(DRIVER, DERBY_URL, "user", "password");
+ DataSource ds2 = ConnectionFactory.getDataSource(DRIVER, DERBY_URL, "user2", "password");
assertNotSame(ds1, ds2);
}
+
+ public void testUnwrap() throws Exception {
+ DataSource ds = ConnectionFactory.getDataSource(DRIVER, DERBY_URL, "user", "password");
+ Connection wrappedCon = ds.getConnection();
+ assertNotNull(wrappedCon);
+ Connection con = ConnectionFactory.unwrap(wrappedCon);
+ assertTrue(con instanceof EngineConnection);
+ }
+
+ private BasicDataSource registerAndGet(String url, String validationQuery) throws Exception {
+ final String name = register(url, validationQuery);
+ DataSource ds = ConnectionFactory.getDataSource(name);
+ assertTrue(ds instanceof BasicDataSource);
+ return (BasicDataSource) ds;
+ }
+
+ private String register(String url, String validationQuery) throws ConfigurationException,
+ RepositoryException {
+ final String name = "some random name to not interfere with integration tests...";
+ DataSourceConfig dsc = new DataSourceConfig();
+ Properties props = new Properties();
+ props.put(DataSourceConfig.LOGICAL_NAME, name);
+ props.put(DataSourceConfig.DRIVER, "org.apache.derby.jdbc.EmbeddedDriver");
+ props.put(DataSourceConfig.URL, url);
+ props.put(DataSourceConfig.DB_TYPE, "dbType");
+ props.put(DataSourceConfig.MAX_POOL_SIZE, "10");
+ props.put(DataSourceConfig.VALIDATION_QUERY, validationQuery);
+ dsc.addDataSourceDefinition(props);
+ ConnectionFactory.registerDataSources(dsc);
+ return name;
+ }
}