/* * Copyright 2012 Red Hat, Inc. and/or its affiliates. * * Licensed under the Eclipse Public License version 1.0, available at * http://www.eclipse.org/legal/epl-v10.html */ package org.jboss.forge.furnace.container.cdi.events; import java.lang.annotation.Annotation; import java.util.ArrayDeque; import java.util.Deque; import java.util.Set; import javax.enterprise.event.Observes; import javax.enterprise.inject.Any; import javax.enterprise.inject.spi.BeanManager; import javax.enterprise.inject.spi.EventMetadata; import javax.inject.Singleton; import org.jboss.forge.furnace.addons.Addon; import org.jboss.forge.furnace.addons.AddonRegistry; import org.jboss.forge.furnace.container.cdi.impl.AddonProducer; import org.jboss.forge.furnace.container.cdi.util.BeanManagerUtils; import org.jboss.forge.furnace.event.EventManager; import org.jboss.forge.furnace.exception.ContainerException; import org.jboss.forge.furnace.util.AddonFilters; import org.jboss.weld.environment.se.events.WeldContainerEvent; /** * @author <a href="mailto:lincolnbaxter@gmail.com">Lincoln Baxter, III</a> */ @Singleton public class CrossContainerObserverMethod { private ThreadLocal<Deque<InboundEvent>> stack; public void handleEvent(@Observes @Any Object event, EventMetadata metadata, BeanManager manager) { try { if (event instanceof WeldContainerEvent) { // Do nothing. The container is booting up or shutting down return; } initStack(); Addon self = BeanManagerUtils.getContextualInstance(manager, AddonProducer.class).produceCurrentAddon(); if (self != null && !(event instanceof InboundEvent)) { Set<Annotation> qualifiers = metadata.getQualifiers(); if (!isLocal(qualifiers) && !onStack(event, qualifiers)) { try { AddonRegistry addonRegistry = BeanManagerUtils.getContextualInstance(manager, AddonRegistry.class); for (Addon addon : addonRegistry.getAddons(AddonFilters.allStarted())) { if (!self.getId().equals(addon.getId())) { EventManager remoteEventManager = addon.getEventManager(); if (remoteEventManager != null) { remoteEventManager.fireEvent(event, qualifiers.toArray(new Annotation[qualifiers.size()])); } } } } catch (Exception e) { throw new ContainerException("Problems encountered during propagation of event [" + event + "] with qualifiers [" + qualifiers + "]", e); } } } else if (event instanceof InboundEvent) { InboundEvent inboundEvent = (InboundEvent) event; try { push(inboundEvent); manager.fireEvent(inboundEvent.getEvent(), inboundEvent.getQualifiers()); } finally { pop(inboundEvent); } } } finally { cleanupStack(); } } private boolean isLocal(Set<Annotation> qualifiers) { for (Annotation annotation : qualifiers) { if (annotation instanceof Local) { return true; } } return false; } private boolean onStack(Object event, Set<Annotation> qualifiers) { InboundEvent peek = peek(); if (peek != null && peek.equals(new InboundEvent(event, qualifiers.toArray(new Annotation[qualifiers.size()])))) { return true; } return false; } private void cleanupStack() { if (stack != null && stack.get().isEmpty()) { stack.remove(); } } private void initStack() { if (stack == null) { stack = ThreadLocal.withInitial(() -> new ArrayDeque<>()); } } private InboundEvent peek() { return this.stack.get().peek(); } private InboundEvent pop(InboundEvent event) { return this.stack.get().pop(); } private void push(InboundEvent event) { this.stack.get().push(event); } }