Yes, you can reuse the Req/Cap model in OSGi for this. I understand the problem is that bundle A.1 uses bundle B.1 and A.2 uses B.2. If A.1 loads a resource X, then it should originate form B.1 and A.2 should load from B.2?
If you use the resource services as mandatory dependencies in DS then you must register the services with a property and use the target filter on the consuming side. A bit awkward since it should contain a version. This does not have to be the OSGi bundle version but that of course makes it easier. One trick is to make the version a Java constant. You can then refer to this constant in a bnd package version annotation AND in your target filter. (Assuming you use bnd.) Another trick is to use a class/interface specific for each application. If B exports this class R then your resource service will register a B.R and A will require B.R. Another application consisting of C and D will use D.R. Since R is now versioned, A.1 will see the B.1.R and A.2 will see the B.2.R. Then everything works out of the box. interface ResourceAvailable { URL getResource( String name ); } interface B.R extends ResourceAvailable {} interface D.R extends ResourceAvailable {} If the services are not involved in DS dependencies then there is another solution. First, A.1 must require B1 in some defined namespace. This can be osgi.wiring.bundle or osgi.wiring.package if you have a package name that is shared. You can also define your own namespace. You should then register as a DS service factory. When you get a request you get the calling bundle. Through the bundle you can find out to what bundles it is wired to in the given namespace. You can then do the resource request. Clearly, this requires that one DS component is shared between all versions of applications. In this model the easiest is to register a single service for all resources. Hope this helps, kind regards, Peter Kriens > On 26 May 2017, at 13:16, Fauth Dirk (AA-AS/EIS2-EU) > <dirk.fa...@de.bosch.com> wrote: > > Hi, > > AFAIK capabilities are used to resolve bundles. They will not help to > restrict the referenced services. That means if you reference resource > services of a special type in a consumer service, you can not specify which > service should be injected by using capabilities. > > For restricting the services that should be injected you can use the target > reference property. The value is an LDAP filter that can inspect service > properties to select the target services that should be referenced. So you > could for example specify a version property on your services and specify a > target filter in our consumer. > > It is also possible to dynamically change the target filter using the > Configuration Admin. > > I wrote about this in one of my blog posts: > http://blog.vogella.com/2016/09/26/configuring-osgi-declarative-services/ > > Mit freundlichen Grüßen / Best regards > > Dirk Fauth > > Automotive Service Solutions, ESI application (AA-AS/EIS2-EU) > Robert Bosch GmbH | Postfach 11 29 | 73201 Plochingen | GERMANY | > www.bosch.com > Tel. +49 7153 666-1155 | dirk.fa...@de.bosch.com > > Sitz: Stuttgart, Registergericht: Amtsgericht Stuttgart, HRB 14000; > Aufsichtsratsvorsitzender: Franz Fehrenbach; Geschäftsführung: Dr. Volkmar > Denner, > Prof. Dr. Stefan Asenkerschbaumer, Dr. Rolf Bulander, Dr. Stefan Hartung, Dr. > Markus Heyn, Dr. Dirk Hoheisel, > Christoph Kübel, Uwe Raschke, Peter Tyroller > > > -----Ursprüngliche Nachricht----- > Von: osgi-dev-boun...@mail.osgi.org [mailto:osgi-dev-boun...@mail.osgi.org] > Im Auftrag von Mark Raynsford > Gesendet: Freitag, 26. Mai 2017 12:54 > An: osgi-dev@mail.osgi.org > Betreff: [osgi-dev] Publishing resources with respect to versioning > > Hello. > > As stated previously, I'm working on a commercial (but open source) game > project. I'm currently working on the code to load resources into the engine > (the "resource manager"). A "resource" in this case can be more or less > anything: Sounds, images, game levels, 3D models, compiled Java code, NPC > definitions, etc. A major design requirement for the engine is to have a > strongly versioned code and resource package system with proper dependency > handling. Obviously, I'm delegating all of this work to OSGi. > > Exposing Java code as services is obviously not a problem; we use declarative > services and the like. However, I also wanted it to be possible to expose > non-code resources in some manner. A while back, I was advised to use a > BundleTracker to expose non-code resources inside bundles as services [0]. > This works well enough, but the problem is that I'm not sure how to properly > expose the services such that version constraints are respected. > > For example, let's take a naive implementation: A bundle loaded into the game > engine might have a file "/catalog.txt" listing the resources to be exported > as services. Each entry in the catalog file declares a fully qualified name > such as "com.example.images.brick", "com.example.sounds.zap", etc, and a file > inside the bundle that will be associated with this name. Resources can > depend on each other. For example, a definition for a new type of NPC might > contain a list of references to sounds that that NPC uses. The NPC definition > would refer to each sound by using its fully qualified name > ("com.example.sounds.zap", for example). > > A naive implementation might have a BundleTracker read this catalog file when > the bundle is loaded and simply publish each named resource by instantiating > a service for each and maintaining some sort of map that can associated fully > qualified resource names with services. If a resource inside a bundle states > that it depends on another resource called "com.example.sounds.zap", the > resource manager just looks up the name in the map and returns a reference to > the corresponding service. > > The problem here should be immediately obvious: If two different versions of > the same bundle are loaded then there are going to be naming conflicts. > Resource defintions are essentially loaded into one big global namespace, and > we essentially get DLL-hell for resources. > If a resource in bundle A specifies that it depends on a resource in bundle > B, but a different version of bundle B (let's call it C) was loaded > afterwards and essentially overrode the contents of B... Ouch. > > A better implementation would take into account the dependency and version > information included in the bundle manifest. So, for example, a bundle A > might declare that it depends on bundle B, and the resource manager > implementation would ensure that only the resources exported by B are visible > to A. If another version of bundle B is loaded that has a version range > incompatible with that specified by bundle A (let's call it bundle C), then A > cannot see the resources published by C. Bundle A carries on referring to > other resources using fully-qualified names as normal, and the underlying > resource manager ensures that those names are mapped to those resources in > bundle B from the perspective of A. > > I'd like to implement this, but I feel like I'd more or less be reinventing > OSGi on top of OSGi. Is there some way I can delegate all of this work back > to OSGi's resolver? From what I can see, the capability system is designed to > facilitate this sort of thing, but as it's relatively new, I can't find any > good literature on how to apply it. I'm not sure if it's even appropriate to > my needs. > > M > > [0] https://mail.osgi.org/pipermail/osgi-dev/2017-April/006312.html > _______________________________________________ > OSGi Developer Mail List > osgi-dev@mail.osgi.org > https://mail.osgi.org/mailman/listinfo/osgi-dev _______________________________________________ OSGi Developer Mail List osgi-dev@mail.osgi.org https://mail.osgi.org/mailman/listinfo/osgi-dev