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 javax.resource.ResourceException;
021 import javax.resource.spi.ConnectionManager;
022 import javax.resource.spi.ConnectionRequestInfo;
023 import javax.resource.spi.LazyAssociatableConnectionManager;
024 import javax.resource.spi.ManagedConnectionFactory;
025 import javax.transaction.SystemException;
026
027 import org.apache.geronimo.connector.outbound.connectionmanagerconfig.PoolingSupport;
028 import org.apache.geronimo.transaction.manager.NamedXAResource;
029 import org.apache.geronimo.transaction.manager.RecoverableTransactionManager;
030
031 /**
032 * @version $Rev: 585309 $ $Date: 2007-10-16 20:54:22 -0400 (Tue, 16 Oct 2007) $
033 */
034 public abstract class AbstractConnectionManager implements ConnectionManagerContainer, ConnectionManager, LazyAssociatableConnectionManager, PoolingAttributes {
035 protected final Interceptors interceptors;
036 private final RecoverableTransactionManager transactionManager;
037
038 //default constructor for use as endpoint
039 public AbstractConnectionManager() {
040 interceptors = null;
041 transactionManager = null;
042 }
043
044 public AbstractConnectionManager(Interceptors interceptors, RecoverableTransactionManager transactionManager) {
045 this.interceptors = interceptors;
046 this.transactionManager = transactionManager;
047 }
048
049 public Object createConnectionFactory(ManagedConnectionFactory mcf) throws ResourceException {
050 return mcf.createConnectionFactory(this);
051 }
052
053 protected ConnectionManager getConnectionManager() {
054 return this;
055 }
056
057 public void doRecovery(ManagedConnectionFactory managedConnectionFactory) {
058 try {
059 if (!getIsRecoverable()) {
060 return;
061 }
062 ManagedConnectionInfo mci = new ManagedConnectionInfo(managedConnectionFactory, null);
063
064 ConnectionInfo recoveryConnectionInfo = new ConnectionInfo(mci);
065 getRecoveryStack().getConnection(recoveryConnectionInfo);
066
067 // For pooled resources, we may now have a new MCI (not the one constructed above). Make sure we use the correct MCI
068 NamedXAResource xaResource = (NamedXAResource) recoveryConnectionInfo.getManagedConnectionInfo().getXAResource();
069 if (xaResource != null) {
070 transactionManager.recoverResourceManager(xaResource);
071 getRecoveryStack().returnConnection(recoveryConnectionInfo, ConnectionReturnAction.DESTROY);
072 }
073 } catch (ResourceException e) {
074 transactionManager.recoveryError((SystemException)new SystemException("Could not obtain recovery XAResource for managedConnectionFactory " + managedConnectionFactory).initCause(e));
075 }
076 }
077
078 /**
079 * in: mcf != null, is a deployed mcf
080 * out: useable connection object.
081 */
082 public Object allocateConnection(ManagedConnectionFactory managedConnectionFactory,
083 ConnectionRequestInfo connectionRequestInfo)
084 throws ResourceException {
085 ManagedConnectionInfo mci = new ManagedConnectionInfo(managedConnectionFactory, connectionRequestInfo);
086 ConnectionInfo ci = new ConnectionInfo(mci);
087 getStack().getConnection(ci);
088 Object connection = ci.getConnectionProxy();
089 if (connection == null) {
090 connection = ci.getConnectionHandle();
091 } else {
092 // connection proxy is used only once so we can be notified
093 // by the garbage collector when a connection is abandoned
094 ci.setConnectionProxy(null);
095 }
096 return connection;
097 }
098
099 /**
100 * in: non-null connection object, from non-null mcf.
101 * connection object is not associated with a managed connection
102 * out: supplied connection object is assiciated with a non-null ManagedConnection from mcf.
103 */
104 public void associateConnection(Object connection,
105 ManagedConnectionFactory managedConnectionFactory,
106 ConnectionRequestInfo connectionRequestInfo)
107 throws ResourceException {
108 ManagedConnectionInfo mci = new ManagedConnectionInfo(managedConnectionFactory, connectionRequestInfo);
109 ConnectionInfo ci = new ConnectionInfo(mci);
110 ci.setConnectionHandle(connection);
111 getStack().getConnection(ci);
112 }
113
114 ConnectionInterceptor getConnectionInterceptor() {
115 return getStack();
116 }
117
118 //statistics
119
120 public int getPartitionCount() {
121 return getPooling().getPartitionCount();
122 }
123
124 public int getPartitionMaxSize() {
125 return getPooling().getPartitionMaxSize();
126 }
127
128 public void setPartitionMaxSize(int maxSize) throws InterruptedException {
129 getPooling().setPartitionMaxSize(maxSize);
130 }
131
132 public int getPartitionMinSize() {
133 return getPooling().getPartitionMinSize();
134 }
135
136 public void setPartitionMinSize(int minSize) {
137 getPooling().setPartitionMinSize(minSize);
138 }
139
140 public int getIdleConnectionCount() {
141 return getPooling().getIdleConnectionCount();
142 }
143
144 public int getConnectionCount() {
145 return getPooling().getConnectionCount();
146 }
147
148 public int getBlockingTimeoutMilliseconds() {
149 return getPooling().getBlockingTimeoutMilliseconds();
150 }
151
152 public void setBlockingTimeoutMilliseconds(int timeoutMilliseconds) {
153 getPooling().setBlockingTimeoutMilliseconds(timeoutMilliseconds);
154 }
155
156 public int getIdleTimeoutMinutes() {
157 return getPooling().getIdleTimeoutMinutes();
158 }
159
160 public void setIdleTimeoutMinutes(int idleTimeoutMinutes) {
161 getPooling().setIdleTimeoutMinutes(idleTimeoutMinutes);
162 }
163
164 private ConnectionInterceptor getStack() {
165 return interceptors.getStack();
166 }
167
168 private ConnectionInterceptor getRecoveryStack() {
169 return interceptors.getRecoveryStack();
170 }
171
172 private boolean getIsRecoverable() {
173 return interceptors.getRecoveryStack() != null;
174 }
175
176 //public for persistence of pooling attributes (max, min size, blocking/idle timeouts)
177 public PoolingSupport getPooling() {
178 return interceptors.getPoolingAttributes();
179 }
180
181 public interface Interceptors {
182 ConnectionInterceptor getStack();
183
184 ConnectionInterceptor getRecoveryStack();
185
186 PoolingSupport getPoolingAttributes();
187 }
188
189 public void doStart() throws Exception {
190
191 }
192
193 public void doStop() throws Exception {
194 interceptors.getStack().destroy();
195 }
196
197 public void doFail() {
198 interceptors.getStack().destroy();
199 }
200 }