org.apache.meecrowave.jta.TransactionContext Maven / Gradle / Ivy
/*
* 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.meecrowave.jta;
import javax.enterprise.context.ContextNotActiveException;
import javax.enterprise.context.spi.AlterableContext;
import javax.enterprise.context.spi.Contextual;
import javax.enterprise.context.spi.CreationalContext;
import javax.transaction.Status;
import javax.transaction.Synchronization;
import javax.transaction.TransactionManager;
import javax.transaction.TransactionScoped;
import javax.transaction.TransactionSynchronizationRegistry;
import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
public class TransactionContext implements AlterableContext, Synchronization {
private TransactionManager transactionManager;
private Map, BeanInstanceBag>> componentInstanceMap;
void init(final TransactionManager transactionManager, final TransactionSynchronizationRegistry transactionSynchronizationRegistry) {
this.transactionManager = transactionManager;
this.componentInstanceMap = Map.class.cast(Proxy.newProxyInstance(
Thread.currentThread().getContextClassLoader(), new Class>[]{Map.class},
new TransactionalMapHandler(this, transactionSynchronizationRegistry)));
}
@Override
public boolean isActive() {
try {
final int status = transactionManager.getTransaction().getStatus();
return status == Status.STATUS_ACTIVE || status == Status.STATUS_MARKED_ROLLBACK
|| status == Status.STATUS_PREPARED || status == Status.STATUS_PREPARING
|| status == Status.STATUS_COMMITTING || status == Status.STATUS_ROLLING_BACK
|| status == Status.STATUS_UNKNOWN;
} catch (final Throwable e) {
return false;
}
}
private void checkActive() {
if (!isActive()) {
throw new ContextNotActiveException("Context with scope annotation @" + getScope().getName() + " is not active");
}
}
private BeanInstanceBag createContextualBag(final Contextual contextual, final CreationalContext creationalContext) {
final BeanInstanceBag bag = new BeanInstanceBag<>(creationalContext);
componentInstanceMap.put(contextual, bag);
return bag;
}
@Override
public T get(final Contextual component) {
checkActive();
final BeanInstanceBag bag = componentInstanceMap.get(component);
if (bag != null) {
return (T) bag.beanInstance;
}
return null;
}
@Override
public T get(Contextual contextual, CreationalContext creationalContext) {
checkActive();
return getInstance(contextual, creationalContext);
}
private T getInstance(final Contextual contextual, final CreationalContext creationalContext) {
T instance;
BeanInstanceBag bag = (BeanInstanceBag) componentInstanceMap.get(contextual);
if (bag == null) {
bag = createContextualBag(contextual, creationalContext);
}
instance = bag.beanInstance;
if (instance != null) {
return instance;
} else {
if (creationalContext == null) {
return null;
} else {
instance = bag.create(contextual);
}
}
return instance;
}
@Override
public void destroy(final Contextual> contextual) {
BeanInstanceBag> instance = componentInstanceMap.get(contextual);
if (instance == null) {
return;
}
CreationalContext