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: 550546 $ $Date: 2007-06-25 12:52:11 -0400 (Mon, 25 Jun 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            }
092            return connection;
093        }
094    
095        /**
096         * in: non-null connection object, from non-null mcf.
097         * connection object is not associated with a managed connection
098         * out: supplied connection object is assiciated with a non-null ManagedConnection from mcf.
099         */
100        public void associateConnection(Object connection,
101                                        ManagedConnectionFactory managedConnectionFactory,
102                                        ConnectionRequestInfo connectionRequestInfo)
103                throws ResourceException {
104            ManagedConnectionInfo mci = new ManagedConnectionInfo(managedConnectionFactory, connectionRequestInfo);
105            ConnectionInfo ci = new ConnectionInfo(mci);
106            ci.setConnectionHandle(connection);
107            getStack().getConnection(ci);
108        }
109    
110        ConnectionInterceptor getConnectionInterceptor() {
111            return getStack();
112        }
113    
114        //statistics
115    
116        public int getPartitionCount() {
117            return getPooling().getPartitionCount();
118        }
119    
120        public int getPartitionMaxSize() {
121            return getPooling().getPartitionMaxSize();
122        }
123    
124        public void setPartitionMaxSize(int maxSize) throws InterruptedException {
125            getPooling().setPartitionMaxSize(maxSize);
126        }
127    
128        public int getPartitionMinSize() {
129            return getPooling().getPartitionMinSize();
130        }
131    
132        public void setPartitionMinSize(int minSize) {
133            getPooling().setPartitionMinSize(minSize);
134        }
135    
136        public int getIdleConnectionCount() {
137            return getPooling().getIdleConnectionCount();
138        }
139    
140        public int getConnectionCount() {
141            return getPooling().getConnectionCount();
142        }
143    
144        public int getBlockingTimeoutMilliseconds() {
145            return getPooling().getBlockingTimeoutMilliseconds();
146        }
147    
148        public void setBlockingTimeoutMilliseconds(int timeoutMilliseconds) {
149            getPooling().setBlockingTimeoutMilliseconds(timeoutMilliseconds);
150        }
151    
152        public int getIdleTimeoutMinutes() {
153            return getPooling().getIdleTimeoutMinutes();
154        }
155    
156        public void setIdleTimeoutMinutes(int idleTimeoutMinutes) {
157            getPooling().setIdleTimeoutMinutes(idleTimeoutMinutes);
158        }
159    
160        private ConnectionInterceptor getStack() {
161            return interceptors.getStack();
162        }
163    
164        private ConnectionInterceptor getRecoveryStack() {
165            return interceptors.getRecoveryStack();
166        }
167    
168        private boolean getIsRecoverable() {
169            return interceptors.getRecoveryStack() != null;
170        }
171    
172        //public for persistence of pooling attributes (max, min size, blocking/idle timeouts)
173        public PoolingSupport getPooling() {
174            return interceptors.getPoolingAttributes();
175        }
176    
177        public interface Interceptors {
178            ConnectionInterceptor getStack();
179    
180            ConnectionInterceptor getRecoveryStack();
181            
182            PoolingSupport getPoolingAttributes();
183        }
184    
185        public void doStart() throws Exception {
186    
187        }
188    
189        public void doStop() throws Exception {
190            interceptors.getStack().destroy();
191        }
192    
193        public void doFail() {
194            interceptors.getStack().destroy();
195        }
196    }