You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by cz...@apache.org on 2017/02/27 13:59:19 UTC

svn commit: r1784564 - in /felix/trunk/osgi-r7/scr/src: main/java/org/apache/felix/scr/impl/ main/java/org/apache/felix/scr/impl/manager/ main/java/org/apache/felix/scr/impl/runtime/ test/java/org/apache/felix/scr/impl/manager/

Author: cziegeler
Date: Mon Feb 27 13:59:18 2017
New Revision: 1784564

URL: http://svn.apache.org/viewvc?rev=1784564&view=rev
Log:
FELIX-5354 : Add change count property to runtime service

Modified:
    felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/Activator.java
    felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/BundleComponentActivator.java
    felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/ComponentRegistry.java
    felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/manager/AbstractComponentManager.java
    felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentActivator.java
    felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentContainer.java
    felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentFactoryImpl.java
    felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/runtime/ServiceComponentRuntimeImpl.java
    felix/trunk/osgi-r7/scr/src/test/java/org/apache/felix/scr/impl/manager/SingleComponentManagerTest.java

Modified: felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/Activator.java
URL: http://svn.apache.org/viewvc/felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/Activator.java?rev=1784564&r1=1784563&r2=1784564&view=diff
==============================================================================
--- felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/Activator.java (original)
+++ felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/Activator.java Mon Feb 27 13:59:18 2017
@@ -79,7 +79,7 @@ public class Activator extends AbstractE
     //  thread acting upon configurations
     private ComponentActorThread m_componentActor;
 
-    private ServiceRegistration<?> m_runtime_reg;
+    private ServiceRegistration<ServiceComponentRuntime> m_runtime_reg;
 
     private ScrCommand m_scrCommand;
 
@@ -156,8 +156,11 @@ public class Activator extends AbstractE
         m_componentBundles = new HashMap<Long, BundleComponentActivator>();
         m_componentRegistry = new ComponentRegistry( this );
 
-        final ServiceComponentRuntime runtime = new ServiceComponentRuntimeImpl( m_globalContext, m_componentRegistry );
-        m_runtime_reg = m_context.registerService( ServiceComponentRuntime.class, runtime, null );
+        final ServiceComponentRuntimeImpl runtime = new ServiceComponentRuntimeImpl( m_globalContext, m_componentRegistry );
+        m_runtime_reg = m_context.registerService( ServiceComponentRuntime.class,
+                runtime,
+                m_componentRegistry.getServiceRegistrationProperties() );
+        m_componentRegistry.setRegistration(m_runtime_reg);
 
         // log SCR startup
         log( LogService.LOG_INFO, m_bundle, " Version = {0}",
@@ -245,6 +248,7 @@ public class Activator extends AbstractE
             this.bundle = bundle;
         }
 
+        @Override
         public void start()
         {
             boolean acquired = false;
@@ -273,6 +277,7 @@ public class Activator extends AbstractE
             }
         }
 
+        @Override
         public void destroy()
         {
             boolean acquired = false;
@@ -469,12 +474,14 @@ public class Activator extends AbstractE
     }
 
     //    @Override
+    @Override
     public void log(int level, String message, Throwable ex)
     {
         log( level, null, message, ex );
     }
 
     //    @Override
+    @Override
     public void log(int level, String pattern, Object[] arguments, Throwable ex)
     {
         if ( isLogEnabled( level ) )
@@ -496,6 +503,7 @@ public class Activator extends AbstractE
     /**
      * Returns <code>true</code> if logging for the given level is enabled.
      */
+    @Override
     public boolean isLogEnabled(int level)
     {
         return m_configuration == null || m_configuration.getLogLevel() >= level;

Modified: felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/BundleComponentActivator.java
URL: http://svn.apache.org/viewvc/felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/BundleComponentActivator.java?rev=1784564&r1=1784563&r2=1784564&view=diff
==============================================================================
--- felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/BundleComponentActivator.java (original)
+++ felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/BundleComponentActivator.java Mon Feb 27 13:59:18 2017
@@ -103,6 +103,7 @@ public class BundleComponentActivator im
     {
         private Map<Filter, List<ExtendedServiceListener<ExtendedServiceEvent>>> filterMap = new HashMap<Filter, List<ExtendedServiceListener<ExtendedServiceEvent>>>();
 
+        @Override
         public void serviceChanged(ServiceEvent event)
         {
             ServiceReference<?> ref = event.getServiceReference();
@@ -186,6 +187,7 @@ public class BundleComponentActivator im
         }
     }
 
+    @Override
     public void addServiceListener(String classNameFilter, Filter eventFilter,
         ExtendedServiceListener<ExtendedServiceEvent> listener)
     {
@@ -213,6 +215,7 @@ public class BundleComponentActivator im
         listenerInfo.add( eventFilter, listener );
     }
 
+    @Override
     public void removeServiceListener(String className, Filter filter,
         ExtendedServiceListener<ExtendedServiceEvent> listener)
     {
@@ -259,7 +262,7 @@ public class BundleComponentActivator im
             new Object[] { m_bundle.getBundleId() }, null, null, null );
 
         // Get the Metadata-Location value from the manifest
-        String descriptorLocations = (String) m_bundle.getHeaders("").get("Service-Component");
+        String descriptorLocations = m_bundle.getHeaders("").get("Service-Component");
         if ( descriptorLocations == null )
         {
             throw new ComponentException( "Service-Component entry not found in the manifest" );
@@ -566,6 +569,7 @@ public class BundleComponentActivator im
      * (not fully setup, though) and reset early in the process of
      * {@link #dispose(int) disposing} this instance.
      */
+    @Override
     public boolean isActive()
     {
         return m_active.get();
@@ -576,11 +580,13 @@ public class BundleComponentActivator im
     *
     * @return the BundleContext
     */
+    @Override
     public BundleContext getBundleContext()
     {
         return m_context;
     }
 
+    @Override
     public ScrConfiguration getConfiguration()
     {
         return m_configuration;
@@ -595,6 +601,7 @@ public class BundleComponentActivator im
      * @param name The name of the component to enable or <code>null</code> to
      *      enable all components.
      */
+    @Override
     public void enableComponent(final String name)
     {
         final List<ComponentHolder<?>> holder = getSelectedComponents( name );
@@ -621,6 +628,7 @@ public class BundleComponentActivator im
      * @param name The name of the component to disable or <code>null</code> to
      *      disable all components.
      */
+    @Override
     public void disableComponent(final String name)
     {
         final List<ComponentHolder<?>> holder = getSelectedComponents( name );
@@ -673,11 +681,13 @@ public class BundleComponentActivator im
 
     //---------- Component ID support
 
+    @Override
     public long registerComponentId(AbstractComponentManager<?> componentManager)
     {
         return m_componentRegistry.registerComponentId( componentManager );
     }
 
+    @Override
     public void unregisterComponentId(AbstractComponentManager<?> componentManager)
     {
         m_componentRegistry.unregisterComponentId( componentManager.getId() );
@@ -692,6 +702,7 @@ public class BundleComponentActivator im
      *
      * @param task The component task to execute
      */
+    @Override
     public void schedule(Runnable task)
     {
         if ( isActive() )
@@ -728,6 +739,7 @@ public class BundleComponentActivator im
     /**
      * Returns <code>true</code> if logging for the given level is enabled.
      */
+    @Override
     public boolean isLogEnabled(int level)
     {
         return m_configuration.getLogLevel() >= level;
@@ -746,6 +758,7 @@ public class BundleComponentActivator im
      * @param componentId
      * @param ex An optional <code>Throwable</code> whose stack trace is written,
      */
+    @Override
     public void log(int level, String pattern, Object[] arguments, ComponentMetadata metadata, Long componentId,
         Throwable ex)
     {
@@ -766,6 +779,7 @@ public class BundleComponentActivator im
      * @param componentId
      * @param ex An optional <code>Throwable</code> whose stack trace is written,
      */
+    @Override
     public void log(int level, String message, ComponentMetadata metadata, Long componentId, Throwable ex)
     {
         if ( isLogEnabled( level ) )
@@ -804,27 +818,32 @@ public class BundleComponentActivator im
         }
     }
 
+    @Override
     public <T> boolean enterCreate(ServiceReference<T> serviceReference)
     {
         return m_componentRegistry.enterCreate( serviceReference );
     }
 
+    @Override
     public <T> void leaveCreate(ServiceReference<T> serviceReference)
     {
         m_componentRegistry.leaveCreate( serviceReference );
     }
 
+    @Override
     public <T> void missingServicePresent(ServiceReference<T> serviceReference)
     {
         m_componentRegistry.missingServicePresent( serviceReference, m_componentActor );
     }
 
+    @Override
     public <S, T> void registerMissingDependency(DependencyManager<S, T> dependencyManager,
         ServiceReference<T> serviceReference, int trackingCount)
     {
         m_componentRegistry.registerMissingDependency( dependencyManager, serviceReference, trackingCount );
     }
 
+    @Override
     public RegionConfigurationSupport setRegionConfigurationSupport(ServiceReference<ConfigurationAdmin> reference)
     {
         RegionConfigurationSupport rcs = m_componentRegistry.registerRegionConfigurationSupport( reference );
@@ -835,9 +854,15 @@ public class BundleComponentActivator im
         return rcs;
     }
 
+    @Override
     public void unsetRegionConfigurationSupport(RegionConfigurationSupport rcs)
     {
         m_componentRegistry.unregisterRegionConfigurationSupport( rcs );
         // TODO anything needed?
     }
+
+    @Override
+    public void updateChangeCount() {
+        this.m_componentRegistry.updateChangeCount();
+    }
 }

Modified: felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/ComponentRegistry.java
URL: http://svn.apache.org/viewvc/felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/ComponentRegistry.java?rev=1784564&r1=1784563&r2=1784564&view=diff
==============================================================================
--- felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/ComponentRegistry.java (original)
+++ felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/ComponentRegistry.java Mon Feb 27 13:59:18 2017
@@ -21,11 +21,15 @@ package org.apache.felix.scr.impl;
 
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Dictionary;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.Hashtable;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.Timer;
+import java.util.TimerTask;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 
@@ -43,9 +47,11 @@ import org.apache.felix.scr.impl.metadat
 import org.osgi.framework.Bundle;
 import org.osgi.framework.Constants;
 import org.osgi.framework.ServiceReference;
+import org.osgi.framework.ServiceRegistration;
 import org.osgi.service.cm.ConfigurationAdmin;
 import org.osgi.service.component.ComponentConstants;
 import org.osgi.service.component.ComponentException;
+import org.osgi.service.component.runtime.ServiceComponentRuntime;
 import org.osgi.service.log.LogService;
 
 
@@ -55,6 +61,13 @@ import org.osgi.service.log.LogService;
  */
 public class ComponentRegistry
 {
+    /**
+     * Service property for change count. This constant is defined here to avoid
+     * a dependency on R7 of the framework.
+     * The value of the property is of type {@code Long}.
+     */
+    private static String PROP_CHANGECOUNT = "service.changecount";
+
 
     /**
      * The map of known components indexed by component name. The values are
@@ -275,7 +288,7 @@ public class ComponentRegistry
                 set.add( componentHolder );
             }
         }
-
+        this.updateChangeCount();
   }
 
     /**
@@ -411,6 +424,7 @@ public class ComponentRegistry
                     }
                 }
             }
+            this.updateChangeCount();
         }
     }
 
@@ -588,6 +602,7 @@ public class ComponentRegistry
             Runnable runnable = new Runnable()
             {
 
+                @Override
                 @SuppressWarnings("unchecked")
                 public void run()
                 {
@@ -721,4 +736,58 @@ public class ComponentRegistry
 		}
 
 	}
+
+	private final Object changeCountLock = new Object();
+
+    private volatile long changeCount;
+
+    private volatile Timer timer;
+
+    private volatile ServiceRegistration<ServiceComponentRuntime> registration;
+
+    public Dictionary<String, Object> getServiceRegistrationProperties()
+    {
+        final Dictionary<String, Object> props = new Hashtable<String, Object>();
+        props.put(PROP_CHANGECOUNT, this.changeCount);
+
+        return props;
+    }
+
+    public void setRegistration(final ServiceRegistration<ServiceComponentRuntime> reg)
+    {
+        this.registration = reg;
+    }
+
+    public void updateChangeCount()
+    {
+        if ( registration != null )
+        {
+            final long count;
+            synchronized ( changeCountLock )
+            {
+                this.changeCount++;
+                count = this.changeCount;
+                if ( this.timer == null )
+                {
+                    this.timer = new Timer();
+                }
+            }
+            timer.schedule(new TimerTask()
+            {
+
+                @Override
+                public void run() {
+                    synchronized ( changeCountLock )
+                    {
+                        if ( changeCount == count )
+                        {
+                            registration.setProperties(getServiceRegistrationProperties());
+                            timer.cancel();
+                            timer = null;
+                        }
+                    }
+                }
+            }, 5000L);
+        }
+    }
 }

Modified: felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/manager/AbstractComponentManager.java
URL: http://svn.apache.org/viewvc/felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/manager/AbstractComponentManager.java?rev=1784564&r1=1784563&r2=1784564&view=diff
==============================================================================
--- felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/manager/AbstractComponentManager.java (original)
+++ felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/manager/AbstractComponentManager.java Mon Feb 27 13:59:18 2017
@@ -170,12 +170,12 @@ public abstract class AbstractComponentM
      * @param container
      * @param componentMethods
      */
-    protected AbstractComponentManager(ComponentContainer<S> container, ComponentMethods componentMethods)
+    protected AbstractComponentManager(ComponentContainer<S> container, ComponentMethods<S> componentMethods)
     {
         this(container, componentMethods, false);
     }
 
-    protected AbstractComponentManager(ComponentContainer<S> container, ComponentMethods componentMethods, boolean factoryInstance)
+    protected AbstractComponentManager(ComponentContainer<S> container, ComponentMethods<S> componentMethods, boolean factoryInstance)
     {
         m_enabledLatchRef.get().resolve(null);
         m_factoryInstance = factoryInstance;
@@ -1424,6 +1424,7 @@ public abstract class AbstractComponentM
             {
                 this.failureReason = null;
             }
+            this.getActivator().updateChangeCount();
         }
         else
         {

Modified: felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentActivator.java
URL: http://svn.apache.org/viewvc/felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentActivator.java?rev=1784564&r1=1784563&r2=1784564&view=diff
==============================================================================
--- felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentActivator.java (original)
+++ felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentActivator.java Mon Feb 27 13:59:18 2017
@@ -54,4 +54,6 @@ public interface ComponentActivator exte
 
     void unsetRegionConfigurationSupport(RegionConfigurationSupport rcs);
 
+    /** Inform about any change in the state of the components. */
+    void updateChangeCount();
 }

Modified: felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentContainer.java
URL: http://svn.apache.org/viewvc/felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentContainer.java?rev=1784564&r1=1784563&r2=1784564&view=diff
==============================================================================
--- felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentContainer.java (original)
+++ felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentContainer.java Mon Feb 27 13:59:18 2017
@@ -40,5 +40,4 @@ public interface ComponentContainer<S>
      * calling the dispose method.
      */
     void disposed(SingleComponentManager<S> component);
-
 }
\ No newline at end of file

Modified: felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentFactoryImpl.java
URL: http://svn.apache.org/viewvc/felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentFactoryImpl.java?rev=1784564&r1=1784563&r2=1784564&view=diff
==============================================================================
--- felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentFactoryImpl.java (original)
+++ felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentFactoryImpl.java Mon Feb 27 13:59:18 2017
@@ -49,9 +49,9 @@ import org.osgi.service.log.LogService;
  * class directly as the holder for component instances created by the
  * {@link #newInstance(Dictionary)} method.
  * <p>
- * This class implements spec-compliant component factories and the felix 
+ * This class implements spec-compliant component factories and the felix
  * "persistent" component factory, where the factory is always registered whether or
- * not all dependencies are present and the created components also persist whether or 
+ * not all dependencies are present and the created components also persist whether or
  * not the dependencies are present to allow the component instance to exist.
  */
 public class ComponentFactoryImpl<S> extends AbstractComponentManager<S> implements ComponentFactory<S>, ComponentContainer<S>
@@ -75,19 +75,19 @@ public class ComponentFactoryImpl<S> ext
      * by the {@link #newInstance(Dictionary)} method.
      */
     private volatile Map<String, Object> m_configuration;
-    
+
     /**
      * Flag telling if our component factory is currently configured from config admin.
      * We are configured when configuration policy is required and we have received the
      * config admin properties, or when configuration policy is optional or ignored.
      */
     private volatile boolean m_hasConfiguration;
-    
+
     /**
      * Configuration change count (R5) or imitation (R4)
      */
     protected volatile long m_changeCount = -1;
-    
+
     protected TargetedPID m_targetedPID;
 
     public ComponentFactoryImpl( ComponentContainer<S> container, ComponentMethods componentMethods )
@@ -98,15 +98,16 @@ public class ComponentFactoryImpl<S> ext
     }
 
 
+    @Override
     protected boolean verifyDependencyManagers()
     {
         if (!getComponentMetadata().isPersistentFactoryComponent())
         {
             return super.verifyDependencyManagers();
         }
-        return true;    
+        return true;
     }
-    
+
     @Override
     public boolean isFactory()
     {
@@ -116,6 +117,7 @@ public class ComponentFactoryImpl<S> ext
     /* (non-Javadoc)
     * @see org.osgi.service.component.ComponentFactory#newInstance(java.util.Dictionary)
     */
+    @Override
     public ComponentInstance<S> newInstance( Dictionary<String, ?> dictionary )
     {
         final SingleComponentManager<S> cm = createComponentManager();
@@ -129,7 +131,7 @@ public class ComponentFactoryImpl<S> ext
         cm.enableInternal();
 
         ComponentInstance<S> instance;
-        if ( getComponentMetadata().isPersistentFactoryComponent() ) 
+        if ( getComponentMetadata().isPersistentFactoryComponent() )
         {
             instance = new ModifyComponentInstance<S>(cm);
         }
@@ -148,10 +150,10 @@ public class ComponentFactoryImpl<S> ext
         {
             m_componentInstances.put( cm, cm );
         }
-        
+
         return instance;
     }
-    
+
     private static class ModifyComponentInstance<S> implements ExtFactoryComponentInstance<S>
     {
         private final SingleComponentManager<S> cm;
@@ -161,37 +163,41 @@ public class ComponentFactoryImpl<S> ext
             this.cm = cm;
         }
 
+        @Override
         public void dispose()
         {
-            cm.dispose();            
+            cm.dispose();
         }
 
+        @Override
         public S getInstance()
         {
             final ComponentInstance<S> componentInstance = cm.getComponentInstance();
             return componentInstance == null? null: componentInstance.getInstance();
         }
 
+        @Override
         public void modify(Dictionary<String, ?> properties)
         {
             cm.setFactoryProperties( properties );
-            cm.reconfigure(false);            
+            cm.reconfigure(false);
         }
-        
+
     }
 
     /**
      * Compares this {@code ComponentFactoryImpl} object to another object.
-     * 
+     *
      * <p>
      * A component factory impl is considered to be <b>equal to </b> another component
      * factory impl if the component names are equal(using {@code String.equals}).
-     * 
+     *
      * @param object The {@code ComponentFactoryImpl} object to be compared.
      * @return {@code true} if {@code object} is a
      *         {@code ComponentFactoryImpl} and is equal to this object;
      *         {@code false} otherwise.
      */
+    @Override
     public boolean equals(Object object)
     {
         if (!(object instanceof ComponentFactoryImpl<?>))
@@ -202,13 +208,14 @@ public class ComponentFactoryImpl<S> ext
         ComponentFactoryImpl<?> other = (ComponentFactoryImpl<?>) object;
         return getComponentMetadata().getName().equals(other.getComponentMetadata().getName());
     }
-    
+
    /**
     * Returns a hash code value for the object.
-    * 
+    *
     * @return An integer which is a hash code value for this object.
     */
-   public int hashCode()
+   @Override
+public int hashCode()
    {
        return getComponentMetadata().getName().hashCode();
    }
@@ -220,6 +227,7 @@ public class ComponentFactoryImpl<S> ext
      * configuration instances are to disabled as a consequence of deactivating
      * the component factory.
      */
+    @Override
     protected void deleteComponent( int reason )
     {
     }
@@ -238,10 +246,11 @@ public class ComponentFactoryImpl<S> ext
     }
 
 
-    /** 
-     * For ComponentFactoryImpl, this is used only for updating targets on the dependency managers, so we don't need any other 
+    /**
+     * For ComponentFactoryImpl, this is used only for updating targets on the dependency managers, so we don't need any other
      * properties.
      */
+    @Override
     public Map<String, Object> getProperties()
     {
         Map<String, Object> props = new HashMap<String, Object>();
@@ -256,7 +265,7 @@ public class ComponentFactoryImpl<S> ext
             }
         }
 
-        // add target properties from configuration (if we have one)        
+        // add target properties from configuration (if we have one)
         for ( String key :  m_configuration.keySet() )
         {
             if ( key.endsWith( ".target" ) )
@@ -267,7 +276,8 @@ public class ComponentFactoryImpl<S> ext
 
         return props;
     }
-    
+
+    @Override
     public void setServiceProperties( Dictionary<String, ?> serviceProperties )
     {
         throw new IllegalStateException( "ComponentFactory service properties are immutable" );
@@ -285,6 +295,7 @@ public class ComponentFactoryImpl<S> ext
         //do nothing
     }
 
+    @Override
     public Dictionary<String, Object> getServiceProperties()
     {
         Dictionary<String, Object> props = new Hashtable<String, Object>(getComponentMetadata().getFactoryProperties());
@@ -298,25 +309,30 @@ public class ComponentFactoryImpl<S> ext
         return props;
     }
 
+    @Override
     boolean hasInstance()
     {
         return false;
     }
 
+    @Override
     protected boolean collectDependencies(ComponentContextImpl<S> componentContext)
     {
         return true;
     }
 
+    @Override
     <T> boolean invokeUpdatedMethod( DependencyManager<S, T> dependencyManager, RefPair<S, T> ref, int trackingCount )
     {
     	return false;
     }
 
+    @Override
     <T> void invokeBindMethod( DependencyManager<S, T> dependencyManager, RefPair<S, T> reference, int trackingCount )
     {
     }
 
+    @Override
     <T> void invokeUnbindMethod( DependencyManager<S, T> dependencyManager, RefPair<S, T> oldRef, int trackingCount )
     {
     }
@@ -337,6 +353,7 @@ public class ComponentFactoryImpl<S> ext
      * or if the owning bundle is stopped. In both cases all components created
      * by this holder must be disposed off.
      */
+    @Override
     public void dispose( int reason )
     {
         List<AbstractComponentManager<S>> cms = new ArrayList<AbstractComponentManager<S>>( );
@@ -356,6 +373,7 @@ public class ComponentFactoryImpl<S> ext
     }
 
 
+    @Override
     public void disposed( SingleComponentManager<S> component )
     {
         synchronized ( m_componentInstances )
@@ -424,5 +442,4 @@ public class ComponentFactoryImpl<S> ext
             cms.addAll(m_componentInstances.keySet());
         }
     }
-
 }

Modified: felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/runtime/ServiceComponentRuntimeImpl.java
URL: http://svn.apache.org/viewvc/felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/runtime/ServiceComponentRuntimeImpl.java?rev=1784564&r1=1784563&r2=1784564&view=diff
==============================================================================
--- felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/runtime/ServiceComponentRuntimeImpl.java (original)
+++ felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/runtime/ServiceComponentRuntimeImpl.java Mon Feb 27 13:59:18 2017
@@ -49,14 +49,12 @@ import org.osgi.util.promise.Promises;
 
 public class ServiceComponentRuntimeImpl implements ServiceComponentRuntime
 {
-
     private static final String[] EMPTY = {};
 
     private final BundleContext context;
     private final ComponentRegistry componentRegistry;
 
-
-    public ServiceComponentRuntimeImpl(BundleContext context,ComponentRegistry componentRegistry)
+    public ServiceComponentRuntimeImpl(final BundleContext context, final ComponentRegistry componentRegistry)
     {
         this.context = context;
         this.componentRegistry = componentRegistry;
@@ -165,8 +163,13 @@ public class ServiceComponentRuntimeImpl
     {
         try
         {
-            ComponentHolder<?> holder = getHolderFromDescription( description);
-            return holder.enableComponents(true);
+            final ComponentHolder<?> holder = getHolderFromDescription( description);
+            final boolean doUpdate = !holder.isEnabled();
+            final Promise<Void> result =  holder.enableComponents(true);
+            if ( doUpdate ) {
+                this.componentRegistry.updateChangeCount();
+            }
+            return result;
         }
         catch ( IllegalStateException ise)
         {
@@ -182,8 +185,13 @@ public class ServiceComponentRuntimeImpl
     {
         try
         {
-            ComponentHolder<?> holder = getHolderFromDescription( description);
-            return holder.disableComponents(true); //synchronous
+            final ComponentHolder<?> holder = getHolderFromDescription( description);
+            final boolean doUpdate = holder.isEnabled();
+            final Promise<Void> result = holder.disableComponents(true); //synchronous
+            if ( doUpdate ) {
+                this.componentRegistry.updateChangeCount();
+            }
+            return result;
         }
         catch ( IllegalStateException ise)
         {

Modified: felix/trunk/osgi-r7/scr/src/test/java/org/apache/felix/scr/impl/manager/SingleComponentManagerTest.java
URL: http://svn.apache.org/viewvc/felix/trunk/osgi-r7/scr/src/test/java/org/apache/felix/scr/impl/manager/SingleComponentManagerTest.java?rev=1784564&r1=1784563&r2=1784564&view=diff
==============================================================================
--- felix/trunk/osgi-r7/scr/src/test/java/org/apache/felix/scr/impl/manager/SingleComponentManagerTest.java (original)
+++ felix/trunk/osgi-r7/scr/src/test/java/org/apache/felix/scr/impl/manager/SingleComponentManagerTest.java Mon Feb 27 13:59:18 2017
@@ -25,9 +25,6 @@ import static org.junit.Assert.assertSam
 import java.lang.reflect.Field;
 import java.util.concurrent.atomic.AtomicInteger;
 
-import javax.imageio.spi.ServiceRegistry;
-
-import org.apache.felix.scr.impl.inject.ComponentMethods;
 import org.apache.felix.scr.impl.inject.ComponentMethodsImpl;
 import org.apache.felix.scr.impl.manager.AbstractComponentManager.State;
 import org.apache.felix.scr.impl.metadata.ComponentMetadata;
@@ -43,131 +40,151 @@ import org.osgi.service.cm.Configuration
 
 public class SingleComponentManagerTest
 {
-    
+
     private ServiceRegistration serviceRegistration = Mockito.mock(ServiceRegistration.class);
     private ServiceReference serviceReference = Mockito.mock(ServiceReference.class);
     private ComponentActivator componentActivator = new ComponentActivator() {
 
+        @Override
         public boolean isLogEnabled(int level)
         {
             // TODO Auto-generated method stub
             return false;
         }
 
+        @Override
         public void log(int level, String pattern, Object[] arguments, ComponentMetadata metadata, Long componentId,
             Throwable ex)
         {
             // TODO Auto-generated method stub
-            
+
         }
 
+        @Override
         public void log(int level, String message, ComponentMetadata metadata, Long componentId, Throwable ex)
         {
             // TODO Auto-generated method stub
-            
+
         }
 
+        @Override
         public void addServiceListener(String className, Filter filter,
             ExtendedServiceListener<ExtendedServiceEvent> listener)
         {
             // TODO Auto-generated method stub
-            
+
         }
 
+        @Override
         public void removeServiceListener(String className, Filter filter,
             ExtendedServiceListener<ExtendedServiceEvent> listener)
         {
             // TODO Auto-generated method stub
-            
+
         }
 
+        @Override
         public BundleContext getBundleContext()
         {
             // TODO Auto-generated method stub
             return null;
         }
 
+        @Override
         public boolean isActive()
         {
             // TODO Auto-generated method stub
             return false;
         }
 
+        @Override
         public ScrConfiguration getConfiguration()
         {
             // TODO Auto-generated method stub
             return null;
         }
 
+        @Override
         public void schedule(Runnable runnable)
         {
             // TODO Auto-generated method stub
-            
+
         }
 
+        @Override
         public long registerComponentId(AbstractComponentManager<?> sAbstractComponentManager)
         {
             // TODO Auto-generated method stub
             return 0;
         }
 
+        @Override
         public void unregisterComponentId(AbstractComponentManager<?> sAbstractComponentManager)
         {
             // TODO Auto-generated method stub
-            
+
         }
 
+        @Override
         public <T> boolean enterCreate(ServiceReference<T> reference)
         {
             // TODO Auto-generated method stub
             return false;
         }
 
+        @Override
         public <T> void leaveCreate(ServiceReference<T> reference)
         {
             // TODO Auto-generated method stub
-            
+
         }
 
+        @Override
         public <S, T> void registerMissingDependency(DependencyManager<S, T> dependencyManager,
             ServiceReference<T> serviceReference, int trackingCount)
         {
             // TODO Auto-generated method stub
-            
+
         }
 
+        @Override
         public <T> void missingServicePresent(ServiceReference<T> serviceReference)
         {
             // TODO Auto-generated method stub
-            
+
         }
 
+        @Override
         public void enableComponent(String name)
         {
             // TODO Auto-generated method stub
-            
         }
 
+        @Override
         public void disableComponent(String name)
         {
             // TODO Auto-generated method stub
-            
         }
 
+        @Override
         public RegionConfigurationSupport setRegionConfigurationSupport(ServiceReference<ConfigurationAdmin> reference)
         {
             // TODO Auto-generated method stub
             return null;
         }
 
+        @Override
         public void unsetRegionConfigurationSupport(RegionConfigurationSupport rcs)
         {
             // TODO Auto-generated method stub
-            
         }
-        
+
+        @Override
+        public void updateChangeCount() {
+            // TODO Auto-generated method stub
+        }
     };
-    
+
     @Test
     public void testGetService() throws Exception {
         ComponentMetadata cm = new ComponentMetadata(DSVersion.DS13);