Yearly Archives: 2010

2 posts

Reading Object Streams in OSGi

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 () );
    }

}

Equinox Remote Terminal Console

Although Equinox offers some sort of remote TCP console it is not what you actually want to have. Being limited to one session, having not authentication and allowing the user to execute any command and shut down the OSGi container is not an option for a productive system.

In OpenSCADA we faced the same problem so we simply developed an OSGi Remote Console based on Apache Mina.

Our equinox console works around the limits of the original OSGi TCP console and can simply be dropped in as a replacement.

SVN Link to the project: http://pubsvn.inavare.net/openscada/modules/aurora/trunk/org.openscada.osgi.equinox.console/

Also we played a little bit with an IRC bot that exposes the OSGi console of Equinox to an IRC server. This is not really tested and just a proof of concept. But it works. If you like check out http://pubsvn.inavare.net/openscada/modules/aurora/trunk/org.openscada.osgi.equinox.ircbot/ and play with it ;-)