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 19:56:54 +0200 (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 }