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.
I can see two possible situations that could help you.
You can add a statement like
DynamicImport-Package: *
to your manifest, and then try to load the class using
Class.forName("com.company.class");
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;
}
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()
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With