blob: 77bde5036b48ed8ffddbe80d625bac4c5f480d67 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.felix.transaction.internal;
import java.util.Map;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import javax.transaction.Transaction;
import javax.transaction.Status;
import javax.transaction.SystemException;
import javax.transaction.xa.XAException;
import org.apache.geronimo.transaction.manager.GeronimoTransactionManager;
import org.apache.geronimo.transaction.manager.TransactionLog;
import org.apache.geronimo.transaction.manager.XidFactory;
import org.apache.geronimo.transaction.manager.TransactionManagerMonitor;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionException;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import org.springframework.transaction.support.TransactionSynchronization;
import org.springframework.transaction.jta.JtaTransactionManager;
/**
*/
public class GeronimoPlatformTransactionManager extends GeronimoTransactionManager implements PlatformTransactionManager {
private final PlatformTransactionManager platformTransactionManager;
private final Map<Transaction, SuspendedResourcesHolder> suspendedResources = new ConcurrentHashMap<Transaction, SuspendedResourcesHolder>();
public GeronimoPlatformTransactionManager() throws XAException {
platformTransactionManager = new JtaTransactionManager(this, this);
registerTransactionAssociationListener();
}
public GeronimoPlatformTransactionManager(int defaultTransactionTimeoutSeconds) throws XAException {
super(defaultTransactionTimeoutSeconds);
platformTransactionManager = new JtaTransactionManager(this, this);
registerTransactionAssociationListener();
}
public GeronimoPlatformTransactionManager(int defaultTransactionTimeoutSeconds, TransactionLog transactionLog) throws XAException {
super(defaultTransactionTimeoutSeconds, transactionLog);
platformTransactionManager = new JtaTransactionManager(this, this);
registerTransactionAssociationListener();
}
public GeronimoPlatformTransactionManager(int defaultTransactionTimeoutSeconds, XidFactory xidFactory, TransactionLog transactionLog) throws XAException {
super(defaultTransactionTimeoutSeconds, xidFactory, transactionLog);
platformTransactionManager = new JtaTransactionManager(this, this);
registerTransactionAssociationListener();
}
public TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException {
return platformTransactionManager.getTransaction(definition);
}
public void commit(TransactionStatus status) throws TransactionException {
platformTransactionManager.commit(status);
}
public void rollback(TransactionStatus status) throws TransactionException {
platformTransactionManager.rollback(status);
}
protected void registerTransactionAssociationListener() {
addTransactionAssociationListener(new TransactionManagerMonitor() {
public void threadAssociated(Transaction transaction) {
try {
if (transaction.getStatus() == Status.STATUS_ACTIVE) {
SuspendedResourcesHolder holder = suspendedResources.remove(transaction);
if (holder != null && holder.getSuspendedSynchronizations() != null) {
TransactionSynchronizationManager.setActualTransactionActive(true);
TransactionSynchronizationManager.setCurrentTransactionReadOnly(holder.isReadOnly());
TransactionSynchronizationManager.setCurrentTransactionName(holder.getName());
TransactionSynchronizationManager.initSynchronization();
for (Iterator<?> it = holder.getSuspendedSynchronizations().iterator(); it.hasNext();) {
TransactionSynchronization synchronization = (TransactionSynchronization) it.next();
synchronization.resume();
TransactionSynchronizationManager.registerSynchronization(synchronization);
}
}
}
} catch (SystemException e) {
return;
}
}
public void threadUnassociated(Transaction transaction) {
try {
if (transaction.getStatus() == Status.STATUS_ACTIVE) {
if (TransactionSynchronizationManager.isSynchronizationActive()) {
List<?> suspendedSynchronizations = TransactionSynchronizationManager.getSynchronizations();
for (Iterator<?> it = suspendedSynchronizations.iterator(); it.hasNext();) {
((TransactionSynchronization) it.next()).suspend();
}
TransactionSynchronizationManager.clearSynchronization();
String name = TransactionSynchronizationManager.getCurrentTransactionName();
TransactionSynchronizationManager.setCurrentTransactionName(null);
boolean readOnly = TransactionSynchronizationManager.isCurrentTransactionReadOnly();
TransactionSynchronizationManager.setCurrentTransactionReadOnly(false);
TransactionSynchronizationManager.setActualTransactionActive(false);
SuspendedResourcesHolder holder = new SuspendedResourcesHolder(null, suspendedSynchronizations, name, readOnly);
suspendedResources.put(transaction, holder);
}
}
} catch (SystemException e) {
return;
}
}
});
}
/**
* Holder for suspended resources.
* Used internally by <code>suspend</code> and <code>resume</code>.
*/
private static class SuspendedResourcesHolder {
private final Object suspendedResources;
private final List<?> suspendedSynchronizations;
private final String name;
private final boolean readOnly;
public SuspendedResourcesHolder(
Object suspendedResources, List<?> suspendedSynchronizations, String name, boolean readOnly) {
this.suspendedResources = suspendedResources;
this.suspendedSynchronizations = suspendedSynchronizations;
this.name = name;
this.readOnly = readOnly;
}
public Object getSuspendedResources() {
return suspendedResources;
}
public List<?> getSuspendedSynchronizations() {
return suspendedSynchronizations;
}
public String getName() {
return name;
}
public boolean isReadOnly() {
return readOnly;
}
}
}