river-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Michal Kleczek <michal.klec...@xpro.biz>
Subject Jini and OSGI revisited
Date Sat, 09 Oct 2010 09:09:47 GMT
Folks,

The discussion about trust and solving deserialization DoS issues brought me 
to the idea of annotating classes with Modules.

On the other hand Peter is working on ClassLoader / class identity issues.
I tried to think about it and came up with an idea that a Module can express 
that it depends on other Modules so that if there is a dependency that is 
shared between two modules classes loaded from this dependency preserve their 
ClassLoader:

interface Module {
  Module[] getDependencies();
  //... class loading methods
}

We would have to implement a ClassLoader structure that is not hierarchical 
but allows loading classes from dependencies.

BUT IT IS ALREADY DONE!!! And it is done well. It is called OSGI.
How can we leverage this?

1. Let's annotate classes with objects implementing:
interface BundleSource extends ReferentUuid {
  Iterable<? extends BundleSource> getDependencies();

  //no more multiple urls - we are a bundle
  //we can either provide everything in our bundle
  //or require dependencies to be installed
  InputStream open();
}

2. As in my original idea - we prepare BundleSources with a ProxyPreparer so 
that we know BundleSource is trusted before.

3. Let's implement a JiniBundle:
public class JiniBundle implements BundleActivator {

  //our context
  private static BundleContext bundleContext;

  //we need a package admin instance to find Bundles that
  //were used to load classes
  //have to check if it is really needed or we can safely assume
  //that ClassLoaders implement BundleReference
  private PackageAdmin packageAdmin;

  //our cache of BundleSources
  private static Map<Bundle, BundleSource> bundleSourceCache =
    new WeakHashMap();

  //used by MarshalOutputStream to annotate classes
  //will return null if we don't know the BundleSource
  public static BundleSource getSourceOf(Class c) {
    return bundleSourceCache.get(
      packageAdmin.getExportedPackage(class.getPackage().getName()).getExportingBundle());
  }

  //now the difficult part :)
  
  //cache of installed BundleSources
  private static Map<BundleSource, Reference<? extends Bundle>>
    installedBundles = new WeakHashMap();

  //used by MarshalInputStream to resolve classes
  //
  public static Class loadClass(
    BundleSource source, String name, ClassLoader defaultLoader) {
    if (source == null) {
      return defaultLoader.loadClass(name);
    }
    try {
      makeSureInstalled(source).loadClass(name);
    }
    catch (RuntimeException e) {
      throw e;
    }
    catch (Exception e) {
      throw new ClassNotFoundException();
    }
  }

  private static Bundle makeSureInstalled(BundleSource source) {
      Bundle b = installedBundles.get(source);
      if (b == null) {

        //prepare
        source = bundleSourcePreparer.prepare(source);

        //make sure dependencies are installed
        for (final BundleSource dependency : source.getDependencies()) {
          makeSureInstalled(dependency);
        }
        
        //install
        Bundle b = bundleContext.installBundle(
          source.getReferentUuid().toString(), source.open());
        
        //cache
        bundleSourceCache.put(b, source);
        installedBundles.put(source, new WeakReference(b));
      }
      return b;
  }

  //osgi activation follows...

}

Further details to be thought out:
1. Especially important is handling of lost codebase problem. OSGI implicitly 
imports exported packages so it can happen that the service interface is 
loaded from a bundle that was not installed by JiniBundle - so there is no 
BundleSource associated with it.
2. Similar to lost codebase problem is that OSGI container can load a class 
from a different bundle than the one we would want to so the codebase will not 
be lost but will be different than the original one.
3. Sure there are many more - and the question is whether OSGI is the best 
choice (maybe classworlds or NetBeans platform is better)

But in the end - would it be a nirvana? :)

Michal

Mime
View raw message