Reputation: 4548
I have an active bundle called bundleA
which implements a class called Example
with a method called doSomething()
from another bundle. ExampleImpl
implements Example
and is loaded via ServiceLoader
(thanks to SPI Fly). In ExampleImpl.doSomething()
from bundleA
, I need to get the BundleWiring
of the bundle which called doSomething()
(without passing the Bundle
or BundleContext
since I cannot change the API). I can get bundleA
's BundleWiring
, but not the calling bundle's BundleWiring
:
Bundle bundleA = FrameworkUtil.getBundle(ExampleClass.class);
BundleWiring bundleWiringOfBundleA = bundle.adapt(BundleWiring.class);
How can I obtain the calling bundle's BundleWiring
?
In my particular case, the calling bundle will always be a WAB which happens to be running in Liferay Portal 7.0. So if there's a solution specific to Liferay Portal, I would accept that, but a more general OSGi solution would be fine as well.
Note that I want the calling bundle's bundle wiring not the bundle wiring of every bundle that depends on the current bundle wiring. I know that I can obtain the bundle wirings that are dependent on the current bundle wiring, but that won't help me obtain the calling bundle specifically:
Bundle bundleA = FrameworkUtil.getBundle(ExampleClass.class);
List<BundleWires> bundleWires =
bundleWiring.getProvidedWires(BundleRevision.PACKAGE_NAMESPACE);
bundleWires.get(0).getRequirerWiring();
Upvotes: 0
Views: 781
Reputation: 4548
In Liferay, the calling WAB's BundleContext
is stored in the ServletContext
as "osgi-bundlecontext"
:
BundleContext bundleContext = servletContext.getAttribute("osgi-bundlecontext");
Bundle bundle = bundleContext.getBundle();
BundleWiring bundleWiring = bundle.adapt(BundleWiring.class);
So as long as you have access to the ServletContext
in Liferay you can obtain the calling bundle's Bundle
and BundleWiring
.
Upvotes: 0
Reputation: 3062
You said you can't change the API. But can you change the calling bundles? If so, then you could have a "proxy" service that calling bundles use instead of the original one. You can then pass Bundle
and/or BundleContext
to the proxy service and put your dependency logic there.
Another option that comes to mind is using ThreadLocal
variables to pass this information to the called bundle, but I'm not sure about what side effects that approach may have.
Upvotes: -1
Reputation: 19626
You can use a BundleTracker and react on all WABs being installed. Then you can introspect each WAB and for example scan classes for annotations.
Declarative services and the existing WAB support work this way. Writing such an extender is not easy though.
Upvotes: -1
Reputation: 23958
You can't do this. OSGi does not intervene at all in cross-bundle method invocation, so the only thing you can possibly use to try to get this information is the Java call stack, accessed with Thread.currentThread().getStackTrace()
. However the StackTraceElement
objects that this returns only gives you class names not java.lang.Class
objects, so there is no way to correlate those back to bundles.
Besides being impossible, I'm very skeptical that this would ever be a good idea. You shouldn't export implementation classes at all, let alone try to make them caller-sensitive.
If you need to implement behaviour that is sensitive to the calling bundle then the canonical and correct way to achieve that is to register a service using the ServiceFactory
interface.
Upvotes: -1