| /* |
| * 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; |
| } |
| } |
| |
| } |