如何在不安装/激活的情况下发现OSGi包导出的类型?

时间:2023-01-18 12:33:41

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 ?

基本上我想发现一个jar是否实现了任何数量的接口,而不是激活或启动捆绑。是否有可能从容器中读取meta-inf中的元数据,但没有激活包?

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.

我想使用OSGi来支持将发布大量接口的插件,并且我想知道当用户上传而不激活捆绑包时哪些接口是由bundle实现的。

2 个解决方案

#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).

我认为不可能发现捆绑包将提供哪些服务,因为这可能发生在Java代码内部,没有任何关于它的元数据。当然,如果使用Declarative Services,则会有一个元数据文件。此外,bundle需要导入(或提供)服务接口,这可能会给你一个提示(但不是更多)。

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.

您可以检查捆绑包导入和导出的Java包而不激活它。如果您愿意安装(不解析,不激活)它,您可以查询它。 Felix或Equinox shell可以列出这些包。

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

以下是Felix'hell的相关来源。它使用PackageAdmin服务:

 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.

你可以试试下面的东西。使用bundle.findResource(...)方法在导出的包中查找“.class”文件。

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

#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).

我认为不可能发现捆绑包将提供哪些服务,因为这可能发生在Java代码内部,没有任何关于它的元数据。当然,如果使用Declarative Services,则会有一个元数据文件。此外,bundle需要导入(或提供)服务接口,这可能会给你一个提示(但不是更多)。

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.

您可以检查捆绑包导入和导出的Java包而不激活它。如果您愿意安装(不解析,不激活)它,您可以查询它。 Felix或Equinox shell可以列出这些包。

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

以下是Felix'hell的相关来源。它使用PackageAdmin服务:

 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.

你可以试试下面的东西。使用bundle.findResource(...)方法在导出的包中查找“.class”文件。

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