Skip to content

Commit

Permalink
Implement EventManager API
Browse files Browse the repository at this point in the history
  • Loading branch information
lincolnthree committed Aug 2, 2013
1 parent d9aee10 commit 0fd76f0
Show file tree
Hide file tree
Showing 9 changed files with 318 additions and 36 deletions.
Expand Up @@ -7,72 +7,119 @@
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.CDI;
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.services.Exported;
import org.jboss.forge.furnace.spi.ExportedInstance;
import org.jboss.forge.furnace.spi.ServiceRegistry;
import org.jboss.forge.furnace.util.AddonFilters;
import org.jboss.forge.furnace.util.Annotations;

/**
* @author <a href="mailto:lincolnbaxter@gmail.com">Lincoln Baxter, III</a>
*/
@Singleton
public class CrossContainerObserverMethod
{
public void handleEvent(@Observes @Any Object event, EventMetadata metadata)
private ThreadLocal<Deque<InboundEvent>> stack;

public void handleEvent(@Observes @Any Object event, EventMetadata metadata, BeanManager manager)
{
if (Annotations.isAnnotationPresent(event.getClass(), Exported.class))
try
{
Set<Annotation> qualifiers = metadata.getQualifiers();
try
initStack();

Addon self = BeanManagerUtils.getContextualInstance(manager, AddonProducer.class).produceCurrentAddon();
if (self != null && Annotations.isAnnotationPresent(event.getClass(), Exported.class))
{
ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
ClassLoader eventClassLoader = event.getClass().getClassLoader();
if (contextClassLoader.equals(eventClassLoader))
{
AddonRegistry addonRegistry = CDI.current().select(AddonRegistry.class).get();
for (Addon addon : addonRegistry.getAddons(AddonFilters.allStarted()))
Set<Annotation> qualifiers = metadata.getQualifiers();
if (!onStack(event, qualifiers))
try
{
// Events should not be fired back into the container from which they originated
ClassLoader addonClassLoader = addon.getClassLoader();
if (!(event.getClass().getClassLoader().equals(addonClassLoader)
|| contextClassLoader.equals(addonClassLoader)
|| ClassLoader.getSystemClassLoader().equals(eventClassLoader)))
AddonRegistry addonRegistry = BeanManagerUtils.getContextualInstance(manager, AddonRegistry.class);
for (Addon addon : addonRegistry.getAddons(AddonFilters.allStarted()))
{
ServiceRegistry addonServiceRegistry = addon.getServiceRegistry();
if (addonServiceRegistry != null)
if (!self.getId().equals(addon.getId()))
{
ExportedInstance<BeanManager> exportedInstance = addonServiceRegistry
.getExportedInstance(BeanManager.class);
if (exportedInstance != null)
EventManager remoteEventManager = addon.getEventManager();
if (remoteEventManager != null)
{
BeanManager manager = exportedInstance.get();
manager.fireEvent(event, qualifiers.toArray(new Annotation[] {}));
remoteEventManager.fireEvent(event, qualifiers.toArray(new Annotation[] {}));
}
}
}
}
}
catch (Exception e)
{
throw new ContainerException("Problems encountered during propagation of event [" + event
+ "] with qualifiers [" + qualifiers + "]", e);
}
}
catch (Exception e)
else if (event instanceof InboundEvent)
{
throw new ContainerException("Problems encountered during propagation of event [" + event
+ "] with qualifiers [" + qualifiers + "]", e);
try
{
push((InboundEvent) event);
manager.fireEvent(((InboundEvent) event).getEvent(), ((InboundEvent) event).getQualifiers());
}
finally
{
pop((InboundEvent) event);
}
}
}
else
finally
{
// do not propagate non-remote org.jboss.forge.furnace.container.cdi.events to other containers.
cleanupStack();
}
}

private boolean onStack(Object event, Set<Annotation> qualifiers)
{
InboundEvent peek = peek();
if (peek != null && peek.equals(new InboundEvent(event, qualifiers.toArray(new Annotation[] {}))))
return true;
return false;
}

private void cleanupStack()
{
if (stack != null && stack.get() != null && stack.get().isEmpty())
stack.remove();
}

private void initStack()
{
if (stack == null)
stack = new ThreadLocal<Deque<InboundEvent>>();
if (stack.get() == null)
stack.set(new ArrayDeque<InboundEvent>());
}

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);
}
}
@@ -0,0 +1,44 @@
/*
* Copyright 2013 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 javax.enterprise.inject.spi.BeanManager;

import org.jboss.forge.furnace.addons.Addon;
import org.jboss.forge.furnace.event.EventException;
import org.jboss.forge.furnace.event.EventManager;

/**
* @author <a href="mailto:lincolnbaxter@gmail.com">Lincoln Baxter, III</a>
*
*/
public class EventManagerImpl implements EventManager
{
private Addon addon;
private BeanManager manager;

public EventManagerImpl(Addon addon, BeanManager manager)
{
this.addon = addon;
this.manager = manager;
}

@Override
public void fireEvent(Object event, Annotation... qualifiers) throws EventException
{
try
{
manager.fireEvent(new InboundEvent(event, qualifiers));
}
catch (Throwable e)
{
throw new EventException("Could not propagate event to addon [" + addon + "]", e);
}
}
}
@@ -0,0 +1,22 @@
package org.jboss.forge.furnace.container.cdi.events;

import javax.enterprise.inject.Produces;
import javax.inject.Singleton;

@Singleton
public class EventManagerProducer
{
private EventManagerImpl manager;

@Produces
@Singleton
public EventManagerImpl produce()
{
return manager;
}

public void setEventManager(EventManagerImpl manager)
{
this.manager = manager;
}
}
@@ -0,0 +1,69 @@
/*
* Copyright 2013 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.Arrays;

/**
* @author <a href="mailto:lincolnbaxter@gmail.com">Lincoln Baxter, III</a>
*
*/
public class InboundEvent
{
private Object event;
private Annotation[] qualifiers;

public InboundEvent(Object event, Annotation[] qualifiers)
{
this.event = event;
this.qualifiers = qualifiers;
}

public Object getEvent()
{
return event;
}

public Annotation[] getQualifiers()
{
return qualifiers;
}

@Override
public int hashCode()
{
final int prime = 31;
int result = 1;
result = prime * result + ((event == null) ? 0 : event.hashCode());
result = prime * result + Arrays.hashCode(qualifiers);
return result;
}

@Override
public boolean equals(Object obj)
{
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
InboundEvent other = (InboundEvent) obj;
if (event == null)
{
if (other.event != null)
return false;
}
else if (!event.equals(other.event))
return false;
if (!Arrays.equals(qualifiers, other.qualifiers))
return false;
return true;
}

}
Expand Up @@ -6,6 +6,7 @@
import javax.enterprise.inject.spi.Extension;

import org.jboss.forge.furnace.container.cdi.events.CrossContainerObserverMethod;
import org.jboss.forge.furnace.container.cdi.events.EventManagerProducer;

public class ContainerBeanRegistrant implements Extension
{
Expand All @@ -15,6 +16,7 @@ public void registerWeldSEBeans(@Observes BeforeBeanDiscovery event, BeanManager
event.addAnnotatedType(manager.createAnnotatedType(AddonRegistryProducer.class));
event.addAnnotatedType(manager.createAnnotatedType(AddonRepositoryProducer.class));
event.addAnnotatedType(manager.createAnnotatedType(CrossContainerObserverMethod.class));
event.addAnnotatedType(manager.createAnnotatedType(EventManagerProducer.class));
event.addAnnotatedType(manager.createAnnotatedType(FurnaceProducer.class));
event.addAnnotatedType(manager.createAnnotatedType(ImportedProducer.class));
event.addAnnotatedType(manager.createAnnotatedType(ServiceRegistryProducer.class));
Expand Down
Expand Up @@ -12,7 +12,7 @@ public class ServiceRegistryProducer

@Produces
@Singleton
public ServiceRegistry produceGlobalAddonRepository()
public ServiceRegistry produce()
{
return registry;
}
Expand Down
Expand Up @@ -5,6 +5,8 @@
import org.jboss.forge.furnace.Furnace;
import org.jboss.forge.furnace.addons.Addon;
import org.jboss.forge.furnace.addons.AddonRegistry;
import org.jboss.forge.furnace.container.cdi.events.EventManagerImpl;
import org.jboss.forge.furnace.container.cdi.events.EventManagerProducer;
import org.jboss.forge.furnace.container.cdi.impl.AddonProducer;
import org.jboss.forge.furnace.container.cdi.impl.AddonRegistryProducer;
import org.jboss.forge.furnace.container.cdi.impl.AddonRepositoryProducer;
Expand All @@ -17,6 +19,7 @@
import org.jboss.forge.furnace.container.cdi.weld.ModularURLScanner;
import org.jboss.forge.furnace.container.cdi.weld.ModularWeld;
import org.jboss.forge.furnace.container.cdi.weld.ModuleScanResult;
import org.jboss.forge.furnace.event.EventManager;
import org.jboss.forge.furnace.event.PostStartup;
import org.jboss.forge.furnace.event.PreShutdown;
import org.jboss.forge.furnace.lifecycle.AddonLifecycleProvider;
Expand All @@ -34,6 +37,7 @@ public class WeldAddonLifecycleProvider implements AddonLifecycleProvider
private ServiceRegistry serviceRegistry;
private BeanManager manager;
private ModularWeld weld;
private EventManagerImpl eventManager;

@Override
public void initialize(Furnace furnace, AddonRegistry registry, Addon self)
Expand Down Expand Up @@ -73,13 +77,20 @@ public void start(Addon addon) throws Exception

ContainerServiceExtension extension = BeanManagerUtils.getContextualInstance(manager,
ContainerServiceExtension.class);

ServiceRegistryProducer serviceRegistryProducer = BeanManagerUtils.getContextualInstance(manager,
ServiceRegistryProducer.class);
serviceRegistry = new ServiceRegistryImpl(furnace.getLockManager(), addon, manager, extension);
serviceRegistryProducer.setServiceRegistry(serviceRegistry);

ServiceRegistry registry = BeanManagerUtils.getContextualInstance(manager, ServiceRegistry.class);
Assert.notNull(registry, "Service registry was null.");
Assert.notNull(BeanManagerUtils.getContextualInstance(manager, ServiceRegistry.class),
"InboundEvent registry was null.");

EventManagerProducer eventManagerProducer = BeanManagerUtils.getContextualInstance(manager,
EventManagerProducer.class);
eventManager = new EventManagerImpl(addon, manager);
eventManagerProducer.setEventManager(eventManager);
Assert.notNull(BeanManagerUtils.getContextualInstance(manager, EventManager.class),
"InboundEvent registry was null.");
}
}

Expand All @@ -104,6 +115,12 @@ public void stop(Addon addon)
weld.shutdown();
}

@Override
public EventManager getEventManager(Addon addon)
{
return eventManager;
}

@Override
public ServiceRegistry getServiceRegistry(Addon addon)
{
Expand All @@ -115,5 +132,4 @@ public ControlType getControlType()
{
return ControlType.DEPENDENTS;
}

}

0 comments on commit 0fd76f0

Please sign in to comment.