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
pgppvOvlCf033.pgp
Description: OpenPGP digital signature
_______________________________________________ OSGi Developer Mail List osgi-dev@mail.osgi.org https://mail.osgi.org/mailman/listinfo/osgi-dev