+
+ private static final class ModuleInvocationHandler extends AbstractInvocationHandler {
+ private final DeadlockMonitor deadlockMonitor;
+ private final ModuleIdentifier moduleIdentifier;
+ private final Module module;
+
+ // optimization: subsequent calls to getInstance MUST return the same value
+ // during transaction,
+ // so it is safe to cache the response
+ private Object cachedInstance;
+
+ ModuleInvocationHandler(final DeadlockMonitor deadlockMonitor, final ModuleIdentifier moduleIdentifier,
+ final Module module) {
+ this.deadlockMonitor = Preconditions.checkNotNull(deadlockMonitor);
+ this.moduleIdentifier = Preconditions.checkNotNull(moduleIdentifier);
+ this.module = Preconditions.checkNotNull(module);
+ }
+
+ @Override
+ @SuppressWarnings("checkstyle:avoidHidingCauseException")
+ protected Object handleInvocation(final Object proxy, final Method method, final Object[] args)
+ throws Throwable {
+ boolean isGetInstance = "getInstance".equals(method.getName());
+ if (isGetInstance) {
+ if (cachedInstance != null) {
+ return cachedInstance;
+ }
+
+ Preconditions.checkState(deadlockMonitor.isAlive(), "Deadlock monitor is not alive");
+ deadlockMonitor.setCurrentlyInstantiatedModule(moduleIdentifier);
+ }
+ try {
+ Object response = method.invoke(module, args);
+ if (isGetInstance) {
+ cachedInstance = response;
+ }
+ return response;
+ } catch (final InvocationTargetException e) {
+ throw e.getCause();
+ } finally {
+ if (isGetInstance) {
+ deadlockMonitor.setCurrentlyInstantiatedModule(null);
+ }
+ }
+ }
+ }
+
+ public void put(final ModuleIdentifier moduleIdentifier, final Module module, final ModuleFactory moduleFactory,
+ final ModuleInternalInfo maybeOldInternalInfo,
+ final TransactionModuleJMXRegistration transactionModuleJMXRegistration, final boolean isDefaultBean,
+ final BundleContext bundleContext) {