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.transaction.TransactionManager;
021    
022    import org.apache.commons.logging.Log;
023    import org.apache.commons.logging.LogFactory;
024    import org.apache.geronimo.connector.outbound.connectionmanagerconfig.PartitionedPool;
025    import org.apache.geronimo.connector.outbound.connectionmanagerconfig.PoolingSupport;
026    import org.apache.geronimo.connector.outbound.connectionmanagerconfig.TransactionSupport;
027    import org.apache.geronimo.connector.outbound.connectiontracking.ConnectionTracker;
028    import org.apache.geronimo.transaction.manager.RecoverableTransactionManager;
029    
030    /**
031     * GenericConnectionManager sets up a connection manager stack according to the
032     * policies described in the attributes.
033     *
034     * @version $Rev: 559268 $ $Date: 2007-07-25 02:52:53 +0200 (Wed, 25 Jul 2007) $
035     */
036    public class GenericConnectionManager extends AbstractConnectionManager {
037        protected static final Log log = LogFactory.getLog(AbstractSinglePoolConnectionInterceptor.class.getName());
038    
039        //default constructor for use as endpoint
040        public GenericConnectionManager() {
041            super();
042        }
043    
044        /**
045         *
046         * @param transactionSupport configuration of transaction support
047         * @param pooling configuration of pooling
048         * @param subjectSource If not null, use container managed security, getting the Subject from the SubjectSource
049         * @param connectionTracker tracks connections between calls as needed
050         * @param transactionManager transaction manager
051         * @param name name
052         * @param classLoader classloader this component is running in.
053         */
054        public GenericConnectionManager(TransactionSupport transactionSupport,
055                                        PoolingSupport pooling,
056                                        SubjectSource subjectSource,
057                                        ConnectionTracker connectionTracker,
058                                        RecoverableTransactionManager transactionManager,
059                                        String name,
060                                        ClassLoader classLoader) {
061            super(new InterceptorsImpl(transactionSupport, pooling, subjectSource, name, connectionTracker, transactionManager, classLoader), transactionManager);
062        }
063    
064        private static class InterceptorsImpl implements AbstractConnectionManager.Interceptors {
065    
066            private final ConnectionInterceptor stack;
067            private final ConnectionInterceptor recoveryStack;
068            private final PoolingSupport poolingSupport;
069    
070            /**
071             * Order of constructed interceptors:
072             * <p/>
073             * ConnectionTrackingInterceptor (connectionTracker != null)
074             * TCCLInterceptor
075             * ConnectionHandleInterceptor
076             * TransactionCachingInterceptor (useTransactions & useTransactionCaching)
077             * TransactionEnlistingInterceptor (useTransactions)
078             * SubjectInterceptor (realmBridge != null)
079             * SinglePoolConnectionInterceptor or MultiPoolConnectionInterceptor
080             * LocalXAResourceInsertionInterceptor or XAResourceInsertionInterceptor (useTransactions (&localTransactions))
081             * MCFConnectionInterceptor
082             */
083            public InterceptorsImpl(TransactionSupport transactionSupport,
084                                    PoolingSupport pooling,
085                                    SubjectSource subjectSource,
086                                    String name,
087                                    ConnectionTracker connectionTracker,
088                                    TransactionManager transactionManager,
089                                    ClassLoader classLoader) {
090                //check for consistency between attributes
091                if (subjectSource == null && pooling instanceof PartitionedPool && ((PartitionedPool) pooling).isPartitionBySubject()) {
092                    throw new IllegalStateException("To use Subject in pooling, you need a SecurityDomain");
093                }
094    
095                //Set up the interceptor stack
096                MCFConnectionInterceptor tail = new MCFConnectionInterceptor();
097                ConnectionInterceptor stack = tail;
098    
099                stack = transactionSupport.addXAResourceInsertionInterceptor(stack, name);
100                stack = pooling.addPoolingInterceptors(stack);
101                if (log.isTraceEnabled()) {
102                    log.trace("Connection Manager " + name + " installed pool " + stack);
103                }
104    
105                this.poolingSupport = pooling;
106                stack = transactionSupport.addTransactionInterceptors(stack, transactionManager);
107    
108                if (subjectSource != null) {
109                    stack = new SubjectInterceptor(stack, subjectSource);
110                }
111    
112                if (transactionSupport.isRecoverable()) {
113                    this.recoveryStack = new TCCLInterceptor(stack, classLoader);
114                } else {
115                    this.recoveryStack = null;
116                }
117                
118    
119                stack = new ConnectionHandleInterceptor(stack);
120                stack = new TCCLInterceptor(stack, classLoader);
121                if (connectionTracker != null) {
122                    stack = new ConnectionTrackingInterceptor(stack,
123                            name,
124                            connectionTracker);
125                }
126                tail.setStack(stack);
127                this.stack = stack;
128            }
129    
130            public ConnectionInterceptor getStack() {
131                return stack;
132            }
133    
134            public ConnectionInterceptor getRecoveryStack() {
135                return recoveryStack;
136            }
137            
138            public PoolingSupport getPoolingAttributes() {
139                return poolingSupport;
140            }
141    
142        }
143    
144    }