Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to load a class by classname string from OSGi runtime environment?

Tags:

java

osgi

I'm making a bundle to plug on OSGi to provide user a function:

Usercase: User input the classname string and click "list" button, the corresponding class will be decompiled and show the text on GUI for user.

So here is my problem: I only have the classloader of my bundle, how can I get the OSGi container classloader that I can load the class by name from the whole OSGi container? (I expect that when OSGi starts, it will load all the bundles and all the class to memory, any class can be loaded by OSGi container classloader if it really exists and able to)

Anyone knows how to do this job? Sample codes are highly appreciated.

like image 244
JerryCai Avatar asked Jun 13 '12 08:06

JerryCai


3 Answers

I can see two possible situations that could help you.

Any visible class

You can add a statement like

DynamicImport-Package: *

to your manifest, and then try to load the class using

Class.forName("com.company.class");

All classes, exported or not

If you really need to find every available class, I'm not sure why you would want this, but you could try asking each bundle whether it 'knows' a given class. Since in this situation you could end up with multiple classes with the same name, it's up to you to pick the right one.

You could do something like

private List<Class<?>> findClass(BundleContext context, String name) {
    List<Class<?>> result = new ArrayList<Class<?>>();
    for (Bundle b : context.getBundles()) {
        try {
            Class<?> c = b.loadClass(name);
            result.add(c);
        } catch (ClassNotFoundException e) {
            // No problem, this bundle doesn't have the class
        }
    }
    return result;
}
like image 51
Angelo van der Sijpt Avatar answered Nov 23 '22 18:11

Angelo van der Sijpt


There is no sure way in OSGi to name a class only by its fully qualified class name. The reason is that two bundles can define the same class name in a different way. This is for example important if bundle A needs a lib v1.0 and bundle B needs the same lib in version 2.0.

It is possible though to name a class if you also know the bundle. So you could resolve a class from (Bundle bundle, String fqClassname)

You can implement this by using the BundleContext. From the bundle context you can list the bundles and for each bundle you can load a class.

Of course you could then also simply iterate over all those class loaders and try to find the class by name. The problem is though that it does not have to be unique. As you can print a warning in your case that might be ok.

So the key API methods you need are: Bundle[] BundleContext.getBundles() Class Bundle.loadClass()

like image 34
Christian Schneider Avatar answered Nov 23 '22 17:11

Christian Schneider


I am not entirely sure of what you are trying to do, but assuming you are building a tool that needs to do some form of processing on all application bundles while being installed in the OSGi framework, you may want to consider the OSGi Extender Pattern

  • The OSGi Extender Model, by Peter Kriens
  • OSGi 4.2: Extender Pattern and BundleTracker, by Kai Tödter
  • Extender Pattern with Automatic Servlet Registration, by Peter Kriens
like image 24
Mohamed Ragab Avatar answered Nov 23 '22 19:11

Mohamed Ragab