You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tomee.apache.org by da...@apache.org on 2007/10/17 02:55:07 UTC
svn commit: r585310 - in /openejb/trunk/openejb3:
container/openejb-core/src/main/java/org/apache/openejb/resource/AutoConnectionTracker.java
container/openejb-core/src/main/java/org/apache/openejb/resource/GeronimoConnectionManagerFactory.java
pom.xml
Author: dain
Date: Tue Oct 16 17:55:07 2007
New Revision: 585310
URL: http://svn.apache.org/viewvc?rev=585310&view=rev
Log:
Reclaim JCA connections that have been garbage collected
Added:
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/resource/AutoConnectionTracker.java
Modified:
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/resource/GeronimoConnectionManagerFactory.java
openejb/trunk/openejb3/pom.xml
Added: openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/resource/AutoConnectionTracker.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/resource/AutoConnectionTracker.java?rev=585310&view=auto
==============================================================================
--- openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/resource/AutoConnectionTracker.java (added)
+++ openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/resource/AutoConnectionTracker.java Tue Oct 16 17:55:07 2007
@@ -0,0 +1,153 @@
+/**
+ *
+ * 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.openejb.resource;
+
+import org.apache.geronimo.connector.outbound.ConnectionInfo;
+import org.apache.geronimo.connector.outbound.ConnectionReturnAction;
+import org.apache.geronimo.connector.outbound.ConnectionTrackingInterceptor;
+import org.apache.geronimo.connector.outbound.ManagedConnectionInfo;
+import org.apache.geronimo.connector.outbound.connectiontracking.ConnectionTracker;
+
+import javax.resource.ResourceException;
+import javax.resource.spi.DissociatableManagedConnection;
+import java.lang.ref.PhantomReference;
+import java.lang.ref.ReferenceQueue;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+public class AutoConnectionTracker implements ConnectionTracker {
+ private final ConcurrentMap<ManagedConnectionInfo, ProxyPhantomReference> references = new ConcurrentHashMap<ManagedConnectionInfo,ProxyPhantomReference>();
+ private final ReferenceQueue referenceQueue = new ReferenceQueue();
+
+ /**
+ * Releases any managed connections held by a garbage collected connection proxy.
+ * @param connectionInfo the connection to be obtained
+ * @param key the unique id of the connection manager
+ */
+ public void setEnvironment(ConnectionInfo connectionInfo, String key) {
+ ProxyPhantomReference reference = (ProxyPhantomReference) referenceQueue.poll();
+ while (reference != null) {
+ reference.clear();
+ references.remove(reference.managedConnectionInfo);
+
+ ConnectionInfo released = new ConnectionInfo(reference.managedConnectionInfo);
+ reference.interceptor.returnConnection(released, ConnectionReturnAction.DESTROY);
+ reference = (ProxyPhantomReference) referenceQueue.poll();
+ }
+ }
+
+ /**
+ * Proxies new connection handles so we can detect when they have been garbage collected.
+ *
+ * @param interceptor the interceptor used to release the managed connection when the handled is garbage collected.
+ * @param connectionInfo the connection that was obtained
+ * @param reassociate should always be false
+ */
+ public void handleObtained(ConnectionTrackingInterceptor interceptor, ConnectionInfo connectionInfo, boolean reassociate) throws ResourceException {
+ if (!reassociate) {
+ proxyConnection(interceptor, connectionInfo);
+ }
+ }
+
+ /**
+ * Removes the released collection from the garbage collection reference tracker, since this
+ * connection is being release via a normal close method.
+ *
+ * @param interceptor ignored
+ * @param connectionInfo the connection that was released
+ * @param action ignored
+ */
+ public void handleReleased(ConnectionTrackingInterceptor interceptor, ConnectionInfo connectionInfo, ConnectionReturnAction action) {
+ PhantomReference phantomReference = references.remove(connectionInfo.getManagedConnectionInfo());
+ if (phantomReference != null) {
+ phantomReference.clear();
+ }
+ }
+
+ private void proxyConnection(ConnectionTrackingInterceptor interceptor, ConnectionInfo connectionInfo) throws ResourceException {
+ // if this connection already has a proxy no need to create another
+ if (connectionInfo.getConnectionProxy() != null) return;
+
+ // DissociatableManagedConnection do not need to be proxied
+ if (connectionInfo.getManagedConnectionInfo().getManagedConnection() instanceof DissociatableManagedConnection) {
+ return;
+ }
+
+ try {
+ Object handle = connectionInfo.getConnectionHandle();
+ ConnectionInvocationHandler invocationHandler = new ConnectionInvocationHandler(handle);
+ Object proxy = Proxy.newProxyInstance(handle.getClass().getClassLoader(), handle.getClass().getInterfaces(), invocationHandler);
+ connectionInfo.setConnectionProxy(proxy);
+ ProxyPhantomReference reference = new ProxyPhantomReference(interceptor, connectionInfo.getManagedConnectionInfo(), invocationHandler, referenceQueue);
+ references.put(connectionInfo.getManagedConnectionInfo(), reference);
+ } catch (Throwable e) {
+ throw new ResourceException("Unable to construct connection proxy", e);
+ }
+ }
+
+ public static class ConnectionInvocationHandler implements InvocationHandler {
+ private final Object handle;
+
+ public ConnectionInvocationHandler(Object handle) {
+ this.handle = handle;
+ }
+
+ public Object invoke(Object object, Method method, Object[] args) throws Throwable {
+ if (method.getDeclaringClass() == Object.class) {
+ if (method.getName().equals("finalize")) {
+ // ignore the handle will get called if it implemented the method
+ return null;
+ }
+ if (method.getName().equals("clone")) {
+ throw new CloneNotSupportedException();
+ }
+ }
+
+ try {
+ Object value = method.invoke(handle, args);
+ return value;
+ } catch (InvocationTargetException ite) {
+ // catch InvocationTargetExceptions and turn them into the target exception (if there is one)
+ Throwable t = ite.getTargetException();
+ if (t != null) {
+ throw t;
+ }
+ throw ite;
+ }
+ }
+ }
+
+ private static class ProxyPhantomReference extends PhantomReference<ConnectionInvocationHandler> {
+ private ConnectionTrackingInterceptor interceptor;
+ private ManagedConnectionInfo managedConnectionInfo;
+
+ @SuppressWarnings({"unchecked"})
+ public ProxyPhantomReference(ConnectionTrackingInterceptor interceptor,
+ ManagedConnectionInfo managedConnectionInfo,
+ ConnectionInvocationHandler handler,
+ ReferenceQueue referenceQueue) {
+ super(handler, referenceQueue);
+ this.interceptor = interceptor;
+ this.managedConnectionInfo = managedConnectionInfo;
+ }
+ }
+}
Modified: openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/resource/GeronimoConnectionManagerFactory.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/resource/GeronimoConnectionManagerFactory.java?rev=585310&r1=585309&r2=585310&view=diff
==============================================================================
--- openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/resource/GeronimoConnectionManagerFactory.java (original)
+++ openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/resource/GeronimoConnectionManagerFactory.java Tue Oct 16 17:55:07 2007
@@ -26,7 +26,6 @@
import org.apache.geronimo.connector.outbound.connectionmanagerconfig.SinglePool;
import org.apache.geronimo.connector.outbound.connectionmanagerconfig.TransactionSupport;
import org.apache.geronimo.connector.outbound.connectionmanagerconfig.XATransactions;
-import org.apache.geronimo.connector.outbound.connectiontracking.ConnectionTrackingCoordinator;
import org.apache.geronimo.transaction.manager.RecoverableTransactionManager;
import javax.transaction.TransactionManager;
@@ -149,7 +148,7 @@
createTransactionSupport(),
poolingSupport,
null,
- new ConnectionTrackingCoordinator(true),
+ new AutoConnectionTracker(),
(RecoverableTransactionManager)transactionManager,
name,
classLoader);
Modified: openejb/trunk/openejb3/pom.xml
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/pom.xml?rev=585310&r1=585309&r2=585310&view=diff
==============================================================================
--- openejb/trunk/openejb3/pom.xml (original)
+++ openejb/trunk/openejb3/pom.xml Tue Oct 16 17:55:07 2007
@@ -501,7 +501,7 @@
<dependency>
<groupId>org.apache.geronimo.components</groupId>
<artifactId>geronimo-connector</artifactId>
- <version>2.0.1</version>
+ <version>2.1-SNAPSHOT</version>
<exclusions>
<exclusion>
<groupId>org.apache.geronimo.specs</groupId>