package org.apache.openwebbeans.environment.osgi.integration;
import java.util.Collection;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.enterprise.context.spi.CreationalContext;
import javax.enterprise.event.Event;
import javax.enterprise.inject.Instance;
import javax.enterprise.inject.spi.AnnotatedType;
import javax.enterprise.inject.spi.BeanManager;
import javax.enterprise.inject.spi.InjectionTarget;
import org.apache.webbeans.config.WebBeansContext;
import org.apache.webbeans.spi.ContainerLifecycle;
import org.osgi.cdi.api.integration.CDIContainer;
import org.osgi.cdi.api.integration.CDIContainers;
import org.osgi.cdi.impl.extension.CDIOSGiExtension;
import org.osgi.framework.Bundle;
/**
*
* @author Mathieu ANCELIN - SERLI (mathieu.ancelin@serli.com)
*/
public class OWB {
private final static Logger LOGGER = Logger.getLogger(OWB.class.getName());
private final Bundle bundle;
private boolean started = false;
private BeanManager manager;
private boolean hasShutdownBeenCalled = false;
private Collection<String> beanClasses;
private ContainerLifecycle lifecycle = null;
private Instance<Object> instance;
public OWB(Bundle bundle) {
this.bundle = bundle;
}
public boolean isStarted() {
return started;
}
/**
* Boots OWB and creates and returns a CDIContainerImpl instance, through which
* beans and events can be accessed.
*/
public boolean initialize() {
started = false;
// ugly hack to make jboss interceptors works.
// thank you Thread.currentThread().getContextClassLoader().loadClass()
ClassLoader old = Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
// -------------
boolean set = CDIOSGiExtension.currentBundle.get() != null;
CDIOSGiExtension.currentBundle.set(bundle.getBundleId());
try {
Enumeration beansXml = bundle.findEntries("META-INF", "beans.xml", true);
if (beansXml == null) {
return started;
}
lifecycle = WebBeansContext.currentInstance().getService(ContainerLifecycle.class);
OSGiScanner service = (OSGiScanner) WebBeansContext.currentInstance().getScannerService();
service.setBundle(bundle);
lifecycle.startApplication(bundle);
System.out.println("Starting OWB container for bundle " + bundle.getSymbolicName());
manager = lifecycle.getBeanManager();
Set<Class<?>> classes = service.getBeanClasses();
Set<String> classesName = new HashSet<String>();
for (Class<?> clazz : classes) {
classesName.add(clazz.getName());
}
beanClasses = classesName;
service.release2();
AnnotatedType annoted = manager.createAnnotatedType(InstanceHolder.class);
InjectionTarget it = manager.createInjectionTarget(annoted);
CreationalContext<?> cc = manager.createCreationalContext(null);
InstanceHolder h = (InstanceHolder) it.produce(cc);
it.inject(h, cc);
it.postConstruct(h);
instance = h.getInstance();
started = true;
} catch (Throwable t) {
t.printStackTrace();
} finally {
if (!set) {
CDIOSGiExtension.currentBundle.remove();
}
Thread.currentThread().setContextClassLoader(old);
}
return started;
}
public boolean shutdown() {
if (started) {
synchronized (this) {
if (!hasShutdownBeenCalled) {
System.out.println("Stopping OWB container for bundle " + bundle.getSymbolicName());
hasShutdownBeenCalled = true;
try {
lifecycle.stopApplication(bundle);
} catch (Throwable t) {
}
started = false;
return true;
} else {
LOGGER.log(Level.INFO, "Skipping spurious call to shutdown");
return false;
}
}
}
return false;
}
public Event getEvent() {
return instance.select(Event.class).get();
}
public BeanManager getBeanManager() {
return manager;
}
public Instance<Object> getInstance() {
return instance;
}
public Collection<String> getBeanClasses() {
return beanClasses;
}
private static class BridgeClassLoader extends ClassLoader {
private final ClassLoader delegate;
private final ClassLoader infra;
public BridgeClassLoader(ClassLoader delegate, ClassLoader infraClassLoader) {
this.delegate = delegate;
this.infra = infraClassLoader;
}
@Override
public Class<?> loadClass(String name) throws ClassNotFoundException {
Class<?> loadedClass = null;
try {
loadedClass = delegate.loadClass(name);
} catch (ClassNotFoundException cnfe) {
// todo : filter on utils class only
loadedClass = infra.loadClass(name);
}
return loadedClass;
}
}
}