package org.apache.aries.transaction; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.HashMap; import java.util.Map; import javax.transaction.Transactional; import javax.transaction.Transactional.TxType; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class ComponentTxData { private static final Logger LOG = LoggerFactory.getLogger(ComponentTxData.class); private static final int BANNED_MODIFIERS = Modifier.PRIVATE | Modifier.STATIC; Map<Method, TxType> txMap = new HashMap<Method, Transactional.TxType>(); private boolean isTransactional; private Class<?> beanClass; public ComponentTxData(Class<?> c) { beanClass = c; isTransactional = false; // Check class hierarchy Class<?> current = c; while (current != Object.class) { isTransactional |= parseTxData(current); for (Class<?> iface : current.getInterfaces()) { isTransactional |= parseTxData(iface); } current = current.getSuperclass(); } } TxType getEffectiveType(Method m) { if (txMap.containsKey(m)) { return txMap.get(m); } try { Method effectiveMethod = beanClass.getDeclaredMethod(m.getName(), m.getParameterTypes()); TxType txType = txMap.get(effectiveMethod); txMap.put(m, txType); return txType; } catch (NoSuchMethodException e) { // NOSONAR return getFromMethod(m); } catch (SecurityException e) { throw new RuntimeException("Security exception when determining effective method", e); // NOSONAR } } private TxType getFromMethod(Method m) { try { Method effectiveMethod = beanClass.getMethod(m.getName(), m.getParameterTypes()); TxType txType = txMap.get(effectiveMethod); txMap.put(m, txType); return txType; } catch (NoSuchMethodException e1) { LOG.debug("No method found when scanning for transactions", e1); return null; } catch (SecurityException e1) { throw new RuntimeException("Security exception when determining effective method", e1); // NOSONAR } } private boolean parseTxData(Class<?> c) { boolean shouldAssignInterceptor = false; TxType defaultType = getType(c.getAnnotation(Transactional.class)); if (defaultType != null) { shouldAssignInterceptor = true; } for (Method m : c.getDeclaredMethods()) { try { TxType t = getType(m.getAnnotation(Transactional.class)); if (t != null) { assertAllowedModifier(m); txMap.put(m, t); shouldAssignInterceptor = true; } else if (defaultType != null){ txMap.put(m, defaultType); } } catch(IllegalStateException e) { LOG.warn("Invalid transaction annoation found", e); } } return shouldAssignInterceptor; } private static TxType getType(Transactional jtaT) { return (jtaT != null) ? jtaT.value() : null; } private static void assertAllowedModifier(Method m) { if ((m.getModifiers() & BANNED_MODIFIERS) != 0) { throw new IllegalArgumentException("Transaction annotation is not allowed on private or static method " + m); } } public boolean isTransactional() { return isTransactional; } public Class<?> getBeanClass() { return beanClass; } }