2009-04-24 3 views
3

Grundsätzlich möchte ich herausfinden, ob ein Jar eine beliebige Anzahl von Schnittstellen implementiert, ohne das Bundle zu aktivieren oder zu starten. Ist es möglich, die Metadaten aus dem Meta-Inf von einer API zu lesen, wie es der Container tut, ohne ein Bündel zu aktivieren?Wie erkennt man Typen, die von OSGi-Bundles exportiert werden, ohne sie zu installieren/zu aktivieren?

Ich möchte OSGi verwenden Plugins, von denen zahlreiche Schnittstellen veröffentlicht wird zu unterstützen, und ich würde gerne wissen, welche Schnittstellen durch ein Bündel implementiert werden, wenn die Börse ohne das Bündel aktivieren usw.

Antwort

2

Ich glaube nicht, Es ist möglich zu ermitteln, welche Dienste ein Bundle bereitstellen wird, da dies aus dem Java-Code heraus geschehen kann, ohne dass irgendwelche Metadaten darüber vorliegen. Wenn Sie deklarative Dienste verwenden, gibt es natürlich eine Metadaten-Datei. Außerdem muss das Paket die Dienstschnittstelle importieren (oder bereitstellen), die Ihnen einen Hinweis (aber nicht mehr) geben kann.

Sie können prüfen, welche Java-Pakete ein Bundles importiert und exportiert, ohne es zu aktivieren. Wenn Sie bereit sind, es zu installieren (nicht zu lösen, nicht zu aktivieren), können Sie es abfragen. Die Felix- oder Equinox-Shells können diese Pakete immerhin auflisten.

Hier ist die relevant source from Felix' shell. Es verwendet den PackageAdmin-Dienst:

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

    // ... 
} 
+0

Vielleicht Dienstleistungen war eine Auswahl von Wörtern, im Grunde wollte ich die Fähigkeit, * alle * die Klassen zu durchlaufen, die aus einem Bündel exportiert werden. Von diesem kann ich testen, ob irgendeine Klasse eine Schnittstelle implementiert und geeignete Maßnahmen ergreift. Ich hatte das Gefühl, dass die offiziellen APIs dies nicht anbieten und es würde die Verwendung von Erweiterungen eines Implementierers usw. erfordern. Problem mit dem natürlich sind diese Dinge können geändert werden, etc. –

2

können Sie versuchen, etwas wie unten. Suchen Sie die ".class" -Dateien in den exportierten Paketen mit der Methode bundle.findResource (...).

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

Ja, aber das wird unordentlich, weil es bedeutet, dass Sie einen Blick auf die werfen müssen bündeln Sie den classspath-Eintrag im Manifest und durchsuchen Sie dann die jars und alle aufgelösten Verzeichnisse. –

Verwandte Themen