protected final static String PROP_TESTWHILEIDLE = "testWhileIdle";
protected final static String PROP_TESTONCONNECT = "testOnConnect";
protected final static String PROP_VALIDATIONQUERY = "validationQuery";
+ protected final static String PROP_VALIDATOR_CLASS_NAME = "validatorClassName";
protected final static String PROP_TIMEBETWEENEVICTIONRUNSMILLIS = "timeBetweenEvictionRunsMillis";
protected final static String PROP_NUMTESTSPEREVICTIONRUN = "numTestsPerEvictionRun";
if (value != null) {
poolProperties.setValidationQuery(value);
}
+
+ value = properties.getProperty(PROP_VALIDATOR_CLASS_NAME);
+ if (value != null) {
+ poolProperties.setValidatorClassName(value);
+ }
value = properties.getProperty(PROP_VALIDATIONINTERVAL);
if (value != null) {
this.poolProperties.setValidationQuery(validationQuery);
}
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void setValidatorClassName(String className) {
+ this.poolProperties.setValidatorClassName(className);
+ }
+
/**
* {@inheritDoc}
*/
return getPoolProperties().getValidationQuery();
}
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String getValidatorClassName() {
+ return getPoolProperties().getValidatorClassName();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Validator getValidator() {
+ return getPoolProperties().getValidator();
+ }
+
/**
* {@inheritDoc}
*/
* @param validationQuery the query used for validation or null if no validation is performed
*/
public void setValidationQuery(String validationQuery);
-
/**
+ * Return the name of the optional validator class - may be null.
+ *
+ * @return the name of the optional validator class - may be null
+ */
+ public String getValidatorClassName();
+
+ /**
+ * Set the name for an optional validator class which will be used in place of test queries. If set to
+ * null, standard validation will be used.
+ *
+ * @param className the name of the optional validator class
+ */
+ public void setValidatorClassName(String className);
+
+ /**
+ * @return the optional validator object - may be null
+ */
+ public Validator getValidator();
+
+ /**
* avoid excess validation, only run validation at most at this frequency - time in milliseconds.
* If a connection is due for validation, but has been validated previously
* within this interval, it will not be validated again.
protected int minIdle = initialSize;
protected int maxWait = 30000;
protected String validationQuery;
+ protected String validatorClassName;
+ protected Validator validator;
protected boolean testOnBorrow = false;
protected boolean testOnReturn = false;
protected boolean testWhileIdle = false;
return validationQuery;
}
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String getValidatorClassName() {
+ return validatorClassName;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Validator getValidator() {
+ return validator;
+ }
+
/**
* {@inheritDoc}
*/
this.validationQuery = validationQuery;
}
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void setValidatorClassName(String className) {
+ this.validatorClassName = className;
+
+ validator = null;
+
+ if (className == null) {
+ return;
+ }
+
+ try {
+ Class<Validator> validatorClass = (Class<Validator>)Class.forName(className);
+ validator = validatorClass.newInstance();
+ } catch (ClassNotFoundException e) {
+ log.warn("The class "+className+" cannot be found.", e);
+ } catch (ClassCastException e) {
+ log.warn("The class "+className+" does not implement the Validator interface.", e);
+ } catch (InstantiationException e) {
+ log.warn("An object of class "+className+" cannot be instantiated. Make sure that "+
+ "it includes an implicit or explicit no-arg constructor.", e);
+ } catch (IllegalAccessException e) {
+ log.warn("The class "+className+" or its no-arg constructor are inaccessible.", e);
+ }
+ }
+
/**
* {@inheritDoc}
*/
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();
--- /dev/null
+/*
+ * 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);
+}
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 {
return getPoolProperties().getValidationQuery();
}
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String getValidatorClassName() {
+ return getPoolProperties().getValidatorClassName();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Validator getValidator() {
+ return getPoolProperties().getValidator();
+ }
+
public boolean isAccessToUnderlyingConnectionAllowed() {
return getPoolProperties().isAccessToUnderlyingConnectionAllowed();
}
}
/**
- * {@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 setValidatorClassName(String className) {
+ getPoolProperties().setValidatorClassName(className);
+ }
+
+ /**
+ * {@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();
+ }
}