001 /**
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017
018 package org.apache.geronimo.connector.outbound;
019
020 import java.util.Collection;
021 import java.util.Iterator;
022
023 import javax.resource.ResourceException;
024 import javax.resource.spi.DissociatableManagedConnection;
025 import javax.resource.spi.ManagedConnection;
026
027 import org.apache.geronimo.connector.outbound.connectiontracking.ConnectionTracker;
028
029 /**
030 * ConnectionTrackingInterceptor.java handles communication with the
031 * CachedConnectionManager. On method call entry, cached handles are
032 * checked for the correct Subject. On method call exit, cached
033 * handles are disassociated if possible. On getting or releasing
034 * a connection the CachedConnectionManager is notified.
035 *
036 *
037 * @version $Rev: 585608 $ $Date: 2007-10-17 13:56:54 -0400 (Wed, 17 Oct 2007) $
038 */
039 public class ConnectionTrackingInterceptor implements ConnectionInterceptor {
040
041 private final ConnectionInterceptor next;
042 private final String key;
043 private final ConnectionTracker connectionTracker;
044
045 public ConnectionTrackingInterceptor(
046 final ConnectionInterceptor next,
047 final String key,
048 final ConnectionTracker connectionTracker
049 ) {
050 this.next = next;
051 this.key = key;
052 this.connectionTracker = connectionTracker;
053 }
054
055 /**
056 * called by: GenericConnectionManager.allocateConnection, GenericConnectionManager.associateConnection, and enter.
057 * in: connectionInfo is non-null, and has non-null ManagedConnectionInfo with non-null managedConnectionfactory.
058 * connection handle may or may not be null.
059 * out: connectionInfo has non-null connection handle, non null ManagedConnectionInfo with non-null ManagedConnection and GeronimoConnectionEventListener.
060 * connection tracker has been notified of handle-managed connection association.
061 * @param connectionInfo
062 * @throws ResourceException
063 */
064 public void getConnection(ConnectionInfo connectionInfo) throws ResourceException {
065 connectionTracker.setEnvironment(connectionInfo, key);
066 next.getConnection(connectionInfo);
067 connectionTracker.handleObtained(this, connectionInfo, false);
068 }
069
070 /**
071 * Called when a proxied connection which has been released need to be reassociated with a real connection.
072 */
073 public void reassociateConnection(ConnectionInfo connectionInfo) throws ResourceException {
074 connectionTracker.setEnvironment(connectionInfo, key);
075 next.getConnection(connectionInfo);
076 connectionTracker.handleObtained(this, connectionInfo, true);
077 }
078
079 /**
080 * called by: GeronimoConnectionEventListener.connectionClosed, GeronimoConnectionEventListener.connectionErrorOccurred, exit
081 * in: handle has already been dissociated from ManagedConnection. connectionInfo not null, has non-null ManagedConnectionInfo, ManagedConnectionInfo has non-null ManagedConnection
082 * handle can be null if called from error in ManagedConnection in pool.
083 * out: connectionTracker has been notified, ManagedConnectionInfo null.
084 * @param connectionInfo
085 * @param connectionReturnAction
086 */
087 public void returnConnection(
088 ConnectionInfo connectionInfo,
089 ConnectionReturnAction connectionReturnAction) {
090 connectionTracker.handleReleased(this, connectionInfo, connectionReturnAction);
091 next.returnConnection(connectionInfo, connectionReturnAction);
092 }
093
094 public void destroy() {
095 next.destroy();
096 }
097
098 public void enter(Collection<ConnectionInfo> connectionInfos) throws ResourceException {
099 for (ConnectionInfo connectionInfo : connectionInfos) {
100 next.getConnection(connectionInfo);
101 }
102
103 }
104
105 public void exit(Collection<ConnectionInfo> connectionInfos)
106 throws ResourceException {
107 for (Iterator<ConnectionInfo> iterator = connectionInfos.iterator(); iterator.hasNext();) {
108 ConnectionInfo connectionInfo = iterator.next();
109 if (connectionInfo.isUnshareable()) {
110 //if one is, they all are
111 return;
112 }
113 ManagedConnectionInfo managedConnectionInfo = connectionInfo.getManagedConnectionInfo();
114 ManagedConnection managedConnection = managedConnectionInfo.getManagedConnection();
115 if (managedConnection instanceof DissociatableManagedConnection
116 && managedConnectionInfo.isFirstConnectionInfo(connectionInfo)) {
117 iterator.remove();
118 ((DissociatableManagedConnection) managedConnection).dissociateConnections();
119 managedConnectionInfo.clearConnectionHandles();
120 //todo this needs some kind of check so cx isn't returned more than once
121 //in case dissociate calls connection closed event and returns cx to pool.
122 returnConnection(connectionInfo, ConnectionReturnAction.RETURN_HANDLE);
123 }
124 }
125 }
126 }