That's pretty much the same code as I just wrote for DS :-)

The only difference I see is that I used the BundleVersion rather than the 
bundle id for comparison of "wired to the same bundle".  It's unlikely but 
perhaps conceivable that the extender itself might be present in two versions 
perhaps during an upgrade.  Anyway I used

m_bundle.adapt(BundleRevision.class).equals(wire.getProvider())

which probably should factor out the adapt so it only happens once :-)

thanks!!
david jencks

On Mar 10, 2015, at 9:54 AM, Manuel Holzleitner <[email protected]> 
wrote:

> With your help, I tried to quickly implement this approach according to your 
> suggestions for the camel-core example (see source snippet below) and tested 
> it in combination with the subsystem module and correct 
> require/provide-capabilities headers. Maybe you could briefly look over the 
> extenderCapabilityWired() method to check whether this is how the "requires 
> wiring" part should be implemented or if there is an easier or better way to 
> do it. 
> 
> In general, I prefer this second option since also no (optional) dependency 
> to the subsystem API needs to be established by the extender (in this case 
> camel-core) and it seems to be aligned to the OSGi spec, as well.
> 
>     ....
>     public void start(BundleContext context) throws Exception {
>         LOG.info("Camel activator starting");
> 
>         bundleId = context.getBundle().getBundleId();
>         tracker = new 
> BundleTracker(context.getBundle(Constants.SYSTEM_BUNDLE_LOCATION).getBundleContext(),
>  Bundle.ACTIVE, this);
>         tracker.open();
> 
>         LOG.info("Camel activator started");
>     }
> 
>     public void stop(BundleContext context) throws Exception {
>         LOG.info("Camel activator stopping");
>         tracker.close();
>         LOG.info("Camel activator stopped");
>     }
> 
>     public Object addingBundle(Bundle bundle, BundleEvent event) {
>         LOG.debug("Bundle started: {}", bundle.getSymbolicName());
> 
>         if (extenderCapabilityWired(bundle)) {
>             List<BaseService> r = new ArrayList<BaseService>();
>             registerComponents(bundle, r);
>             registerLanguages(bundle, r);
>             registerDataFormats(bundle, r);
>             registerTypeConverterLoader(bundle, r);
>             for (BaseService service : r) {
>                 service.register();
>             }
>             resolvers.put(bundle.getBundleId(), r);
>         }
> 
>         return bundle;
>     }
> 
>     private boolean extenderCapabilityWired(Bundle bundle) {
>         BundleWiring wiring = bundle.adapt(BundleWiring.class);
>         List<BundleWire> requiredWires = 
> wiring.getRequiredWires(ExtenderNamespace.EXTENDER_NAMESPACE);
>         for (BundleWire requiredWire : requiredWires) {
>             if 
> ("org.apache.camel".equals(requiredWire.getCapability().getAttributes().get(ExtenderNamespace.EXTENDER_NAMESPACE)))
>  {
>                 if (this.bundleId == 
> requiredWire.getProviderWiring().getBundle().getBundleId()) {
>                     LOG.debug("Bundle {} extender capability wired to this 
> extender implementation.", bundle.getBundleId());
>                     return true;
>                 } else {
>                     LOG.info("Bundle {} ignored since extender capability is 
> not wired to this extender implementation.", bundle.getBundleId());
>                     return false;
>                 }
>             }
>         }
>         LOG.debug("Bundle {} does not require extender capability.", 
> bundle.getBundleId());
> 
>         return true;
>     }
>     ...
> 
> On Fri, Mar 6, 2015 at 7:04 PM, David Jencks <[email protected]> wrote:
> I really think dragging in any awareness of subsystems is going to make 
> things disastrously more complicated than they need to be.  The upcoming R6 
> DS 1.3 spec mentions the approach I suggest of listening on the system bundle 
> for DS implementations that want to work for bundles in isolated environments 
> (such as subsystems).  The extender capability/requirement/wiring bit is part 
> of the spec.  The (trunk, unreleased) Felix DS implementation has a 
> configuration flag to choose whether to use its' own bundle or the system 
> bundle for bundle tracking, and exposes an appropriate extender capability.  
> bnd trunk now adds an extender requirement for bundles that end up using the 
> 1.3 DS namespace (or you request it using an option).  I don't think we 
> implemented the "requires wiring" bit yet though. 
> 
> thanks
> david jencks
> 
> On Mar 6, 2015, at 10:40 AM, Manuel Holzleitner 
> <[email protected]> wrote:
> 
>> Hi, 
>> 
>> thanks for your information. I agree that case 2b should match in this case. 
>> It's a very good point that the camel extender within an subsystem needs to 
>> extend for the subsystem context and only in the root subsystem on the 
>> framework context. But how should the camel-core extender find out in which 
>> subsystem it resides?
>> 
>> I sketched the following solution according to what you proposed:
>>     ...
>>     public void start(BundleContext context) throws Exception {
>>         LOG.info("Camel activator starting");
>> 
>>         BundleContext trackerContext = context;
>>         ServiceReference serviceReference = 
>> context.getServiceReference("org.osgi.service.subsystem.Subsystem");
>>         if (serviceReference != null) {
>>             org.osgi.service.subsystem.Subsystem subsystem = 
>> (org.osgi.service.subsystem.Subsystem) context.getService(serviceReference);
>>             if (subsystem != null) {
>>                 LOG.debug("Camel activator starting in subsystem: {}", 
>> subsystem);
>> 
>>                 if 
>> (subsystem.getSymbolicName().equals(org.osgi.service.subsystem.SubsystemConstants.ROOT_SUBSYSTEM_SYMBOLICNAME))
>>  {
>>                     trackerContext = 
>> context.getBundle(Constants.SYSTEM_BUNDLE_LOCATION).getBundleContext();
>>                 } else {
>>                     trackerContext = subsystem.getBundleContext();
>>                 }
>>             }
>>         }
>> 
>>         tracker = new BundleTracker(trackerContext, Bundle.ACTIVE, this);
>>         tracker.open();
>>         LOG.info("Camel activator started");
>>     }
>>     ...
>> 
>> I also needed to add an optional Import-Package to 
>> org.osgi.service.subsystem package and a optional dependency to 
>> osgi.enterprise 5.0.0 so that this mechanism is only active for containers 
>> with subsystem features.
>> First tests showed that the bundle tracker events are received properly in 
>> the camel extender in the root subsystem also for subsystems. I would need 
>> to further test this on different subsystem levels and check the service 
>> registration for correct subsystem isolation. Do you think this should be 
>> the right way to do it?
>> 
>> The alternative proposal with the "global" extender pattern also sounds 
>> interesting but now I'm wondering which of those options should be 
>> preferred. Since you mentioned that this approach seems to be a common 
>> pattern could you point me to an actual extender implementation that uses 
>> this approach?
>> 
>> Thanks for your help!
>> Manuel
>> 
>> On Fri, Mar 6, 2015 at 4:14 PM, David Bosschaert 
>> <[email protected]> wrote:
>> Hi David
>> 
>> On 6 March 2015 at 14:48, David Jencks <[email protected]> wrote:
>> > I'm not sure what the "synthesized bundle" you are talking about is.  
>> > Subsystems run off resolver hooks.
>> 
>> AFAIK synthesized bundles appear for every isolated subsystem. If you
>> want to see an example see bundle 20 in the following example:
>> http://coderthoughts.blogspot.com/2014/01/osgi-subsytems-on-apache-felix.html
>> 
>> Best regards,
>> 
>> David
>> 
> 
> 

Reply via email to