/*
* JBoss, Home of Professional Open Source.
* Copyright 2013, Red Hat, Inc., and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package com.arjuna.ats.jta.cdi;
import com.arjuna.ats.jta.common.jtaPropertyManager;
import com.arjuna.ats.jta.logging.jtaLogger;
import javax.enterprise.context.ContextNotActiveException;
import javax.enterprise.context.spi.Context;
import javax.enterprise.context.spi.Contextual;
import javax.enterprise.context.spi.CreationalContext;
import javax.enterprise.inject.spi.PassivationCapable;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.transaction.*;
import java.lang.annotation.Annotation;
import java.util.HashMap;
import java.util.Map;
/**
* @author paul.robinson@redhat.com 01/05/2013
*/
public class TransactionContext implements Context {
private static TransactionManager transactionManager;
private static TransactionSynchronizationRegistry transactionSynchronizationRegistry;
private Map<Transaction, TransactionScopeCleanup> transactions = new HashMap<Transaction, TransactionScopeCleanup>();
@Override
public Class<? extends Annotation> getScope() {
return TransactionScoped.class;
}
public <T> T get(Contextual<T> contextual, CreationalContext<T> creationalContext) {
if (!isActive()) {
throw new ContextNotActiveException();
}
if (contextual == null) {
throw new RuntimeException(jtaLogger.i18NLogger.get_contextual_is_null());
}
PassivationCapable bean = (PassivationCapable) contextual;
TransactionSynchronizationRegistry tsr = getTransactionSynchronizationRegistry();
Object resource = tsr.getResource(bean.getId());
if (resource != null) {
return (T) resource;
} else if (creationalContext != null) {
Transaction currentTransaction = getCurrentTransaction();
T t = contextual.create(creationalContext);
tsr.putResource(bean.getId(), t);
synchronized (transactions) {
TransactionScopeCleanup synch = transactions.get(currentTransaction);
if (synch == null) {
synch = new TransactionScopeCleanup(this, currentTransaction);
transactions.put(currentTransaction, synch);
}
synch.registerBean(contextual, creationalContext, t);
}
return t;
} else {
return null;
}
}
public <T> T get(Contextual<T> contextual) {
return get(contextual, null);
}
public boolean isActive() {
Transaction transaction = getCurrentTransaction();
if (transaction == null) {
return false;
}
try {
int currentStatus = transaction.getStatus();
return currentStatus == Status.STATUS_ACTIVE ||
currentStatus == Status.STATUS_MARKED_ROLLBACK ||
currentStatus == Status.STATUS_PREPARED ||
currentStatus == Status.STATUS_UNKNOWN ||
currentStatus == Status.STATUS_PREPARING ||
currentStatus == Status.STATUS_COMMITTING ||
currentStatus == Status.STATUS_ROLLING_BACK;
} catch (SystemException e) {
throw new RuntimeException(jtaLogger.i18NLogger.get_error_getting_tx_status(), e);
}
}
void cleanupScope(Transaction transaction) {
synchronized (transactions) {
transactions.remove(transaction);
}
}
private Transaction getCurrentTransaction() {
try {
TransactionManager tm = getTransactionManager();
return tm.getTransaction();
} catch (SystemException e) {
throw new RuntimeException(jtaLogger.i18NLogger.get_error_getting_current_tx(), e);
}
}
private TransactionManager getTransactionManager() {
// ignore findbugs warning about incorrect lazy initialization of static field since the values are looked up via JNDI
// (ie there is no object construction during initialization)
if (transactionManager == null) {
try {
InitialContext initialContext = new InitialContext();
transactionManager = (TransactionManager) initialContext.lookup(jtaPropertyManager.getJTAEnvironmentBean().getTransactionManagerJNDIContext());
} catch (NamingException e) {
throw new ContextNotActiveException(jtaLogger.i18NLogger.get_could_not_lookup_tm(), e);
}
}
return transactionManager;
}
private TransactionSynchronizationRegistry getTransactionSynchronizationRegistry() {
// ignore findbugs warning about incorrect lazy initialization of static field since the values are looked up via JNDI
// (ie there is no object construction during initialization)
if (transactionSynchronizationRegistry == null) {
try {
InitialContext initialContext = new InitialContext();
transactionSynchronizationRegistry = (TransactionSynchronizationRegistry) initialContext.lookup(jtaPropertyManager.getJTAEnvironmentBean().getTransactionSynchronizationRegistryJNDIContext());
} catch (NamingException e) {
throw new ContextNotActiveException(jtaLogger.i18NLogger.get_could_not_lookup_tsr(), e);
}
}
return transactionSynchronizationRegistry;
}
}