How to discovering types exported by OSGi bundle w

2019-01-26 21:00发布

问题:

Basically i want to discover if a jar implements any number of interfaces wihtout activating or starting the bundle. Is it possible to read the meta data from the meta-inf from an API just like the container does but without activating a bundle ?

I want to use OSGi to support plugins of which numerous interfaces will be published and i would like to know which interfaces are implemented by a bundle when the user uploads without activating the bundle etc.

回答1:

I do not think it is possible to discover what services a bundle is going to provide, because this can happen from inside the Java code, without any meta-data about it. Of course, if you use Declarative Services, there is a meta-data file. Also, the bundle needs to import (or provide) the service interface, which may give you a hint (but not more).

You can inspect what Java packages a bundles imports and exports without activating it. If you are willing to install (not resolve, not activate) it, you can query it. The Felix or Equinox shells can list those packages after all.

Here is the relevant source from Felix' shell. It uses the PackageAdmin service:

 public void execute(String s, PrintStream out, PrintStream err)
{
    // Get package admin service.
    ServiceReference ref = m_context.getServiceReference(
        org.osgi.service.packageadmin.PackageAdmin.class.getName());
    PackageAdmin pa = (ref == null) ? null : 
        (PackageAdmin) m_context.getService(ref);

    // ... 

    Bundle bundle = m_context.getBundle( bundleId );
    ExportedPackage[] exports = pa.getExportedPackages(bundle);

    // ...
}


回答2:

you may try something like below. Find the ".class" files in the exported packages using bundle.findResource(...) method.

 BundleContext context = bundle.getBundleContext();
  ServiceReference ref = context.getServiceReference(PackageAdmin.class.getName());
  PackageAdmin packageAdmin = (PackageAdmin)context.getService(ref);
  List<Class> agentClasses = new ArrayList<Class>();
  ExportedPackage[] exportedPackages = packageAdmin.getExportedPackages(bundle);
  for(ExportedPackage ePackage : exportedPackages){
      String packageName = ePackage.getName();
      String packagePath = "/"+packageName.replace('.', '/');
      //find all the class files in current exported package
      Enumeration clazzes = bundle.findEntries(packagePath, "*.class", false);
      while(clazzes.hasMoreElements()){
       URL url = (URL)clazzes.nextElement();
       String path = url.getPath();
       int index = path.lastIndexOf("/");
       int endIndex = path.length()-6;//Strip ".class" substring
       String className = path.substring(index+1, endIndex);
       String fullClassName=packageName+"."+className;
       try {
     Class clazz = bundle.loadClass(fullClassName);
     //check whether the class is annotated with Agent tag.
     if(clazz.isAnnotationPresent(Agent.class))
      agentClasses.add(clazz);
    } catch (ClassNotFoundException e) { 
     e.printStackTrace();
    }
      }
  }


标签: osgi