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.geronimo.connector.outbound.connectionmanagerconfig.PartitionedPool;
023 import org.apache.geronimo.connector.outbound.connectionmanagerconfig.PoolingSupport;
024 import org.apache.geronimo.connector.outbound.connectionmanagerconfig.TransactionSupport;
025 import org.apache.geronimo.connector.outbound.connectiontracking.ConnectionTracker;
026 import org.apache.geronimo.transaction.manager.RecoverableTransactionManager;
027 import org.slf4j.Logger;
028 import org.slf4j.LoggerFactory;
029
030 /**
031 * GenericConnectionManager sets up a connection manager stack according to the
032 * policies described in the attributes.
033 *
034 * @version $Rev: 723385 $ $Date: 2008-12-04 12:55:02 -0500 (Thu, 04 Dec 2008) $
035 */
036 public class GenericConnectionManager extends AbstractConnectionManager {
037 protected static final Logger log = LoggerFactory.getLogger(AbstractSinglePoolConnectionInterceptor.class);
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 }