package org.osgi.cdi.impl.integration;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
import javax.enterprise.event.Event;
import javax.enterprise.inject.Instance;
import javax.enterprise.inject.spi.BeanManager;
import org.osgi.cdi.api.extension.events.BundleContainerInitialized;
import org.osgi.cdi.api.extension.events.BundleContainerShutdown;
import org.osgi.cdi.api.integration.CDIContainers;
import org.osgi.cdi.api.integration.CDIContainer;
import org.osgi.cdi.api.integration.CDIContainerFactory;
import org.osgi.cdi.impl.extension.CDIOSGiExtension;
import org.osgi.cdi.impl.extension.services.BundleHolder;
import org.osgi.cdi.impl.extension.services.ContainerObserver;
import org.osgi.cdi.impl.extension.services.RegistrationsHolder;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleEvent;
import org.osgi.framework.BundleListener;
import org.osgi.framework.ServiceEvent;
import org.osgi.framework.ServiceListener;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.ServiceRegistration;
/**
*
* @author Guillaume Sauthier
* @author Mathieu ANCELIN - SERLI (mathieu.ancelin@serli.com)
*/
public class IntegrationActivator implements BundleActivator, BundleListener, CDIContainers, ServiceListener {
private Map<Long, CDIContainer> managed;
private ServiceReference factoryRef = null;
private BundleContext context;
private AtomicBoolean started = new AtomicBoolean(false);
@Override
public void start(BundleContext context) throws Exception {
managed = new HashMap<Long, CDIContainer>();
this.context = context;
ServiceReference[] refs = context.getServiceReferences(CDIContainerFactory.class.getName(), null);
if (refs != null && refs.length > 0) {
factoryRef = refs[0];
startCDIOSGi();
}
context.addServiceListener(this);
}
@Override
public void stop(BundleContext context) throws Exception {
stopCDIOSGi();
}
public void startCDIOSGi() throws Exception {
started.set(true);
managed = new HashMap<Long, CDIContainer>();
for (Bundle bundle : context.getBundles()) {
if (Bundle.ACTIVE == bundle.getState()) {
startManagement(bundle);
}
}
context.addBundleListener(this);
}
public void stopCDIOSGi() throws Exception {
started.set(false);
for (Bundle bundle : context.getBundles()) {
CDIContainer holder = managed.get(bundle.getBundleId());
if (holder != null) {
stopManagement(holder.getBundle());
}
}
}
@Override
public void bundleChanged(BundleEvent event) {
switch (event.getType()) {
case BundleEvent.STARTED:
if (started.get())
startManagement(event.getBundle());
break;
case BundleEvent.STOPPED:
stopManagement(event.getBundle());
break;
}
}
private void stopManagement(Bundle bundle) {
boolean set = CDIOSGiExtension.currentBundle.get() != null;
CDIOSGiExtension.currentBundle.set(bundle.getBundleId());
CDIContainer holder = managed.get(bundle.getBundleId());
if (holder != null) {
Collection<ServiceRegistration> regs = holder.getRegistrations();
for (ServiceRegistration reg : regs) {
try {
reg.unregister();
} catch (IllegalStateException e) {
// Ignore
}
}
try {
holder.getBeanManager().fireEvent(new BundleContainerShutdown(bundle.getBundleContext()));
// unregistration for managed services. It should be done by the OSGi framework
RegistrationsHolder regsHolder = holder.getInstance().select(RegistrationsHolder.class).get();
for (ServiceRegistration r : regsHolder.getRegistrations()) {
try {
r.unregister();
} catch (Exception e) {
// the service is already unregistered if shutdown is called when bundle is stopped
// but with a manual boostrap, you can't be sure
//System.out.println("Service already unregistered.");
}
}
} catch (Throwable t) {
t.printStackTrace();
}
holder.shutdown();
managed.remove(bundle.getBundleId());
}
if (!set) {
CDIOSGiExtension.currentBundle.remove();
}
}
private void startManagement(Bundle bundle) {
boolean set = CDIOSGiExtension.currentBundle.get() != null;
CDIOSGiExtension.currentBundle.set(bundle.getBundleId());
//System.out.println("Starting management for bundle " + bundle);
CDIContainer holder = ((CDIContainerFactory) context.getService(factoryRef)).container(bundle);
holder.initialize();
if (holder.isStarted()) {
// setting contextual informations
holder.getInstance().select(BundleHolder.class).get().setBundle(bundle);
holder.getInstance().select(BundleHolder.class).get().setContext(bundle.getBundleContext());
holder.getInstance().select(ContainerObserver.class).get().setContainers(this);
holder.getInstance().select(ContainerObserver.class).get().setCurrentContainer(holder);
// fire container start
ServicePublisher publisher = new ServicePublisher(holder.getBeanClasses(),
bundle, holder.getInstance(),
((CDIContainerFactory) context.getService(factoryRef)).getContractBlacklist());
// registering publishable services
publisher.registerAndLaunchComponents();
holder.getBeanManager().fireEvent(new BundleContainerInitialized(bundle.getBundleContext()));
Collection<ServiceRegistration> regs = new ArrayList<ServiceRegistration>();
BundleContext bundleContext = bundle.getBundleContext();
try {
regs.add(
bundleContext.registerService(Event.class.getName(),
holder.getEvent(),
null));
regs.add(
bundleContext.registerService(BeanManager.class.getName(),
holder.getBeanManager(),
null));
regs.add(
bundleContext.registerService(Instance.class.getName(),
holder.getInstance(),
null));
} catch (Throwable t) {
// Ignore
}
holder.setRegistrations(regs);
managed.put(bundle.getBundleId(), holder);
}
if (!set) {
CDIOSGiExtension.currentBundle.remove();
}
}
@Override
public void serviceChanged(ServiceEvent event) {
try {
ServiceReference[] refs = context.getServiceReferences(CDIContainerFactory.class.getName(), null);
if (ServiceEvent.REGISTERED == event.getType()) {
if (!started.get() && refs != null && refs.length > 0) {
factoryRef = refs[0];
startCDIOSGi();
}
} else if (ServiceEvent.UNREGISTERING == event.getType()) {
if (started.get() && (refs == null || refs.length == 0)) {
factoryRef = null;
stopCDIOSGi();
}
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
@Override
public Iterator<CDIContainer> iterator() {
return managed.values().iterator();
}
}