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.HashMap; 021 import java.util.Map; 022 023 import javax.resource.ResourceException; 024 import javax.resource.spi.ConnectionRequestInfo; 025 import javax.security.auth.Subject; 026 027 import org.apache.geronimo.connector.outbound.connectionmanagerconfig.PoolingSupport; 028 029 /** 030 * MultiPoolConnectionInterceptor maps the provided subject and connection request info to a 031 * "SinglePool". This can be used to make sure all matches will succeed, avoiding synchronization 032 * slowdowns. 033 * 034 * Created: Fri Oct 10 12:53:11 2003 035 * 036 * @version $Rev: 585608 $ $Date: 2007-10-17 19:56:54 +0200 (Wed, 17 Oct 2007) $ 037 */ 038 public class MultiPoolConnectionInterceptor implements ConnectionInterceptor, PoolingAttributes{ 039 040 private final ConnectionInterceptor next; 041 private final PoolingSupport singlePoolFactory; 042 043 private final boolean useSubject; 044 045 private final boolean useCRI; 046 047 private final Map<SubjectCRIKey,PoolingAttributes> pools = new HashMap<SubjectCRIKey,PoolingAttributes>(); 048 049 // volatile is not necessary, here, because of synchronization. but maintained for consistency with other Interceptors... 050 private volatile boolean destroyed = false; 051 052 public MultiPoolConnectionInterceptor( 053 final ConnectionInterceptor next, 054 PoolingSupport singlePoolFactory, 055 final boolean useSubject, 056 final boolean useCRI) { 057 this.next = next; 058 this.singlePoolFactory = singlePoolFactory; 059 this.useSubject = useSubject; 060 this.useCRI = useCRI; 061 } 062 063 public void getConnection(ConnectionInfo connectionInfo) throws ResourceException { 064 ManagedConnectionInfo mci = connectionInfo.getManagedConnectionInfo(); 065 SubjectCRIKey key = 066 new SubjectCRIKey( 067 useSubject ? mci.getSubject() : null, 068 useCRI ? mci.getConnectionRequestInfo() : null); 069 ConnectionInterceptor poolInterceptor = null; 070 synchronized (pools) { 071 if (destroyed) { 072 throw new ResourceException("ConnectionManaged has been destroyed"); 073 } 074 poolInterceptor = (ConnectionInterceptor) pools.get(key); 075 if (poolInterceptor == null) { 076 poolInterceptor = singlePoolFactory.addPoolingInterceptors(next); 077 pools.put(key, (PoolingAttributes) poolInterceptor); 078 } 079 } 080 mci.setPoolInterceptor(poolInterceptor); 081 poolInterceptor.getConnection(connectionInfo); 082 } 083 084 // let underlying pools handle destroyed processing... 085 public void returnConnection( 086 ConnectionInfo connectionInfo, 087 ConnectionReturnAction connectionReturnAction) { 088 ManagedConnectionInfo mci = connectionInfo.getManagedConnectionInfo(); 089 ConnectionInterceptor poolInterceptor = mci.getPoolInterceptor(); 090 poolInterceptor.returnConnection(connectionInfo, connectionReturnAction); 091 } 092 093 public void destroy() { 094 synchronized (pools) { 095 destroyed = true; 096 for (PoolingAttributes poolingAttributes : pools.values()) { 097 ConnectionInterceptor poolInterceptor = (ConnectionInterceptor) poolingAttributes; 098 poolInterceptor.destroy(); 099 } 100 pools.clear(); 101 } 102 next.destroy(); 103 } 104 105 public int getPartitionCount() { 106 return pools.size(); 107 } 108 109 public int getPartitionMaxSize() { 110 return singlePoolFactory.getPartitionMaxSize(); 111 } 112 113 public void setPartitionMaxSize(int maxSize) throws InterruptedException { 114 singlePoolFactory.setPartitionMaxSize(maxSize); 115 for (PoolingAttributes poolingAttributes : pools.values()) { 116 poolingAttributes.setPartitionMaxSize(maxSize); 117 } 118 } 119 120 public int getPartitionMinSize() { 121 return singlePoolFactory.getPartitionMinSize(); 122 } 123 124 public void setPartitionMinSize(int minSize) { 125 singlePoolFactory.setPartitionMinSize(minSize); 126 for (PoolingAttributes poolingAttributes : pools.values()) { 127 poolingAttributes.setPartitionMinSize(minSize); 128 } 129 } 130 131 public int getIdleConnectionCount() { 132 int count = 0; 133 for (PoolingAttributes poolingAttributes : pools.values()) { 134 count += poolingAttributes.getIdleConnectionCount(); 135 } 136 return count; 137 } 138 139 public int getConnectionCount() { 140 int count = 0; 141 for (PoolingAttributes poolingAttributes : pools.values()) { 142 count += poolingAttributes.getConnectionCount(); 143 } 144 return count; 145 } 146 147 public int getBlockingTimeoutMilliseconds() { 148 return singlePoolFactory.getBlockingTimeoutMilliseconds(); 149 } 150 151 public void setBlockingTimeoutMilliseconds(int timeoutMilliseconds) { 152 singlePoolFactory.setBlockingTimeoutMilliseconds(timeoutMilliseconds); 153 for (PoolingAttributes poolingAttributes : pools.values()) { 154 poolingAttributes.setBlockingTimeoutMilliseconds(timeoutMilliseconds); 155 } 156 } 157 158 public int getIdleTimeoutMinutes() { 159 return singlePoolFactory.getIdleTimeoutMinutes(); 160 } 161 162 public void setIdleTimeoutMinutes(int idleTimeoutMinutes) { 163 singlePoolFactory.setIdleTimeoutMinutes(idleTimeoutMinutes); 164 for (PoolingAttributes poolingAttributes : pools.values()) { 165 poolingAttributes.setIdleTimeoutMinutes(idleTimeoutMinutes); 166 } 167 } 168 169 static class SubjectCRIKey { 170 private final Subject subject; 171 private final ConnectionRequestInfo cri; 172 private final int hashcode; 173 174 public SubjectCRIKey( 175 final Subject subject, 176 final ConnectionRequestInfo cri) { 177 this.subject = subject; 178 this.cri = cri; 179 this.hashcode = 180 (subject == null ? 17 : subject.hashCode() * 17) 181 ^ (cri == null ? 1 : cri.hashCode()); 182 } 183 184 public int hashCode() { 185 return hashcode; 186 } 187 188 public boolean equals(Object other) { 189 if (!(other instanceof SubjectCRIKey)) { 190 return false; 191 } 192 SubjectCRIKey o = (SubjectCRIKey) other; 193 return hashcode == o.hashcode && 194 (subject == null ? o.subject == null : subject.equals(o.subject) && 195 cri == null ? o.cri == null : cri.equals(o.cri)); 196 } 197 } 198 }