FELIX-5959 Exception on changecount timer timeout

Signed-off-by: Raymond Auge <rotty3000@apache.org>

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk/scr@1843483 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/src/main/java/org/apache/felix/scr/impl/Activator.java b/src/main/java/org/apache/felix/scr/impl/Activator.java
index 2341098..728c1d3 100644
--- a/src/main/java/org/apache/felix/scr/impl/Activator.java
+++ b/src/main/java/org/apache/felix/scr/impl/Activator.java
@@ -151,7 +151,7 @@
 
         // prepare component registry
         m_componentBundles = new HashMap<>();
-        m_componentRegistry = new ComponentRegistry( this.logger );
+        m_componentRegistry = new ComponentRegistry( this.m_configuration, this.logger );
 
         final ServiceComponentRuntimeImpl runtime = new ServiceComponentRuntimeImpl( m_globalContext, m_componentRegistry );
         m_runtime_reg = m_context.registerService( ServiceComponentRuntime.class,
diff --git a/src/main/java/org/apache/felix/scr/impl/ComponentRegistry.java b/src/main/java/org/apache/felix/scr/impl/ComponentRegistry.java
index 10d7bf2..e11e0b2 100644
--- a/src/main/java/org/apache/felix/scr/impl/ComponentRegistry.java
+++ b/src/main/java/org/apache/felix/scr/impl/ComponentRegistry.java
@@ -43,6 +43,7 @@
 import org.apache.felix.scr.impl.manager.ConfigurableComponentHolder;
 import org.apache.felix.scr.impl.manager.DependencyManager;
 import org.apache.felix.scr.impl.manager.RegionConfigurationSupport;
+import org.apache.felix.scr.impl.manager.ScrConfiguration;
 import org.apache.felix.scr.impl.metadata.ComponentMetadata;
 import org.apache.felix.scr.impl.metadata.TargetedPID;
 import org.osgi.framework.Bundle;
@@ -126,8 +127,11 @@
 
     private final ScrLogger m_logger;
 
-    public ComponentRegistry( final ScrLogger logger )
+    private final ScrConfiguration m_configuration;
+
+    public ComponentRegistry( final ScrConfiguration scrConfiguration, final ScrLogger logger )
     {
+        m_configuration = scrConfiguration;
         m_logger = logger;
         m_componentHoldersByName = new HashMap<>();
         m_componentHoldersByPid = new HashMap<>();
@@ -719,29 +723,37 @@
                 {
                     this.timer = new Timer();
                 }
-                timer.schedule(new TimerTask()
+                try
                 {
-
-                    @Override
-                    public void run() {
-                        synchronized ( changeCountLock )
+                    timer.schedule(new TimerTask()
                         {
-                            if ( changeCount == count )
-                            {
-                                try
+
+                            @Override
+                            public void run() {
+                                synchronized ( changeCountLock )
                                 {
-                                    registration.setProperties(getServiceRegistrationProperties());
+                                    if ( changeCount == count )
+                                    {
+                                        try
+                                        {
+                                            registration.setProperties(getServiceRegistrationProperties());
+                                        }
+                                        catch ( final IllegalStateException ise)
+                                        {
+                                            // we ignore this as this might happen on shutdown
+                                        }
+                                        timer.cancel();
+                                        timer = null;
+                                    }
                                 }
-                                catch ( final IllegalStateException ise)
-                                {
-                                    // we ignore this as this might happen on shutdown
-                                }
-                                timer.cancel();
-                                timer = null;
                             }
-                        }
-                    }
-                }, 5000L);
+                        }, m_configuration.serviceChangecountTimeout());
+                }
+                catch (Exception e) {
+                    m_logger.log(LogService.LOG_WARNING,
+                        "Service changecount Timer for {0} had a problem", e,
+                        registration.getReference());
+                }
             }
         }
     }
diff --git a/src/main/java/org/apache/felix/scr/impl/config/ScrConfigurationImpl.java b/src/main/java/org/apache/felix/scr/impl/config/ScrConfigurationImpl.java
index 8c6fa2b..5ff6b25 100644
--- a/src/main/java/org/apache/felix/scr/impl/config/ScrConfigurationImpl.java
+++ b/src/main/java/org/apache/felix/scr/impl/config/ScrConfigurationImpl.java
@@ -85,6 +85,8 @@
 
     private long stopTimeout = DEFAULT_STOP_TIMEOUT_MILLISECONDS;
 
+    private long serviceChangecountTimeout = DEFAULT_SERVICE_CHANGECOUNT_TIMEOUT_MILLISECONDS;
+
     private Boolean globalExtender;
 
     private volatile BundleContext bundleContext;
@@ -171,6 +173,7 @@
                         infoAsService = false;
                         lockTimeout = DEFAULT_LOCK_TIMEOUT_MILLISECONDS;
                         stopTimeout = DEFAULT_STOP_TIMEOUT_MILLISECONDS;
+                        serviceChangecountTimeout = DEFAULT_SERVICE_CHANGECOUNT_TIMEOUT_MILLISECONDS;
                         newGlobalExtender = false;
                     }
                     else
@@ -181,6 +184,7 @@
                         infoAsService = getDefaultInfoAsService();
                         lockTimeout = getDefaultLockTimeout();
                         stopTimeout = getDefaultStopTimeout();
+                        serviceChangecountTimeout = getServiceChangecountTimeout();
                         newGlobalExtender = getDefaultGlobalExtender();
                     }
                 }
@@ -263,6 +267,12 @@
         return globalExtender;
     }
 
+    @Override
+    public long serviceChangecountTimeout()
+    {
+        return serviceChangecountTimeout;
+    }
+
     private boolean getDefaultFactoryEnabled()
     {
         return VALUE_TRUE.equals( bundleContext.getProperty( PROP_FACTORY_ENABLED ) );
@@ -305,6 +315,15 @@
         return Long.parseLong( val );
     }
 
+    private long getServiceChangecountTimeout()
+    {
+        String val = bundleContext.getProperty( PROP_SERVICE_CHANGECOUNT_TIMEOUT );
+        if ( val == null)
+        {
+            return DEFAULT_SERVICE_CHANGECOUNT_TIMEOUT_MILLISECONDS;
+        }
+        return Long.parseLong( val );
+    }
 
     private boolean getDefaultGlobalExtender()
     {
diff --git a/src/main/java/org/apache/felix/scr/impl/manager/ScrConfiguration.java b/src/main/java/org/apache/felix/scr/impl/manager/ScrConfiguration.java
index fdf42ea..6f4f529 100644
--- a/src/main/java/org/apache/felix/scr/impl/manager/ScrConfiguration.java
+++ b/src/main/java/org/apache/felix/scr/impl/manager/ScrConfiguration.java
@@ -58,12 +58,16 @@
 
     long DEFAULT_LOCK_TIMEOUT_MILLISECONDS = 5000;
 
+    long DEFAULT_SERVICE_CHANGECOUNT_TIMEOUT_MILLISECONDS = 5000;
+
     long DEFAULT_STOP_TIMEOUT_MILLISECONDS = 60000;
 
     String PROP_LOGLEVEL = "ds.loglevel";
 
     String PROP_GLOBAL_EXTENDER="ds.global.extender";
 
+    String PROP_SERVICE_CHANGECOUNT_TIMEOUT = "ds.service.changecount.timeout";
+
     /**
      * Returns the current log level.
      * @return
@@ -88,4 +92,9 @@
      */
     boolean globalExtender();
 
+    /**
+     * @since 2.2
+     */
+    long serviceChangecountTimeout();
+
 }
diff --git a/src/test/java/org/apache/felix/scr/impl/logger/MockScrLogger.java b/src/test/java/org/apache/felix/scr/impl/logger/MockScrLogger.java
index 9e18b53..761df75 100644
--- a/src/test/java/org/apache/felix/scr/impl/logger/MockScrLogger.java
+++ b/src/test/java/org/apache/felix/scr/impl/logger/MockScrLogger.java
@@ -63,6 +63,12 @@
             }
 
             @Override
+            public long serviceChangecountTimeout()
+            {
+                return 0;
+            }
+
+            @Override
             public int getLogLevel()
             {
                 return LogService.LOG_ERROR;