基本上我想发现jar是否在激活或启动bundle时实现了任意数量的接口。是否有可能从容器中读取meta-inf中的元数据,就像容器一样,但没有激活包?
我想使用OSGi来支持将发布大量接口的插件,我想知道当用户上传而不激活捆绑包时,捆绑包实现了哪些接口。
答案 0 :(得分:2)
我认为不可能发现捆绑包将提供哪些服务,因为这可能发生在Java代码内部,而没有任何关于它的元数据。当然,如果您使用Declarative Services,则会有一个元数据文件。此外,捆绑包需要导入(或提供)服务接口,这可能会给你一个提示(但不是更多)。
您可以检查捆绑包导入和导出的Java包而不激活它。 如果您愿意安装(不解析,不激活)它,您可以查询它。毕竟Felix或Equinox shell可以列出这些包。
这是relevant source from 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);
// ...
}
答案 1 :(得分:2)
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();
}
}
}