package org.societies.comm.xmpp.xc.impl; import java.util.HashMap; import java.util.Hashtable; import java.util.Map; import org.osgi.framework.Bundle; import org.osgi.framework.FrameworkUtil; import org.osgi.framework.wiring.BundleWiring; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.societies.api.comm.xmpp.interfaces.ICommCallback; import org.societies.api.comm.xmpp.interfaces.IFeatureServer; public class ClassLoaderManager { private static Logger LOG = LoggerFactory .getLogger(ClassLoaderManager.class); private Map<Class<?>,ClassLoader> fsRegistry; private Map<Class<?>,ClassLoader> callbackRegistry; private Map<String,ClassLoader> callbackTemporary; private Bundle thisBundle; private ClassLoader thisBundlesClassLoader; public ClassLoaderManager() { thisBundle = FrameworkUtil.getBundle(this.getClass()); //thisBundlesClassLoader = getBundleClassloader(thisBundle); thisBundlesClassLoader = this.getClass().getClassLoader(); fsRegistry = new HashMap<Class<?>, ClassLoader>(); callbackRegistry = new HashMap<Class<?>, ClassLoader>(); callbackTemporary = new Hashtable<String, ClassLoader>(); // Hashtable because it is synchronized } public ClassLoader classLoaderMagic(ICommCallback callback) { LOG.debug("getting classloader for ICommCallback {}",callback.toString()); ClassLoader newClassloader = callbackRegistry.get(callback.getClass()); ClassLoader oldClassloader = Thread.currentThread().getContextClassLoader(); if (newClassloader!=null) { LOG.debug("found a classloader for this context! oldClassloader={} newClassloader={}",oldClassloader.toString(),newClassloader); Thread.currentThread().setContextClassLoader(newClassloader); return oldClassloader; } else { LOG.debug("no classloader found! contextClassLoader=",oldClassloader.toString()); } return null; } public ClassLoader classLoaderMagic(IFeatureServer fs) { LOG.debug("getting classloader for IFeatureServer {}",fs.toString()); ClassLoader newClassloader = fsRegistry.get(fs.getClass()); ClassLoader oldClassloader = Thread.currentThread().getContextClassLoader(); if (newClassloader!=null) { LOG.debug("found a classloader for this context! oldClassloader={} newClassloader={}",oldClassloader.toString(),newClassloader); Thread.currentThread().setContextClassLoader(newClassloader); return oldClassloader; } else { LOG.debug("no classloader found! contextClassLoader={}",oldClassloader.toString()); } return null; } // CISCommFactory generated comms are fixed // private ClassLoader getOldClassloader() { // ClassLoader ctcl = Thread.currentThread().getContextClassLoader(); // // // try { // ctcl.loadClass(this.getClass().getCanonicalName()); // return ctcl; // } catch (ClassNotFoundException e) { // LOG.warn("Old ClassLoader is '"+ctcl.toString()+"' instead of '"+thisBundlesClassLoader.toString()+"'!!! Forcing...", e); // Thread.currentThread().setContextClassLoader(thisBundlesClassLoader); // return thisBundlesClassLoader; // } // } public ClassLoader classLoaderMagicTemp(String id) { LOG.debug("getting classloader for request id {}",id); ClassLoader newClassloader = callbackTemporary.get(id); ClassLoader oldClassloader = Thread.currentThread().getContextClassLoader(); // not old classloader verification required here if (newClassloader!=null) { LOG.debug("found a classloader for this context! oldClassloader={} newClassloader={}",oldClassloader.toString(),newClassloader); callbackTemporary.remove(id); Thread.currentThread().setContextClassLoader(newClassloader); return oldClassloader; } else { LOG.debug("no classloader found! contextClassLoader={}",oldClassloader.toString()); } return null; } public void addTempClassloader(String id, Object payload) { // using context classloader that was used to send the IQ //callbackTemporary.put(id, Thread.currentThread().getContextClassLoader()); // using the payload classloader that was used to send the IQ callbackTemporary.put(id, payload.getClass().getClassLoader()); } public void classloaderRegistry(IFeatureServer fs) { Bundle b = FrameworkUtil.getBundle(fs.getClass()); LOG.info("Class "+fs.getClass().toString()+" is associated with bundle "+b.toString()); if (b.getBundleId()!=thisBundle.getBundleId()) fsRegistry.put(fs.getClass(), getBundleClassloader(b)); } public void classloaderRegistry(ICommCallback messageCallback) { Bundle b = FrameworkUtil.getBundle(messageCallback.getClass()); LOG.info("Class "+messageCallback.getClass().toString()+" is associated with bundle "+b.toString()); if (b.getBundleId()!=thisBundle.getBundleId()) callbackRegistry.put(messageCallback.getClass(), getBundleClassloader(b)); } private ClassLoader getBundleClassloader(Bundle b) { // http://tomsondev.bestsolution.at/2011/10/15/find-classloader-for-a-given-osgi-bundle/ BundleWiring wiring = (BundleWiring)b.adapt(BundleWiring.class); return wiring.getClassLoader(); } }