Index: java/org/apache/tomcat/jdbc/pool/DataSourceProxy.java =================================================================== --- java/org/apache/tomcat/jdbc/pool/DataSourceProxy.java (revision 943434) +++ java/org/apache/tomcat/jdbc/pool/DataSourceProxy.java (working copy) @@ -390,6 +390,14 @@ public class DataSourceProxy implements PoolConfiguration { this.poolProperties.setValidationQuery(validationQuery); } + /** + * {@inheritDoc} + */ + @Override + public void setValidator(Validator validator) { + getPoolProperties().setValidator(validator); + } + /** * {@inheritDoc} */ @@ -818,6 +826,14 @@ public class DataSourceProxy implements PoolConfiguration { return getPoolProperties().getValidationQuery(); } + /** + * {@inheritDoc} + */ + @Override + public Validator getValidator() { + return getPoolProperties().getValidator(); + } + /** * {@inheritDoc} */ Index: java/org/apache/tomcat/jdbc/pool/PoolConfiguration.java =================================================================== --- java/org/apache/tomcat/jdbc/pool/PoolConfiguration.java (revision 943434) +++ java/org/apache/tomcat/jdbc/pool/PoolConfiguration.java (working copy) @@ -522,7 +522,19 @@ public interface PoolConfiguration { * @param validationQuery the query used for validation or null if no validation is performed */ public void setValidationQuery(String validationQuery); + + /** + * @return the optional validator object - may be null + */ + public Validator getValidator(); + /** + * Set an optional validator object which will be used in place of test queries. If set to + * null, standard validation will be used. + * + * @param validator the optional validator + */ + public void setValidator(Validator validator); /** * avoid excess validation, only run validation at most at this frequency - time in milliseconds. Index: java/org/apache/tomcat/jdbc/pool/PoolProperties.java =================================================================== --- java/org/apache/tomcat/jdbc/pool/PoolProperties.java (revision 943434) +++ java/org/apache/tomcat/jdbc/pool/PoolProperties.java (working copy) @@ -51,6 +51,7 @@ public class PoolProperties implements PoolConfiguration { protected int minIdle = initialSize; protected int maxWait = 30000; protected String validationQuery; + protected Validator validator; protected boolean testOnBorrow = false; protected boolean testOnReturn = false; protected boolean testWhileIdle = false; @@ -338,6 +339,14 @@ public class PoolProperties implements PoolConfiguration { return validationQuery; } + /** + * {@inheritDoc} + */ + @Override + public Validator getValidator() { + return validator; + } + /** * {@inheritDoc} */ @@ -631,6 +640,14 @@ public class PoolProperties implements PoolConfiguration { this.validationQuery = validationQuery; } + /** + * {@inheritDoc} + */ + @Override + public void setValidator(Validator validator) { + this.validator = validator; + } + /** * {@inheritDoc} */ Index: java/org/apache/tomcat/jdbc/pool/PooledConnection.java =================================================================== --- java/org/apache/tomcat/jdbc/pool/PooledConnection.java (revision 943434) +++ java/org/apache/tomcat/jdbc/pool/PooledConnection.java (working copy) @@ -362,21 +362,29 @@ public class PooledConnection { return true; } - String query = (VALIDATE_INIT==validateAction && (poolProperties.getInitSQL()!=null))?poolProperties.getInitSQL():sql; - - if (query==null) query = poolProperties.getValidationQuery(); - - if (query == null) { - //no validation possible - return true; - } + //Don't bother validating if already have recently enough long now = System.currentTimeMillis(); - if (this.poolProperties.getValidationInterval() > 0 && - (validateAction!=VALIDATE_INIT) && + if (validateAction!=VALIDATE_INIT && + poolProperties.getValidationInterval() > 0 && (now - this.lastValidated) < - this.poolProperties.getValidationInterval()) { + poolProperties.getValidationInterval()) { return true; } + + if (poolProperties.getValidator() != null) { + return poolProperties.getValidator().validate(connection, validateAction); + } + + String query = sql; + + if (validateAction == VALIDATE_INIT && poolProperties.getInitSQL() != null) { + query = poolProperties.getInitSQL(); + } + + if (query == null) { + query = poolProperties.getValidationQuery(); + } + Statement stmt = null; try { stmt = connection.createStatement(); Index: java/org/apache/tomcat/jdbc/pool/Validator.java new file mode 100644 =================================================================== --- /dev/null (revision 943434) +++ java/org/apache/tomcat/jdbc/pool/Validator.java (working copy) @@ -0,0 +1,37 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tomcat.jdbc.pool; + +import java.sql.Connection; + +/** + * Interface to be implemented by custom validator classes. + * + * @author mpassell + */ +public interface Validator { + /** + * Validate a connection and return a boolean to indicate if it's valid. + * + * @param connection the Connection object to test + * @param validateAction the action used. One of {@link PooledConnection#VALIDATE_BORROW}, + * {@link PooledConnection#VALIDATE_IDLE}, {@link PooledConnection#VALIDATE_INIT} or + * {@link PooledConnection#VALIDATE_RETURN} + * @return true if the connection is valid + */ + public boolean validate(Connection connection, int validateAction); +} Index: java/org/apache/tomcat/jdbc/pool/jmx/ConnectionPool.java =================================================================== --- java/org/apache/tomcat/jdbc/pool/jmx/ConnectionPool.java (revision 943434) +++ java/org/apache/tomcat/jdbc/pool/jmx/ConnectionPool.java (working copy) @@ -29,6 +29,7 @@ import javax.management.NotificationListener; import org.apache.juli.logging.Log; import org.apache.juli.logging.LogFactory; import org.apache.tomcat.jdbc.pool.PoolConfiguration; +import org.apache.tomcat.jdbc.pool.Validator; import org.apache.tomcat.jdbc.pool.PoolProperties.InterceptorDefinition; public class ConnectionPool extends NotificationBroadcasterSupport implements ConnectionPoolMBean { @@ -278,6 +279,14 @@ public class ConnectionPool extends NotificationBroadcasterSupport implements Co return getPoolProperties().getValidationQuery(); } + /** + * {@inheritDoc} + */ + @Override + public Validator getValidator() { + return getPoolProperties().getValidator(); + } + public boolean isAccessToUnderlyingConnectionAllowed() { return getPoolProperties().isAccessToUnderlyingConnectionAllowed(); } @@ -557,48 +566,56 @@ public class ConnectionPool extends NotificationBroadcasterSupport implements Co } /** - * {@inheritDoc} - */ - @Override - public int getSuspectTimeout() { - return getPoolProperties().getSuspectTimeout(); - } - - /** - * {@inheritDoc} - */ - @Override - public void setSuspectTimeout(int seconds) { - //no op - } - - /** - * {@inheritDoc} - */ - public void setDataSource(Object ds) { - getPoolProperties().setDataSource(ds); - } - - /** - * {@inheritDoc} - */ - public Object getDataSource() { - return getPoolProperties().getDataSource(); - } - - - /** - * {@inheritDoc} - */ - public void setDataSourceJNDI(String jndiDS) { - //noop - } - - /** - * {@inheritDoc} - */ - public String getDataSourceJNDI() { - return getPoolProperties().getDataSourceJNDI(); - } + * {@inheritDoc} + */ + @Override + public void setValidator(Validator validator) { + getPoolProperties().setValidator(validator); + } + + /** + * {@inheritDoc} + */ + @Override + public int getSuspectTimeout() { + return getPoolProperties().getSuspectTimeout(); + } + + /** + * {@inheritDoc} + */ + @Override + public void setSuspectTimeout(int seconds) { + //no op + } + + /** + * {@inheritDoc} + */ + public void setDataSource(Object ds) { + getPoolProperties().setDataSource(ds); + } + + /** + * {@inheritDoc} + */ + public Object getDataSource() { + return getPoolProperties().getDataSource(); + } + + + /** + * {@inheritDoc} + */ + public void setDataSourceJNDI(String jndiDS) { + //noop + } + + /** + * {@inheritDoc} + */ + public String getDataSourceJNDI() { + return getPoolProperties().getDataSourceJNDI(); + } }