SLING-7086 : Register bundles with context of extended bundle

git-svn-id: https://svn.apache.org/repos/asf/sling/trunk@1806138 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/pom.xml b/pom.xml
index 64002f3..220b081 100644
--- a/pom.xml
+++ b/pom.xml
@@ -22,7 +22,7 @@
     <parent>
         <groupId>org.apache.sling</groupId>
         <artifactId>sling</artifactId>
-        <version>30</version>
+        <version>31</version>
         <relativePath/>
     </parent>
 
diff --git a/src/main/java/org/apache/sling/bundleresource/impl/Activator.java b/src/main/java/org/apache/sling/bundleresource/impl/Activator.java
index a2d8aa2..5233f6e 100644
--- a/src/main/java/org/apache/sling/bundleresource/impl/Activator.java
+++ b/src/main/java/org/apache/sling/bundleresource/impl/Activator.java
@@ -42,30 +42,19 @@
 
     private final Map<Long, BundleResourceProvider[]> bundleResourceProviderMap = new HashMap<>();
 
-    private volatile BundleContext bundleContext;
-
     /**
      * @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext)
      */
     @Override
     public void start(final BundleContext context) throws Exception {
-
-        this.bundleContext = context;
-
         context.addBundleListener(this);
 
-        try {
-            final Bundle[] bundles = context.getBundles();
-            for (final Bundle bundle : bundles) {
-                if (bundle.getState() == Bundle.ACTIVE) {
-                    // add bundle resource provider for active bundles
-                    addBundleResourceProvider(bundle);
-                }
+        final Bundle[] bundles = context.getBundles();
+        for (final Bundle bundle : bundles) {
+            if (bundle.getState() == Bundle.ACTIVE) {
+                // add bundle resource provider for active bundles
+                addBundleResourceProvider(bundle);
             }
-        } catch (Throwable t) {
-            log.error(
-                "activate: Problem while registering bundle resources for existing bundles",
-                t);
         }
 
         BundleResourceWebConsolePlugin.initPlugin(context);
@@ -79,7 +68,16 @@
         BundleResourceWebConsolePlugin.destroyPlugin();
 
         context.removeBundleListener(this);
-        this.bundleContext = null;
+        for(final BundleResourceProvider[] providers : this.bundleResourceProviderMap.values()) {
+            for(final BundleResourceProvider p : providers) {
+                try {
+                    p.unregisterService();
+                } catch ( final IllegalStateException ise) {
+                    // might happen on shutdown
+                }
+            }
+        }
+        this.bundleResourceProviderMap.clear();
     }
 
     /**
@@ -108,38 +106,62 @@
     // ---------- Bundle provided resources -----------------------------------
 
     private void addBundleResourceProvider(final Bundle bundle) {
-        final String prefixes = bundle.getHeaders().get(
-            BUNDLE_RESOURCE_ROOTS);
-        if (prefixes != null) {
-            log.debug(
-                "addBundleResourceProvider: Registering resources '{}' for bundle {}/{} as service ",
-                new Object[] { prefixes, bundle.getSymbolicName(),
-                    bundle.getBundleId() });
+        BundleResourceProvider[] providers = null;
+        try {
+            synchronized ( this ) {
+                // on startup we might get here twice for a bundle (listener and activator)
+                if ( bundleResourceProviderMap.get(bundle.getBundleId()) != null ) {
+                    return;
+                }
+                final String prefixes = bundle.getHeaders().get(BUNDLE_RESOURCE_ROOTS);
+                if (prefixes != null) {
+                    log.debug(
+                        "addBundleResourceProvider: Registering resources '{}' for bundle {}:{} ({}) as service ",
+                        new Object[] { prefixes, bundle.getSymbolicName(), bundle.getVersion(),
+                            bundle.getBundleId() });
 
-            final MappedPath[] roots = BundleResourceProvider.getRoots(bundle, prefixes);
-            final BundleResourceProvider[] providers = new BundleResourceProvider[roots.length];
+                    final MappedPath[] roots = BundleResourceProvider.getRoots(bundle, prefixes);
+                    providers = new BundleResourceProvider[roots.length];
 
-            int index = 0;
-            for(final MappedPath path : roots) {
-                final BundleResourceProvider brp = new BundleResourceProvider(bundle, path);
-                final long id = brp.registerService(bundleContext);
-                providers[index] = brp;
-                bundleResourceProviderMap.put(bundle.getBundleId(), providers);
+                    int index = 0;
+                    for(final MappedPath path : roots) {
+                        final BundleResourceProvider brp = new BundleResourceProvider(bundle, path);
+                        providers[index] = brp;
 
-                log.debug("addBundleResourceProvider: Service ID = {}", id);
-                index++;
+                        index++;
+                    }
+                    bundleResourceProviderMap.put(bundle.getBundleId(), providers);
+                }
             }
+            if ( providers != null ) {
+                for(final BundleResourceProvider provider : providers) {
+                    final long id = provider.registerService();
+                    log.debug("addBundleResourceProvider: Service ID = {}", id);
+                }
+            }
+        } catch (final Throwable t) {
+            log.error(
+                "activate: Problem while registering bundle resources for bundle "
+                     + bundle.getSymbolicName() + ":" + bundle.getVersion() + " (" + bundle.getBundleId() + ")",
+                t);
         }
     }
 
     private void removeBundleResourceProvider(final Bundle bundle) {
-        final BundleResourceProvider[] brp = bundleResourceProviderMap.remove(bundle.getBundleId());
+        final BundleResourceProvider[] brp;
+        synchronized ( this ) {
+            brp = bundleResourceProviderMap.remove(bundle.getBundleId());
+        }
         if (brp != null) {
             log.debug(
-                "removeBundleResourceProvider: Unregistering resources for bundle {}/{}",
-                new Object[] { bundle.getSymbolicName(), bundle.getBundleId() });
+                "removeBundleResourceProvider: Unregistering resources for bundle {}:{} ({})",
+                new Object[] { bundle.getSymbolicName(), bundle.getVersion(), bundle.getBundleId() });
             for(final BundleResourceProvider provider : brp) {
-                provider.unregisterService();
+                try {
+                    provider.unregisterService();
+                } catch ( final IllegalStateException ise) {
+                    // might happen on shutdown
+                }
             }
         }
     }
diff --git a/src/main/java/org/apache/sling/bundleresource/impl/BundleResourceProvider.java b/src/main/java/org/apache/sling/bundleresource/impl/BundleResourceProvider.java
index c24f3c1..baa13d4 100644
--- a/src/main/java/org/apache/sling/bundleresource/impl/BundleResourceProvider.java
+++ b/src/main/java/org/apache/sling/bundleresource/impl/BundleResourceProvider.java
@@ -31,7 +31,6 @@
 import org.apache.sling.spi.resource.provider.ResourceContext;
 import org.apache.sling.spi.resource.provider.ResourceProvider;
 import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleContext;
 import org.osgi.framework.Constants;
 import org.osgi.framework.ServiceRegistration;
 
@@ -76,7 +75,7 @@
 
     //---------- Service Registration
 
-    long registerService(final BundleContext context) {
+    long registerService() {
         final Dictionary<String, Object> props = new Hashtable<>();
         props.put(Constants.SERVICE_DESCRIPTION,
             "Provider of bundle based resources");
@@ -84,9 +83,8 @@
         props.put(ResourceProvider.PROPERTY_ROOT, getRoot());
         props.put(PROP_BUNDLE, this.bundle.getBundle().getBundleId());
 
-        serviceRegistration = context.registerService(ResourceProvider.class, this, props);
-        return (Long) serviceRegistration.getReference().getProperty(
-            Constants.SERVICE_ID);
+        serviceRegistration = this.bundle.getBundle().getBundleContext().registerService(ResourceProvider.class, this, props);
+        return (Long) serviceRegistration.getReference().getProperty(Constants.SERVICE_ID);
     }
 
     void unregisterService() {