package org.jboss.weld.environment.osgi.integration; import java.util.HashMap; import java.util.Map; import org.jboss.weld.bootstrap.api.Singleton; import org.jboss.weld.bootstrap.api.SingletonProvider; import org.osgi.cdi.impl.extension.CDIOSGiExtension; import org.osgi.framework.Bundle; import org.osgi.framework.FrameworkUtil; /** * * @author Mathieu ANCELIN - SERLI (mathieu.ancelin@serli.com) */ public class BundleSingletonProvider extends SingletonProvider { @Override public <T> Singleton<T> create(Class<? extends T> expectedType) { return new BundleSingleton<T>(expectedType); } private static class BundleSingleton<T> implements Singleton<T> { private static Map<String, Bundle> classes = new HashMap<String, Bundle>(); private final Map<Long, T> store = new HashMap<Long, T>(); private final Class<? extends T> clazz; public BundleSingleton(Class<? extends T> clazz) { this.clazz = clazz; } private Long getId() { Long value = CDIOSGiExtension.currentBundle.get(); // fix with a patched version of weld ProxyMethodHandler // if (value == null) { // return FrameworkUtil.getBundle(ProxyMethodHandler.currentCaller.get()).getBundleId(); // } return value; } @Override public T get() { if (!store.containsKey(getId())) { T maybeObject = null; Throwable t = new Throwable(); for (StackTraceElement element : t.getStackTrace()) { String className = element.getClassName(); if (!className.startsWith("org.jboss.weld") && !className.startsWith("java") && !className.startsWith("org.apache.felix.framework")) { if (!classes.containsKey(className)) { //System.out.println("\u001b[1;31mAnalyzing stacktrace for class " + clazz.getName() + ": \u001b[m"); //System.out.println("\u001b[0;31m" + className + "." + element.getMethodName() + "\u001b[m"); Class<?> maybe = null; try { maybe = this.getClass().getClassLoader().loadClass(className); } catch (ClassNotFoundException ex) { //System.out.println("CNFE " + element.getClassName()); // Ignore } if (maybe != null) { Bundle bundle = FrameworkUtil.getBundle(maybe); if (bundle != null) { classes.put(className, bundle); } } } Bundle maybeBundle = classes.get(className); if (maybeBundle != null) { if (!maybeBundle.getSymbolicName().equals("org.jboss.weld.osgi.weld-osgi")) { CDIOSGiExtension.currentBundle.set(maybeBundle.getBundleId()); maybeObject = get(); CDIOSGiExtension.currentBundle.remove(); if (maybeObject != null) { return maybeObject; } break; } } } } throw new IllegalStateException("Singleton is not set for bundle " + getId()); } return store.get(getId()); } @Override public void set(T object) { store.put(getId(), object); } @Override public void clear() { store.remove(getId()); } @Override public boolean isSet() { return store.containsKey(getId()); } } }