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

Attachment: pgppvOvlCf033.pgp
Description: OpenPGP digital signature

_______________________________________________
OSGi Developer Mail List
osgi-dev@mail.osgi.org
https://mail.osgi.org/mailman/listinfo/osgi-dev

Reply via email to