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.spring.transaction;
018:
019: import java.util.Hashtable;
020: import java.util.List;
021: import java.util.Map;
022:
023: import org.compass.core.CompassException;
024: import org.compass.core.CompassSession;
025: import org.compass.core.CompassTransaction;
026: import org.compass.core.CompassTransaction.TransactionIsolation;
027: import org.compass.core.config.CompassSettings;
028: import org.compass.core.spi.InternalCompassSession;
029: import org.compass.core.transaction.AbstractTransactionFactory;
030: import org.compass.core.transaction.InternalCompassTransaction;
031: import org.compass.core.transaction.TransactionException;
032: import org.springframework.transaction.PlatformTransactionManager;
033: import org.springframework.transaction.support.TransactionSynchronization;
034: import org.springframework.transaction.support.TransactionSynchronizationManager;
035:
036: public class SpringSyncTransactionFactory extends
037: AbstractTransactionFactory {
038:
039: private static ThreadLocal<PlatformTransactionManager> transactionManagerHolder = new ThreadLocal<PlatformTransactionManager>();
040:
041: private static String transactionManagerKey = SpringSyncTransactionFactory.class
042: .getName();
043:
044: private PlatformTransactionManager transactionManager;
045:
046: private transient Map<TransactionSynchronization, CompassSession> currentSessionMap = new Hashtable<TransactionSynchronization, CompassSession>();
047:
048: public static void setTransactionManager(
049: PlatformTransactionManager transactionManager) {
050: transactionManagerHolder.set(transactionManager);
051: }
052:
053: protected void doConfigure(CompassSettings settings) {
054: this .transactionManager = transactionManagerHolder.get();
055: if (transactionManager == null) {
056: transactionManager = (PlatformTransactionManager) settings
057: .getRegistry(transactionManagerKey);
058: }
059: if (transactionManager != null) {
060: settings.setRegistry(transactionManagerKey,
061: transactionManager);
062: }
063: transactionManagerHolder.set(null);
064: }
065:
066: protected boolean isWithinExistingTransaction(
067: InternalCompassSession session) throws CompassException {
068: return TransactionSynchronizationManager
069: .isActualTransactionActive();
070: // return ExistingSpringTxCompassHelper.isExistingTransaction(transactionManager);
071: }
072:
073: protected InternalCompassTransaction doBeginTransaction(
074: InternalCompassSession session,
075: TransactionIsolation transactionIsolation)
076: throws CompassException {
077: SpringSyncTransaction tr = new SpringSyncTransaction(this );
078: // transaction manager might be null, we rely then on the fact that the
079: // transaction started before
080: tr.begin(transactionManager, session, transactionIsolation,
081: commitBeforeCompletion);
082: return tr;
083: }
084:
085: protected InternalCompassTransaction doContinueTransaction(
086: InternalCompassSession session) throws CompassException {
087: SpringSyncTransaction tr = new SpringSyncTransaction(this );
088: tr.join(session);
089: return tr;
090: }
091:
092: public CompassSession getTransactionBoundSession()
093: throws CompassException {
094: TransactionSynchronization sync = lookupTransactionSynchronization();
095: if (sync == null) {
096: return null;
097: }
098: return currentSessionMap.get(sync);
099: }
100:
101: protected void doBindSessionToTransaction(CompassTransaction tr,
102: CompassSession session) throws CompassException {
103: TransactionSynchronization sync = lookupTransactionSynchronization();
104: if (sync == null) {
105: throw new TransactionException(
106: "Failed to find compass registered spring synchronization");
107: }
108: currentSessionMap.put(sync, session);
109: }
110:
111: public void unbindSessionFromTransaction(
112: TransactionSynchronization sync) {
113: currentSessionMap.remove(sync);
114: }
115:
116: private TransactionSynchronization lookupTransactionSynchronization()
117: throws TransactionException {
118: if (!TransactionSynchronizationManager
119: .isSynchronizationActive()) {
120: if (transactionManager == null) {
121: throw new TransactionException(
122: "Either spring trnasction synchronization is not active, or a spring transaction has not been started, "
123: + "you might want to check if transactionManager is set on LocalCompassBean configuration, so compass can start one by itself");
124: } else {
125: return null;
126: }
127: }
128: List syncs = TransactionSynchronizationManager
129: .getSynchronizations();
130: for (int i = 0; i < syncs.size(); i++) {
131: Object sync = syncs.get(i);
132: if (sync instanceof SpringSyncTransaction.SpringTransactionSynchronization) {
133: SpringSyncTransaction.SpringTransactionSynchronization springSync = (SpringSyncTransaction.SpringTransactionSynchronization) sync;
134: if (springSync.getSession().getCompass() == compass) {
135: return springSync;
136: }
137: }
138: }
139: return null;
140: }
141:
142: public PlatformTransactionManager getTransactionManager() {
143: return this.transactionManager;
144: }
145: }
|