FELIX-4467 Configure global extender capability

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1590350 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/Activator.java b/scr/src/main/java/org/apache/felix/scr/impl/Activator.java
index ebfb0d6..9ab6180 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/Activator.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/Activator.java
@@ -51,7 +51,7 @@
     static final String PACKAGEADMIN_CLASS = "org.osgi.service.packageadmin.PackageAdmin";
 
     // Our configuration from bundle context properties and Config Admin
-    private static ScrConfiguration m_configuration = new ScrConfiguration();
+    private static ScrConfiguration m_configuration;
 
     // this bundle's context
     private static BundleContext m_context;
@@ -75,6 +75,7 @@
     private ComponentActorThread m_componentActor;
 
     public Activator() {
+        m_configuration = new ScrConfiguration( this );
         setSynchronous(true);
     }
 
@@ -89,20 +90,53 @@
     {
         m_context = context;
         m_bundle = context.getBundle();
-        super.start(context);
-    }
-
-    protected void doStart() throws Exception {
         // require the log service
         m_logService = new ServiceTracker( m_context, LOGSERVICE_CLASS, null );
         m_logService.open();
+        // get the configuration
+        m_configuration.start( m_context ); //this will call restart, which calls super.start.
+    }
+    
+    public void restart( boolean globalExtender )
+    {
+        BundleContext context;
+        if ( globalExtender )
+        {
+            context = m_context.getBundle( 0 ).getBundleContext();
+        }
+        else
+        {
+            context = m_context;
+        }
+        if ( m_packageAdmin != null )
+        {
+            //this really is a restart, not the initial start
+            try
+            {
+                super.stop(context);
+            }
+            catch ( Exception e )
+            {
+                log( LogService.LOG_ERROR, m_bundle, "Exception stopping during restart", e );
+            }
+        }
+        try
+        {
+            super.start( context );
+        }
+        catch ( Exception e )
+        {
+            log( LogService.LOG_ERROR, m_bundle, "Exception starting during restart", e );
+        }
+        
+    }
+
+    protected void doStart() throws Exception {
 
         // prepare component registry
         m_componentBundles = new HashMap<Long, BundleComponentActivator>();
         m_componentRegistry = new ComponentRegistry( m_context );
 
-        // get the configuration
-        m_configuration.start( m_context );
 
         // log SCR startup
         log( LogService.LOG_INFO, m_bundle, " Version = {0}",
@@ -120,6 +154,13 @@
         ScrCommand scrCommand = ScrCommand.register(m_context, m_componentRegistry, m_configuration);
         m_configuration.setScrCommand( scrCommand );
     }
+    
+    public void stop(BundleContext context) throws Exception
+    {
+        super.stop(context);
+        m_configuration.stop();
+        m_configuration = null;
+    }
 
 
     /**
@@ -349,7 +390,7 @@
      */
     public static boolean isLogEnabled( int level )
     {
-        return m_configuration.getLogLevel() >= level;
+        return m_configuration == null || m_configuration.getLogLevel() >= level;
     }
 
     /**
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/config/ScrConfiguration.java b/scr/src/main/java/org/apache/felix/scr/impl/config/ScrConfiguration.java
index 1f96d31..8c4dd04 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/config/ScrConfiguration.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/config/ScrConfiguration.java
@@ -22,10 +22,12 @@
 import java.util.Dictionary;
 import java.util.Hashtable;
 
+import org.apache.felix.scr.impl.Activator;
 import org.apache.felix.scr.impl.ScrCommand;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.Constants;
 import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.cm.ManagedService;
 import org.osgi.service.log.LogService;
 
 
@@ -85,6 +87,10 @@
     private static final String PROP_SHOWTRACE = "ds.showtrace";
 
     private static final String PROP_SHOWERRORS = "ds.showerrors";
+    
+    public static final String PROP_GLOBAL_EXTENDER="ds.global.extender";
+    
+    private final Activator activator;
 
     private int logLevel;
 
@@ -97,32 +103,38 @@
     private long lockTimeout = DEFAULT_LOCK_TIMEOUT_MILLISECONDS;
 
     private long stopTimeout = DEFAULT_STOP_TIMEOUT_MILLISECONDS;
+    
+    private Boolean globalExtender;
 
     private BundleContext bundleContext;
 
-    private ServiceRegistration managedService;
+    private ServiceRegistration<ManagedService> managedService;
     
     private ScrCommand scrCommand;
 
-    public ScrConfiguration( )
+    public ScrConfiguration( Activator activator )
     {
-        // default configuration
-        configure( null );
+        this.activator = activator;
     }
 
-    public void start(final BundleContext bundleContext){
+    @SuppressWarnings("unchecked")
+    public void start(final BundleContext bundleContext) 
+    {
         this.bundleContext = bundleContext;
 
-        // reconfigure from bundle context properties
-        configure( null );
-
         // listen for Configuration Admin configuration
-        Dictionary props = new Hashtable();
+        Dictionary<String, Object> props = new Hashtable<String, Object>();
         props.put(Constants.SERVICE_PID, PID);
         props.put(Constants.SERVICE_DESCRIPTION, "SCR Configurator");
         props.put(Constants.SERVICE_VENDOR, "The Apache Software Foundation");
-        managedService = bundleContext.registerService("org.osgi.service.cm.ManagedService", new ScrManagedServiceServiceFactory(this),
+        managedService = ( ServiceRegistration<ManagedService> ) bundleContext.registerService("org.osgi.service.cm.ManagedService", new ScrManagedServiceServiceFactory(this),
             props);
+        
+        if ( globalExtender == null)  //no config admin or no configuration
+        {
+            // configure from bundle context properties
+            configure( null );            
+        }
     }
 
     public void stop() {
@@ -141,8 +153,9 @@
     }
 
     // Called from the ScrManagedService.updated method to reconfigure
-    void configure( Dictionary config )
+    void configure( Dictionary<String, ?> config )
     {
+        Boolean oldGlobalExtender = globalExtender;
         if ( config == null )
         {
             if ( this.bundleContext == null )
@@ -153,6 +166,7 @@
                 infoAsService = false;
                 lockTimeout = DEFAULT_LOCK_TIMEOUT_MILLISECONDS;
                 stopTimeout = DEFAULT_STOP_TIMEOUT_MILLISECONDS;
+                globalExtender = false;
             }
             else
             {
@@ -162,6 +176,7 @@
                 infoAsService = getDefaultInfoAsService();
                 lockTimeout = getDefaultLockTimeout();
                 stopTimeout = getDefaultStopTimeout();
+                globalExtender = getDefaultGlobalExtender();
             }
         }
         else
@@ -174,11 +189,16 @@
             lockTimeout = timeout == null? DEFAULT_LOCK_TIMEOUT_MILLISECONDS: timeout;
             timeout = ( Long ) config.get( PROP_STOP_TIMEOUT );
             stopTimeout = timeout == null? DEFAULT_STOP_TIMEOUT_MILLISECONDS: timeout;
+            globalExtender = VALUE_TRUE.equalsIgnoreCase( String.valueOf( config.get( PROP_GLOBAL_EXTENDER) ) );
         }
         if ( scrCommand != null )
         {
             scrCommand.update( infoAsService() );
         }
+        if ( globalExtender != oldGlobalExtender )
+        {
+            activator.restart( globalExtender );
+        }
     }
 
     /**
@@ -260,6 +280,11 @@
     }
 
 
+    private boolean getDefaultGlobalExtender()
+    {
+        return VALUE_TRUE.equalsIgnoreCase( bundleContext.getProperty( PROP_GLOBAL_EXTENDER) );
+    }
+
     private int getLogLevel( final Object levelObject )
     {
         if ( levelObject != null )
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/config/ScrManagedService.java b/scr/src/main/java/org/apache/felix/scr/impl/config/ScrManagedService.java
index d64f88c..d2973c9 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/config/ScrManagedService.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/config/ScrManagedService.java
@@ -50,7 +50,7 @@
         this.scrConfiguration = scrConfiguration;
     }
 
-    public void updated(Dictionary properties) throws ConfigurationException
+    public void updated(Dictionary<String, ?> properties) throws ConfigurationException
     {
         this.scrConfiguration.configure(properties);
     }
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/config/ScrManagedServiceMetaTypeProvider.java b/scr/src/main/java/org/apache/felix/scr/impl/config/ScrManagedServiceMetaTypeProvider.java
index ac9e27a..9bc0281 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/config/ScrManagedServiceMetaTypeProvider.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/config/ScrManagedServiceMetaTypeProvider.java
@@ -99,7 +99,7 @@
                     + "Declarative Services specifications suggests that instances of delayed components are disposed off "
                     + "if there is not used any longer. Setting this flag causes the components to not be disposed off "
                     + "and thus prevent them from being constantly recreated if often used. Examples of such components "
-                    + "may be EventHandler services. The default is to dispose off unused components.", this
+                    + "may be EventHandler services. The default is to dispose of unused components.", this
                     .getScrConfiguration().keepInstances() ) );
 
         adList.add( new AttributeDefinitionImpl(
@@ -116,6 +116,20 @@
                 new String[] { String.valueOf(this.getScrConfiguration().lockTimeout())}, 
                 0, null, null) );
 
+        adList.add( new AttributeDefinitionImpl(
+                ScrConfiguration.PROP_STOP_TIMEOUT,
+                "Stop timeout milliseconds",
+                "How long stopping a bundle is waited for before continuing due to suspected deadlock", 
+                AttributeDefinition.LONG,
+                new String[] { String.valueOf(this.getScrConfiguration().stopTimeout())}, 
+                0, null, null) );
+
+        adList.add( new AttributeDefinitionImpl(
+                ScrConfiguration.PROP_GLOBAL_EXTENDER,
+                "Global Extender",
+                "Whether to extend all bundles whether or not visible to this bundle.", 
+                false ) );
+
         return new ObjectClassDefinition()
         {