You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@aries.apache.org by gn...@apache.org on 2014/06/17 13:25:34 UTC
svn commit: r1603130 - in
/aries/trunk/transaction/transaction-jdbc/src/main/java/org/apache/aries/transaction/jdbc:
./ internal/
Author: gnodet
Date: Tue Jun 17 11:25:34 2014
New Revision: 1603130
URL: http://svn.apache.org/r1603130
Log:
[ARIES-1211] Add connection validation feature to jdbc
Added:
aries/trunk/transaction/transaction-jdbc/src/main/java/org/apache/aries/transaction/jdbc/internal/Reflections.java
aries/trunk/transaction/transaction-jdbc/src/main/java/org/apache/aries/transaction/jdbc/internal/ValidatingDelegatingManagedConnectionFactory.java
aries/trunk/transaction/transaction-jdbc/src/main/java/org/apache/aries/transaction/jdbc/internal/ValidatingGenericConnectionManager.java
Modified:
aries/trunk/transaction/transaction-jdbc/src/main/java/org/apache/aries/transaction/jdbc/RecoverableDataSource.java
aries/trunk/transaction/transaction-jdbc/src/main/java/org/apache/aries/transaction/jdbc/internal/ConnectionManagerFactory.java
aries/trunk/transaction/transaction-jdbc/src/main/java/org/apache/aries/transaction/jdbc/internal/ManagedDataSourceFactory.java
Modified: aries/trunk/transaction/transaction-jdbc/src/main/java/org/apache/aries/transaction/jdbc/RecoverableDataSource.java
URL: http://svn.apache.org/viewvc/aries/trunk/transaction/transaction-jdbc/src/main/java/org/apache/aries/transaction/jdbc/RecoverableDataSource.java?rev=1603130&r1=1603129&r2=1603130&view=diff
==============================================================================
--- aries/trunk/transaction/transaction-jdbc/src/main/java/org/apache/aries/transaction/jdbc/RecoverableDataSource.java (original)
+++ aries/trunk/transaction/transaction-jdbc/src/main/java/org/apache/aries/transaction/jdbc/RecoverableDataSource.java Tue Jun 17 11:25:34 2014
@@ -59,6 +59,9 @@ public class RecoverableDataSource imple
private int poolMaxSize = 10;
private int poolMinSize = 0;
private String transaction;
+ private boolean validateOnMatch = true;
+ private boolean backgroundValidation = false;
+ private int backgroundValidationMilliseconds = 600000;
private DataSource delegate;
@@ -152,6 +155,30 @@ public class RecoverableDataSource imple
this.poolMinSize = poolMinSize;
}
+ /**
+ * If validation on connection matching is enabled (defaults to true).
+ * @param validateOnMatch
+ */
+ public void setValidateOnMatch(boolean validateOnMatch) {
+ this.validateOnMatch = validateOnMatch;
+ }
+
+ /**
+ * If periodically background validation is enabled (defaults to false).
+ * @param backgroundValidation
+ */
+ public void setBackgroundValidation(boolean backgroundValidation) {
+ this.backgroundValidation = backgroundValidation;
+ }
+
+ /**
+ * Background validation period (defaults to 600000)
+ * @param backgroundValidationMilliseconds
+ */
+ public void setBackgroundValidationMilliseconds(int backgroundValidationMilliseconds) {
+ this.backgroundValidationMilliseconds = backgroundValidationMilliseconds;
+ }
+
/**
* Transaction support.
* Can be none, local or xa (defaults to xa).
@@ -194,6 +221,9 @@ public class RecoverableDataSource imple
cm.setPooling(pooling);
cm.setPoolMaxSize(poolMaxSize);
cm.setPoolMinSize(poolMinSize);
+ cm.setValidateOnMatch(validateOnMatch);
+ cm.setBackgroundValidation(backgroundValidation);
+ cm.setBackgroundValidationMilliseconds(backgroundValidationMilliseconds);
cm.setTransaction(transaction);
cm.init();
Modified: aries/trunk/transaction/transaction-jdbc/src/main/java/org/apache/aries/transaction/jdbc/internal/ConnectionManagerFactory.java
URL: http://svn.apache.org/viewvc/aries/trunk/transaction/transaction-jdbc/src/main/java/org/apache/aries/transaction/jdbc/internal/ConnectionManagerFactory.java?rev=1603130&r1=1603129&r2=1603130&view=diff
==============================================================================
--- aries/trunk/transaction/transaction-jdbc/src/main/java/org/apache/aries/transaction/jdbc/internal/ConnectionManagerFactory.java (original)
+++ aries/trunk/transaction/transaction-jdbc/src/main/java/org/apache/aries/transaction/jdbc/internal/ConnectionManagerFactory.java Tue Jun 17 11:25:34 2014
@@ -32,6 +32,7 @@ import org.apache.geronimo.connector.out
import org.apache.geronimo.connector.outbound.connectiontracking.ConnectionTrackingCoordinator;
import org.apache.geronimo.connector.outbound.connectiontracking.GeronimoTransactionListener;
import org.apache.geronimo.transaction.manager.TransactionManagerMonitor;
+import org.tranql.connector.UserPasswordManagedConnectionFactory;
import javax.resource.spi.ConnectionManager;
import javax.resource.spi.ManagedConnectionFactory;
@@ -53,6 +54,10 @@ public class ConnectionManagerFactory {
private int connectionMaxWaitMilliseconds = 5000;
private int connectionMaxIdleMinutes = 15;
+ private boolean validateOnMatch = true;
+ private boolean backgroundValidation = false;
+ private int backgroundValidationMilliseconds = 600000;
+
private SubjectSource subjectSource;
private ConnectionTrackingCoordinator connectionTracker;
@@ -136,16 +141,34 @@ public class ConnectionManagerFactory {
transactionManager.addTransactionAssociationListener(transactionManagerMonitor);
}
if (connectionManager == null) {
- // Instantiate the Geronimo Connection Manager
- connectionManager = new GenericConnectionManager(
- transactionSupport,
- poolingSupport,
- subjectSource,
- connectionTracker,
- transactionManager,
- managedConnectionFactory,
- getClass().getName(),
- getClass().getClassLoader());
+ if (validateOnMatch || backgroundValidation) {
+ // Wrap the original ManagedConnectionFactory to add validation capability
+ managedConnectionFactory = new ValidatingDelegatingManagedConnectionFactory((UserPasswordManagedConnectionFactory) managedConnectionFactory);
+ }
+ if (backgroundValidation) {
+ // Instantiate the Validating Connection Manager
+ connectionManager = new ValidatingGenericConnectionManager(
+ transactionSupport,
+ poolingSupport,
+ subjectSource,
+ connectionTracker,
+ transactionManager,
+ managedConnectionFactory,
+ getClass().getName(),
+ getClass().getClassLoader(),
+ backgroundValidationMilliseconds);
+ } else {
+ // Instantiate the Geronimo Connection Manager
+ connectionManager = new GenericConnectionManager(
+ transactionSupport,
+ poolingSupport,
+ subjectSource,
+ connectionTracker,
+ transactionManager,
+ managedConnectionFactory,
+ getClass().getName(),
+ getClass().getClassLoader());
+ }
connectionManager.doStart();
}
@@ -257,6 +280,30 @@ public class ConnectionManagerFactory {
this.connectionMaxIdleMinutes = connectionMaxIdleMinutes;
}
+ public boolean isValidateOnMatch() {
+ return validateOnMatch;
+ }
+
+ public void setValidateOnMatch(boolean validateOnMatch) {
+ this.validateOnMatch = validateOnMatch;
+ }
+
+ public boolean isBackgroundValidation() {
+ return backgroundValidation;
+ }
+
+ public void setBackgroundValidation(boolean backgroundValidation) {
+ this.backgroundValidation = backgroundValidation;
+ }
+
+ public int getBackgroundValidationMilliseconds() {
+ return backgroundValidationMilliseconds;
+ }
+
+ public void setBackgroundValidationMilliseconds(int backgroundValidationMilliseconds) {
+ this.backgroundValidationMilliseconds = backgroundValidationMilliseconds;
+ }
+
public SubjectSource getSubjectSource() {
return subjectSource;
}
Modified: aries/trunk/transaction/transaction-jdbc/src/main/java/org/apache/aries/transaction/jdbc/internal/ManagedDataSourceFactory.java
URL: http://svn.apache.org/viewvc/aries/trunk/transaction/transaction-jdbc/src/main/java/org/apache/aries/transaction/jdbc/internal/ManagedDataSourceFactory.java?rev=1603130&r1=1603129&r2=1603130&view=diff
==============================================================================
--- aries/trunk/transaction/transaction-jdbc/src/main/java/org/apache/aries/transaction/jdbc/internal/ManagedDataSourceFactory.java (original)
+++ aries/trunk/transaction/transaction-jdbc/src/main/java/org/apache/aries/transaction/jdbc/internal/ManagedDataSourceFactory.java Tue Jun 17 11:25:34 2014
@@ -112,6 +112,9 @@ public class ManagedDataSourceFactory {
cm.setPooling(getBool("aries.xa.pooling", true));
cm.setPoolMaxSize(getInt("aries.xa.poolMaxSize", 10));
cm.setPoolMinSize(getInt("aries.xa.poolMinSize", 0));
+ cm.setValidateOnMatch(getBool("aries.xa.validateOnMatch", true));
+ cm.setBackgroundValidation(getBool("aries.xa.backgroundValidation", false));
+ cm.setBackgroundValidationMilliseconds(getInt("aries.xa.backgroundValidationMilliseconds", 600000));
cm.setTransaction(getString("aries.xa.transaction", "xa"));
cm.init();
Added: aries/trunk/transaction/transaction-jdbc/src/main/java/org/apache/aries/transaction/jdbc/internal/Reflections.java
URL: http://svn.apache.org/viewvc/aries/trunk/transaction/transaction-jdbc/src/main/java/org/apache/aries/transaction/jdbc/internal/Reflections.java?rev=1603130&view=auto
==============================================================================
--- aries/trunk/transaction/transaction-jdbc/src/main/java/org/apache/aries/transaction/jdbc/internal/Reflections.java (added)
+++ aries/trunk/transaction/transaction-jdbc/src/main/java/org/apache/aries/transaction/jdbc/internal/Reflections.java Tue Jun 17 11:25:34 2014
@@ -0,0 +1,58 @@
+/*
+ * 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.aries.transaction.jdbc.internal;
+
+import java.lang.reflect.Field;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+public final class Reflections {
+
+ private Reflections() {
+ // no-op
+ }
+
+ public static Object get(final Object instance, String field) {
+ Class<?> clazz = instance.getClass();
+ while (clazz != null) {
+ try {
+ final Field f = clazz.getDeclaredField(field);
+ final boolean acc = f.isAccessible();
+ return AccessController.doPrivileged(new PrivilegedAction<Object>() {
+ @Override
+ public Object run() {
+ f.setAccessible(true);
+ try {
+ return f.get(instance);
+ } catch (IllegalAccessException ex) {
+ throw new IllegalArgumentException(ex);
+ } finally {
+ f.setAccessible(acc);
+ }
+ }
+ });
+ } catch (NoSuchFieldException nsfe) {
+ // no-op
+ }
+
+ clazz = clazz.getSuperclass();
+ }
+ throw new RuntimeException(new NoSuchFieldException(field));
+ }
+}
Added: aries/trunk/transaction/transaction-jdbc/src/main/java/org/apache/aries/transaction/jdbc/internal/ValidatingDelegatingManagedConnectionFactory.java
URL: http://svn.apache.org/viewvc/aries/trunk/transaction/transaction-jdbc/src/main/java/org/apache/aries/transaction/jdbc/internal/ValidatingDelegatingManagedConnectionFactory.java?rev=1603130&view=auto
==============================================================================
--- aries/trunk/transaction/transaction-jdbc/src/main/java/org/apache/aries/transaction/jdbc/internal/ValidatingDelegatingManagedConnectionFactory.java (added)
+++ aries/trunk/transaction/transaction-jdbc/src/main/java/org/apache/aries/transaction/jdbc/internal/ValidatingDelegatingManagedConnectionFactory.java Tue Jun 17 11:25:34 2014
@@ -0,0 +1,155 @@
+/*
+ * 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.aries.transaction.jdbc.internal;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.tranql.connector.AbstractManagedConnection;
+import org.tranql.connector.ManagedConnectionHandle;
+import org.tranql.connector.UserPasswordManagedConnectionFactory;
+import org.tranql.connector.jdbc.ConnectionHandle;
+import org.tranql.connector.jdbc.TranqlDataSource;
+
+import javax.resource.NotSupportedException;
+import javax.resource.ResourceException;
+import javax.resource.spi.ConnectionManager;
+import javax.resource.spi.ConnectionRequestInfo;
+import javax.resource.spi.ManagedConnection;
+import javax.resource.spi.ManagedConnectionFactory;
+import javax.resource.spi.TransactionSupport;
+import javax.resource.spi.ValidatingManagedConnectionFactory;
+import javax.security.auth.Subject;
+
+import java.io.PrintWriter;
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.util.HashSet;
+import java.util.Set;
+
+public final class ValidatingDelegatingManagedConnectionFactory implements UserPasswordManagedConnectionFactory, ValidatingManagedConnectionFactory, TransactionSupport {
+
+ private static final Logger LOG = LoggerFactory.getLogger(ValidatingDelegatingManagedConnectionFactory.class);
+ private final ManagedConnectionFactory delegate;
+
+ public ValidatingDelegatingManagedConnectionFactory(ManagedConnectionFactory managedConnectionFactory) {
+ this.delegate = managedConnectionFactory;
+ }
+
+ private boolean isValidConnection(Connection c) {
+ try {
+ if (c.isValid(0)) {
+ LOG.debug("Connection validation succeeded for managed connection {}.", c);
+ return true;
+ } else {
+ LOG.debug("Connection validation failed for managed connection {}.", c);
+ }
+ } catch (SQLException e) {
+ // no-op
+ }
+ return false;
+ }
+
+ @Override
+ public TransactionSupportLevel getTransactionSupport() {
+ return TransactionSupport.class.cast(delegate).getTransactionSupport();
+ }
+
+ @Override
+ public Set getInvalidConnections(Set connectionSet) throws ResourceException {
+ Set<ManagedConnection> invalid = new HashSet<ManagedConnection>();
+
+ for (Object o : connectionSet) {
+ if (o instanceof AbstractManagedConnection) {
+ AbstractManagedConnection<Connection, ConnectionHandle> amc = AbstractManagedConnection.class.cast(o);
+
+ if (!isValidConnection(amc.getPhysicalConnection())) {
+ invalid.add(amc);
+ }
+ }
+ }
+
+ return invalid;
+ }
+
+ @Override
+ public String getUserName() {
+ return UserPasswordManagedConnectionFactory.class.cast(delegate).getUserName();
+ }
+
+ @Override
+ public String getPassword() {
+ return UserPasswordManagedConnectionFactory.class.cast(delegate).getPassword();
+ }
+
+ @Override
+ public Object createConnectionFactory(ConnectionManager cxManager) throws ResourceException {
+ return new TranqlDataSource(this, cxManager);
+ }
+
+ @Override
+ public Object createConnectionFactory() throws ResourceException {
+ throw new NotSupportedException("ConnectionManager is required");
+ }
+
+ @Override
+ public ManagedConnection createManagedConnection(Subject subject, ConnectionRequestInfo cxRequestInfo) throws ResourceException {
+ return delegate.createManagedConnection(subject, cxRequestInfo);
+ }
+
+ @Override
+ public ManagedConnection matchManagedConnections(Set connectionSet, Subject subject, ConnectionRequestInfo cxRequestInfo) throws ResourceException {
+ for (Object o : connectionSet) {
+ if (o instanceof ManagedConnectionHandle) {
+ ManagedConnectionHandle mch = ManagedConnectionHandle.class.cast(o);
+ if (mch.matches(this, subject, cxRequestInfo)) {
+ if (mch instanceof AbstractManagedConnection) {
+ AbstractManagedConnection<Connection, ConnectionHandle> amc = AbstractManagedConnection.class.cast(mch);
+ if (isValidConnection(amc.getPhysicalConnection())) {
+ return amc;
+ }
+ } else {
+ return mch;
+ }
+ }
+ }
+ }
+
+ return null;
+ }
+
+ @Override
+ public void setLogWriter(PrintWriter out) throws ResourceException {
+ delegate.setLogWriter(out);
+ }
+
+ @Override
+ public PrintWriter getLogWriter() throws ResourceException {
+ return delegate.getLogWriter();
+ }
+
+ @Override
+ public int hashCode() {
+ return delegate.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return delegate.equals(other);
+ }
+}
Added: aries/trunk/transaction/transaction-jdbc/src/main/java/org/apache/aries/transaction/jdbc/internal/ValidatingGenericConnectionManager.java
URL: http://svn.apache.org/viewvc/aries/trunk/transaction/transaction-jdbc/src/main/java/org/apache/aries/transaction/jdbc/internal/ValidatingGenericConnectionManager.java?rev=1603130&view=auto
==============================================================================
--- aries/trunk/transaction/transaction-jdbc/src/main/java/org/apache/aries/transaction/jdbc/internal/ValidatingGenericConnectionManager.java (added)
+++ aries/trunk/transaction/transaction-jdbc/src/main/java/org/apache/aries/transaction/jdbc/internal/ValidatingGenericConnectionManager.java Tue Jun 17 11:25:34 2014
@@ -0,0 +1,168 @@
+/*
+ * 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.aries.transaction.jdbc.internal;
+
+import org.apache.geronimo.connector.outbound.AbstractSinglePoolConnectionInterceptor;
+import org.apache.geronimo.connector.outbound.ConnectionInfo;
+import org.apache.geronimo.connector.outbound.ConnectionInterceptor;
+import org.apache.geronimo.connector.outbound.ConnectionReturnAction;
+import org.apache.geronimo.connector.outbound.GenericConnectionManager;
+import org.apache.geronimo.connector.outbound.ManagedConnectionInfo;
+import org.apache.geronimo.connector.outbound.MultiPoolConnectionInterceptor;
+import org.apache.geronimo.connector.outbound.SinglePoolConnectionInterceptor;
+import org.apache.geronimo.connector.outbound.SinglePoolMatchAllConnectionInterceptor;
+import org.apache.geronimo.connector.outbound.SubjectSource;
+import org.apache.geronimo.connector.outbound.connectionmanagerconfig.PoolingSupport;
+import org.apache.geronimo.connector.outbound.connectionmanagerconfig.TransactionSupport;
+import org.apache.geronimo.connector.outbound.connectiontracking.ConnectionTracker;
+import org.apache.geronimo.transaction.manager.RecoverableTransactionManager;
+
+import javax.resource.ResourceException;
+import javax.resource.spi.ManagedConnection;
+import javax.resource.spi.ManagedConnectionFactory;
+import javax.resource.spi.ValidatingManagedConnectionFactory;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.Timer;
+import java.util.TimerTask;
+import java.util.concurrent.locks.ReadWriteLock;
+
+public final class ValidatingGenericConnectionManager extends GenericConnectionManager {
+
+ private static final Timer TIMER = new Timer("ValidatingGenericConnectionManagerTimer", true);
+
+ private transient final TimerTask validatingTask;
+ private final long validatingInterval;
+
+ private final ReadWriteLock lock;
+ private final Object pool;
+
+ public ValidatingGenericConnectionManager(TransactionSupport transactionSupport, PoolingSupport pooling, SubjectSource subjectSource, ConnectionTracker connectionTracker, RecoverableTransactionManager transactionManager, ManagedConnectionFactory mcf, String name, ClassLoader classLoader, long interval) {
+ super(transactionSupport, pooling, subjectSource, connectionTracker, transactionManager, mcf, name, classLoader);
+ validatingInterval = interval;
+
+ ConnectionInterceptor stack = interceptors.getStack();
+
+ ReadWriteLock foundLock = null;
+ ConnectionInterceptor current = stack;
+ do {
+ if (current instanceof AbstractSinglePoolConnectionInterceptor) {
+ try {
+ foundLock = (ReadWriteLock) Reflections.get(current, "resizeLock");
+ } catch (Exception e) {
+ // no-op
+ }
+ break;
+ }
+
+ // look next
+ try {
+ current = (ConnectionInterceptor) Reflections.get(current, "next");
+ } catch (Exception e) {
+ current = null;
+ }
+ } while (current != null);
+
+ this.lock = foundLock;
+
+ Object foundPool = null;
+ if (current instanceof AbstractSinglePoolConnectionInterceptor) {
+ foundPool = Reflections.get(stack, "pool");
+ } else if (current instanceof MultiPoolConnectionInterceptor) {
+ log.warn("validation on stack {} not supported", stack);
+ }
+ this.pool = foundPool;
+
+ if (pool != null) {
+ validatingTask = new ValidatingTask(current, lock, pool);
+ } else {
+ validatingTask = null;
+ }
+ }
+
+ @Override
+ public void doStart() throws Exception {
+ super.doStart();
+ if (validatingTask != null) {
+ TIMER.schedule(validatingTask, validatingInterval, validatingInterval);
+ }
+ }
+
+ @Override
+ public void doStop() throws Exception {
+ if (validatingTask != null) {
+ validatingTask.cancel();
+ }
+ super.doStop();
+ }
+
+ private class ValidatingTask extends TimerTask {
+
+ private final ConnectionInterceptor stack;
+ private final ReadWriteLock lock;
+ private final Object pool;
+
+ public ValidatingTask(ConnectionInterceptor stack, ReadWriteLock lock, Object pool) {
+ this.stack = stack;
+ this.lock = lock;
+ this.pool = pool;
+ }
+
+ @Override
+ public void run() {
+ if (lock != null) {
+ lock.writeLock().lock();
+ }
+
+ try {
+ final Map<ManagedConnection, ManagedConnectionInfo> connections;
+ if (stack instanceof SinglePoolConnectionInterceptor) {
+ connections = new HashMap<ManagedConnection, ManagedConnectionInfo>();
+ for (ManagedConnectionInfo info : (List<ManagedConnectionInfo>) pool) {
+ connections.put(info.getManagedConnection(), info);
+ }
+ } else if (stack instanceof SinglePoolMatchAllConnectionInterceptor) {
+ connections = (Map<ManagedConnection, ManagedConnectionInfo>) pool;
+ } else {
+ log.warn("stack {} currently not supported", stack);
+ return;
+ }
+
+ // destroy invalid connections
+ try {
+ Set<ManagedConnection> invalids = ValidatingManagedConnectionFactory.class.cast(getManagedConnectionFactory()).getInvalidConnections(connections.keySet());
+ if (invalids != null) {
+ for (ManagedConnection invalid : invalids) {
+ stack.returnConnection(new ConnectionInfo(connections.get(invalid)), ConnectionReturnAction.DESTROY);
+ }
+ }
+ } catch (ResourceException e) {
+ log.error(e.getMessage(), e);
+ }
+ } finally {
+ if (lock != null) {
+ lock.writeLock().unlock();
+ }
+ }
+ }
+ }
+}