001: /*
002: * Copyright 2004-2006 the original author or authors.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package org.compass.core.transaction;
018:
019: import java.util.Map;
020: import java.util.concurrent.ConcurrentHashMap;
021: import javax.naming.InitialContext;
022: import javax.naming.NamingException;
023: import javax.transaction.Status;
024: import javax.transaction.SystemException;
025: import javax.transaction.Transaction;
026: import javax.transaction.TransactionManager;
027: import javax.transaction.UserTransaction;
028:
029: import org.compass.core.CompassException;
030: import org.compass.core.CompassSession;
031: import org.compass.core.CompassTransaction;
032: import org.compass.core.config.CompassEnvironment;
033: import org.compass.core.config.CompassSettings;
034: import org.compass.core.jndi.NamingHelper;
035: import org.compass.core.spi.InternalCompassSession;
036:
037: /**
038: * A base class for JTA transaction strategies. Associates a {@link org.compass.core.CompassSession}
039: * with the JTA {@link javax.transaction.Transaction} and uses it as the basis for begin / continue
040: * a transaction and for transaction boudn session management.
041: *
042: * @author kimchy
043: */
044: public abstract class AbstractJTATransactionFactory extends
045: AbstractTransactionFactory {
046:
047: private static final String DEFAULT_USER_TRANSACTION_NAME = "java:comp/UserTransaction";
048:
049: private transient Map<Transaction, CompassSession> currentSessionMap = new ConcurrentHashMap<Transaction, CompassSession>();
050:
051: private InitialContext context;
052:
053: private String utName;
054:
055: private UserTransaction userTransaction;
056:
057: private TransactionManager transactionManager;
058:
059: public void doConfigure(CompassSettings settings)
060: throws CompassException {
061:
062: try {
063: context = NamingHelper.getInitialContext(settings);
064: } catch (NamingException ne) {
065: throw new CompassException(
066: "Could not obtain initial context", ne);
067: }
068:
069: utName = settings
070: .getSetting(CompassEnvironment.Transaction.USER_TRANSACTION);
071:
072: TransactionManagerLookup lookup = TransactionManagerLookupFactory
073: .getTransactionManagerLookup(settings);
074: if (lookup != null) {
075: transactionManager = lookup.getTransactionManager(settings);
076: if (transactionManager == null) {
077: throw new CompassException(
078: "Failed to find transaction manager");
079: }
080: if (utName == null)
081: utName = lookup.getUserTransactionName();
082: } else {
083: throw new CompassException(
084: "Must register a transaction manager lookup using the "
085: + CompassEnvironment.Transaction.MANAGER_LOOKUP
086: + " property");
087: }
088:
089: if (utName == null) {
090: utName = DEFAULT_USER_TRANSACTION_NAME;
091: }
092:
093: boolean cacheUserTransaction = settings.getSettingAsBoolean(
094: CompassEnvironment.Transaction.CACHE_USER_TRANSACTION,
095: true);
096: if (cacheUserTransaction) {
097: if (log.isDebugEnabled()) {
098: log.debug("Caching JTA UserTransaction from Jndi ["
099: + utName + "]");
100: }
101: userTransaction = lookupUserTransaction();
102: }
103: }
104:
105: protected boolean isWithinExistingTransaction(
106: InternalCompassSession session) throws CompassException {
107: try {
108: return getUserTransaction().getStatus() != Status.STATUS_NO_TRANSACTION;
109: } catch (SystemException e) {
110: throw new CompassException(
111: "Failed to get staus on JTA transaciton", e);
112: }
113: }
114:
115: public CompassSession getTransactionBoundSession()
116: throws CompassException {
117: UserTransaction ut = getUserTransaction();
118: try {
119: if (ut.getStatus() == Status.STATUS_NO_TRANSACTION) {
120: return null;
121: }
122: Transaction tr = transactionManager.getTransaction();
123: return currentSessionMap.get(tr);
124: } catch (SystemException e) {
125: throw new TransactionException(
126: "Failed to fetch transaction bound session", e);
127: }
128: }
129:
130: protected void doBindSessionToTransaction(CompassTransaction tr,
131: CompassSession session) throws CompassException {
132: try {
133: Transaction tx = transactionManager.getTransaction();
134: currentSessionMap.put(tx, session);
135: } catch (SystemException e) {
136: throw new TransactionException(
137: "Failed to bind session to transcation", e);
138: }
139: }
140:
141: public void unbindSessionFromTransaction(Transaction tx) {
142: currentSessionMap.remove(tx);
143: }
144:
145: public TransactionManager getTransactionManager() {
146: return this .transactionManager;
147: }
148:
149: public UserTransaction getUserTransaction()
150: throws TransactionException {
151: if (userTransaction != null) {
152: return userTransaction;
153: }
154: return lookupUserTransaction();
155: }
156:
157: private UserTransaction lookupUserTransaction()
158: throws TransactionException {
159: if (log.isDebugEnabled()) {
160: log.debug("Looking for UserTransaction under [" + utName
161: + "]");
162: }
163: UserTransaction ut;
164: try {
165: ut = (UserTransaction) context.lookup(utName);
166: } catch (NamingException ne) {
167: ut = null;
168: }
169: if (ut == null) {
170: if (log.isInfoEnabled()) {
171: log
172: .info("Failed to locate a UserTransaction under ["
173: + utName
174: + "], creating UserTransactionAdapter in its place");
175: }
176: ut = new UserTransactionAdapter(transactionManager);
177: }
178: return ut;
179: }
180:
181: }
|