基本上我想发现一个 jar 是否实现了任意数量的接口而不激活或启动包。是否可以像容器一样从 API 的 meta-inf 读取元数据,但无需激活捆绑包?
我想使用 OSGi 来支持将发布许多接口的插件,并且我想知道当用户上传而不激活捆绑包等时捆绑包实现了哪些接口。
基本上我想发现一个 jar 是否实现了任意数量的接口而不激活或启动包。是否可以像容器一样从 API 的 meta-inf 读取元数据,但无需激活捆绑包?
我想使用 OSGi 来支持将发布许多接口的插件,并且我想知道当用户上传而不激活捆绑包等时捆绑包实现了哪些接口。
我认为不可能发现捆绑软件将提供哪些服务,因为这可能发生在 Java 代码内部,而没有任何关于它的元数据。当然,如果您使用声明式服务,则有一个元数据文件。此外,bundle 需要导入(或提供)服务接口,这可能会给您一些提示(但不会更多)。
您可以在不激活它的情况下检查捆绑导入和导出的 Java 包。如果你愿意安装(不解析,不激活),可以查询。Felix 或 Equinox shell 毕竟可以列出这些包。
这是Felix' shell 的相关来源。它使用 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);
// ...
}
你可以试试下面的东西。使用 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();
}
}
}