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-17 02:54:22 +0200 (Wed, 17 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    }