Reading an object from an ObjectInputStream is easy. But using OSGi it can be a little bit more difficult. Due to the class loader system of OSGi the ObjectInputStream might not know the class that was stored. Assume you have a Bundle A, B and C. B provides the storing capabilities that stores objects somewhere and C provides the data object itself. Now if A tells B to store some object from C this will not be a problem, since the object class is attached to the object instance. But reading back the object will result in a ClassNotFoundException since B has no reference to C and therefore does not know any classes of C.
One solution of course would be to add a dependency from B to C. But that is probably not what you want. Another way would be using Eclipses “Buddy” policies workaround for problems like this. In this case the bundle B would declare itself capable of working with the buddy system and C would declare itself a “buddy of B”. This turns around the reference. While this is a possible way if you cannot change the logic in B (like existing third party libraries that have to be used) it also has some drawbacks. First of all you commit to using Eclipse/Equinox since this is not covered by OSGi. Also you still have to declare those dependencies from C to B.
On the other hand you can sub-class the ObjectInputStream and override “resolveClass” to let the bundle resolve the class instead of the “current” classloader. Passing the bundle A to that input stream you would have all the classes you need.
Check out the following sample implementation:
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectStreamClass;
import org.osgi.framework.Bundle;
/**
* An object input stream which loads its classes from the provided bundle.
* @author Jens Reimann
*
*/
public class BundleObjectInputStream extends ObjectInputStream
{
private final Bundle bundle;
public BundleObjectInputStream ( final InputStream in, final Bundle bundle ) throws IOException
{
super ( in );
this.bundle = bundle;
}
@Override
protected Class<?> resolveClass ( final ObjectStreamClass desc ) throws IOException, ClassNotFoundException
{
return this.bundle.loadClass ( desc.getName () );
}
}