Fix FELIX-4106
Defensive service registration and update

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1489947 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/IPojoFactory.java b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/IPojoFactory.java
index 862eb9a..99a2ebe 100644
--- a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/IPojoFactory.java
+++ b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/IPojoFactory.java
@@ -22,6 +22,7 @@
 import org.apache.felix.ipojo.architecture.PropertyDescription;

 import org.apache.felix.ipojo.extender.internal.Extender;

 import org.apache.felix.ipojo.metadata.Element;

+import org.apache.felix.ipojo.util.Log;

 import org.apache.felix.ipojo.util.Logger;

 import org.apache.felix.ipojo.util.SecurityHelper;

 import org.osgi.framework.BundleContext;

@@ -586,7 +587,7 @@
      * Destroys the factory.

      * The factory cannot be restarted. Only the {@link Extender} can call this method.

      */

-    synchronized void dispose() {

+    public synchronized void dispose() {

         stop(); // Does not hold the lock.

         m_requiredHandlers.clear();

         m_listeners = null;

@@ -628,13 +629,17 @@
             }

             BundleContext bc = SecurityHelper.selectContextToRegisterServices(m_componentDesc.getFactoryInterfacesToPublish(),

                     m_context, getIPOJOBundleContext());

-            m_sr =

-                    bc.registerService(m_componentDesc.getFactoryInterfacesToPublish(), this, m_componentDesc

-                            .getPropertiesToPublish());

+            if (SecurityHelper.canRegisterService(bc)) {

+                m_sr =

+                        bc.registerService(m_componentDesc.getFactoryInterfacesToPublish(), this, m_componentDesc

+                                .getPropertiesToPublish());

+                m_logger.log(Logger.INFO, "Factory " + m_factoryName + " started");

+            } else {

+                m_logger.log(Log.ERROR, "Cannot register the Factory service with the bundle context of the bundle "

+                        + bc.getBundle().getBundleId() + " - the bundle is in the state " + bc.getBundle().getState()

+                );

+            }

         }

-

-        m_logger.log(Logger.INFO, "Factory " + m_factoryName + " started");

-

     }

 

     /**

@@ -777,7 +782,9 @@
 

                 m_state = VALID;

                 if (m_sr != null) {

-                    m_sr.setProperties(m_componentDesc.getPropertiesToPublish());

+                    if (SecurityHelper.canUpdateService(m_sr)) {

+                        m_sr.setProperties(m_componentDesc.getPropertiesToPublish());

+                    }

                 }

 

                 // Register the factory on the ConfigurationTracker

@@ -812,7 +819,8 @@
 

                 m_componentInstances.clear();

 

-                if (m_sr != null) {

+                if (SecurityHelper.canUpdateService(m_sr)) {

+                    // No null check required as the security helper is checking this too.

                     m_sr.setProperties(m_componentDesc.getPropertiesToPublish());

                 }

             }

diff --git a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/AbstractService.java b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/AbstractService.java
index 1fa48f0..e4f201a 100644
--- a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/AbstractService.java
+++ b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/AbstractService.java
@@ -33,12 +33,10 @@
      * The bundle context.
      */
     private final BundleContext m_bundleContext;
-
     /**
      * The service specification.
      */
     private final Class<?> m_type;
-
     /**
      * The service registration.
      */
diff --git a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/handlers/architecture/ArchitectureHandler.java b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/handlers/architecture/ArchitectureHandler.java
index e8cce04..4078b87 100644
--- a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/handlers/architecture/ArchitectureHandler.java
+++ b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/handlers/architecture/ArchitectureHandler.java
@@ -25,6 +25,7 @@
 import org.apache.felix.ipojo.architecture.Architecture;
 import org.apache.felix.ipojo.architecture.InstanceDescription;
 import org.apache.felix.ipojo.metadata.Element;
+import org.apache.felix.ipojo.util.SecurityHelper;
 import org.osgi.framework.ServiceRegistration;
 
 import java.util.Dictionary;
@@ -58,12 +59,16 @@
         Dictionary<String, String> dict = new Hashtable<String, String>();
         dict.put(ARCHITECTURE_INSTANCE, m_name);
 
-        debug("Registering architecture service for " + m_name);
-        m_serviceRegistration = getInstanceManager().getContext().registerService(Architecture.class.getName(), this, dict);
-
-        // We can't use the regular handler stateChanged method as this method is not called when the instance is
-        // disposed. This handler stays actives until the instance disposal.
-        getInstanceManager().addInstanceStateListener(this);
+        if (SecurityHelper.canRegisterService(getInstanceManager().getContext())) {
+            debug("Registering architecture service for " + m_name);
+            m_serviceRegistration = getInstanceManager().getContext().registerService(Architecture.class.getName(), this, dict);
+            // We can't use the regular handler stateChanged method as this method is not called when the instance is
+            // disposed. This handler stays actives until the instance disposal.
+            getInstanceManager().addInstanceStateListener(this);
+        } else {
+            error("Cannot register the architecture service, bundle " + getInstanceManager().getContext().getBundle()
+                    .getBundleId() + " is not in a valid state" );
+        }
     }
 
     /**
diff --git a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/handlers/configuration/ConfigurationHandler.java b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/handlers/configuration/ConfigurationHandler.java
index 609bcfc..0dead11 100644
--- a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/handlers/configuration/ConfigurationHandler.java
+++ b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/handlers/configuration/ConfigurationHandler.java
@@ -358,7 +358,8 @@
 
             // Security Check
             if (SecurityHelper.hasPermissionToRegisterService(ManagedService.class.getName(),
-                    getInstanceManager().getContext())) {
+                    getInstanceManager().getContext())  && SecurityHelper.canRegisterService
+                    (getInstanceManager().getContext())) {
                 m_sr = getInstanceManager().getContext().registerService(ManagedService.class.getName(), this, props);
             } else {
                 error("Cannot register the ManagedService - The bundle "
diff --git a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/handlers/providedservice/ProvidedService.java b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/handlers/providedservice/ProvidedService.java
index 62d53b2..88e5e84 100644
--- a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/handlers/providedservice/ProvidedService.java
+++ b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/handlers/providedservice/ProvidedService.java
@@ -351,7 +351,7 @@
                     BundleContext bc = m_handler.getInstanceManager().getContext();
                     // Security check
                     if (SecurityHelper.hasPermissionToRegisterServices(
-                            m_serviceSpecifications, bc)) {
+                            m_serviceSpecifications, bc)  && SecurityHelper.canRegisterService(bc)) {
                         serviceProperties = getServiceProperties();
                         m_strategy.onPublication(getInstanceManager(),
                                 getServiceSpecificationsToRegister(),
@@ -373,7 +373,8 @@
 
         // An update may happen during the registration, re-check and apply.
         // This must be call outside the synchronized block.
-        if (reg != null && m_wasUpdated) {
+        // If the registration is null, the security helper returns false.
+        if (m_wasUpdated  && SecurityHelper.canUpdateService(reg)) {
             Properties updated = getServiceProperties();
             reg.setProperties((Dictionary) updated);
             m_publishedProperties = updated;
@@ -497,22 +498,27 @@
 
             // First check, are the size equals
             if (oldProps.size() != newProps.size()) {
-                m_handler.info("Updating Registration : " + oldProps.size() + " / " + newProps.size());
-                m_publishedProperties = updated;
-                m_serviceRegistration.setProperties((Dictionary) updated);
+                if (SecurityHelper.canUpdateService(m_serviceRegistration)) {
+                    m_handler.info("Updating Registration : " + oldProps.size() + " / " + newProps.size());
+                    m_publishedProperties = updated;
+                    m_serviceRegistration.setProperties(updated);
+                }
             } else {
                 // Check changes
                 Enumeration keys = oldProps.keys();
-                while (keys.hasMoreElements()) {
+                boolean hasChanged = false;
+                while (! hasChanged  && keys.hasMoreElements()) {
                     String k = (String) keys.nextElement();
                     Object val = oldProps.get(k);
                     if (! val.equals(updated.get(k))) {
-                        m_handler.info("Updating Registration : " + k);
-                        m_publishedProperties = updated;
-                        m_serviceRegistration.setProperties((Dictionary) updated);
-                        return;
+                        hasChanged = true;
                     }
                 }
+                if (hasChanged  && SecurityHelper.canUpdateService(m_serviceRegistration)) {
+                    m_handler.info("Updating Registration : " + updated);
+                    m_publishedProperties = updated;
+                    m_serviceRegistration.setProperties(updated);
+                }
             }
         } else {
             // Need to be updated later.
diff --git a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/handlers/providedservice/ProvidedServiceHandler.java b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/handlers/providedservice/ProvidedServiceHandler.java
index ddea97b..a0131d8 100644
--- a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/handlers/providedservice/ProvidedServiceHandler.java
+++ b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/handlers/providedservice/ProvidedServiceHandler.java
@@ -19,11 +19,7 @@
 package org.apache.felix.ipojo.handlers.providedservice;
 
 import java.lang.reflect.Field;
-import java.util.Dictionary;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Set;
+import java.util.*;
 
 import org.apache.felix.ipojo.ConfigurationException;
 import org.apache.felix.ipojo.HandlerFactory;
@@ -59,7 +55,7 @@
     /**
      * The list of the provided service.
      */
-    private ProvidedService[] m_providedServices = new ProvidedService[0];
+    private Set<ProvidedService> m_providedServices = new LinkedHashSet<ProvidedService>();
 
     /**
      * The handler description.
@@ -67,32 +63,11 @@
     private ProvidedServiceHandlerDescription m_description;
 
     /**
-     * Add a provided service to the list .
-     *
-     * @param svc : the provided service to add
-     */
-    private void addProvidedService(ProvidedService svc) {
-        // Verify that the provided service is not already in the array.
-        for (int i = 0; i < m_providedServices.length; i++) {
-            if (m_providedServices[i] == svc) { return; }
-        }
-
-        if (m_providedServices.length > 0) {
-            ProvidedService[] newPS = new ProvidedService[m_providedServices.length + 1];
-            System.arraycopy(m_providedServices, 0, newPS, 0, m_providedServices.length);
-            newPS[m_providedServices.length] = svc;
-            m_providedServices = newPS;
-        } else {
-            m_providedServices = new ProvidedService[] { svc };
-        }
-    }
-
-    /**
      * Get the array of provided service.
      * @return the list of the provided service.
      */
     public ProvidedService[] getProvidedServices() {
-        return m_providedServices;
+        return m_providedServices.toArray(new ProvidedService[m_providedServices.size()]);
     }
 
     /**
@@ -100,21 +75,21 @@
      * @param componentMetadata : the component type metadata
      * @param configuration : the instance configuration
      * @throws ConfigurationException : the metadata are not correct.
-     * @see org.apache.felix.ipojo.Handler#configure(org.apache.felix.ipojo.InstanceManager, org.apache.felix.ipojo.metadata.Element, java.util.Dictionary)
+     * @see org.apache.felix.ipojo.Handler#configure(org.apache.felix.ipojo.metadata.Element, java.util.Dictionary)
      */
     public void configure(Element componentMetadata, Dictionary configuration) throws ConfigurationException {
-        m_providedServices = new ProvidedService[0];
+        m_providedServices.clear();
         // Create the dependency according to the component metadata
         Element[] providedServices = componentMetadata.getElements("Provides");
-        for (int i = 0; i < providedServices.length; i++) {
-            String[] serviceSpecifications = ParseUtils.parseArrays(providedServices[i].getAttribute("specifications")); // Set by the initialize component factory.
+        for (Element providedService : providedServices) {
+            String[] serviceSpecifications = ParseUtils.parseArrays(providedService.getAttribute("specifications")); // Set by the initialize component factory.
 
             // Get the factory policy
             int factory = ProvidedService.SINGLETON_STRATEGY;
             Class custom = null;
-            String strategy = providedServices[i].getAttribute("strategy");
+            String strategy = providedService.getAttribute("strategy");
             if (strategy == null) {
-                strategy = providedServices[i].getAttribute("factory");
+                strategy = providedService.getAttribute("factory");
             }
             if (strategy != null) {
                 if ("singleton".equalsIgnoreCase(strategy)) {
@@ -129,7 +104,7 @@
                     // Customized policy
                     try {
                         custom = getInstanceManager().getContext().getBundle().loadClass(strategy);
-                        if (! CreationStrategy.class.isAssignableFrom(custom)) {
+                        if (!CreationStrategy.class.isAssignableFrom(custom)) {
                             throw new ConfigurationException("The custom creation policy class " + custom.getName() + " does not implement " + CreationStrategy.class.getName());
                         }
                     } catch (ClassNotFoundException e) {
@@ -145,20 +120,20 @@
             ProvidedService svc = new ProvidedService(this, serviceSpecifications, factory, custom, configuration);
 
             // Post-Registration callback
-            String post = providedServices[i].getAttribute("post-registration");
+            String post = providedService.getAttribute("post-registration");
             if (post != null) {
-                Callback cb = new Callback(post, new Class[] {ServiceReference.class}, false, getInstanceManager());
+                Callback cb = new Callback(post, new Class[]{ServiceReference.class}, false, getInstanceManager());
                 svc.setPostRegistrationCallback(cb);
             }
 
-            post = providedServices[i].getAttribute("post-unregistration");
+            post = providedService.getAttribute("post-unregistration");
             if (post != null) {
                 // TODO Can we really send the service reference here ?
-                Callback cb = new Callback(post, new Class[] {ServiceReference.class}, false, getInstanceManager());
+                Callback cb = new Callback(post, new Class[]{ServiceReference.class}, false, getInstanceManager());
                 svc.setPostUnregistrationCallback(cb);
             }
 
-            Element[] props = providedServices[i].getElements("Property");
+            Element[] props = providedService.getElements("Property");
             if (props != null) {
                 //Property[] properties = new Property[props.length];
                 Property[] properties = new Property[props.length];
@@ -188,19 +163,19 @@
                 svc.setProperties(properties);
             }
 
-            Element[] controllers = providedServices[i].getElements("Controller");
+            Element[] controllers = providedService.getElements("Controller");
             if (controllers != null) {
-                for (int k = 0; k < controllers.length; k++) {
-                    String field = controllers[k].getAttribute("field");
+                for (Element controller : controllers) {
+                    String field = controller.getAttribute("field");
                     if (field == null) {
                         throw new ConfigurationException("The field attribute of a controller is mandatory");
                     }
 
-                    String v = controllers[k].getAttribute("value");
-                    boolean value = ! (v != null  && v.equalsIgnoreCase("false"));
-                    String s = controllers[k].getAttribute("specification");
+                    String v = controller.getAttribute("value");
+                    boolean value = !(v != null && v.equalsIgnoreCase("false"));
+                    String s = controller.getAttribute("specification");
                     if (s == null) {
-                        s ="ALL";
+                        s = "ALL";
                     }
                     svc.setController(field, value, s);
 
@@ -209,18 +184,18 @@
             }
 
             if (checkProvidedService(svc)) {
-                addProvidedService(svc);
+                m_providedServices.add(svc);
             } else {
-                StringBuffer itfs = new StringBuffer();
-                for (int j = 0; j < serviceSpecifications.length; j++) {
+                StringBuilder itfs = new StringBuilder();
+                for (String serviceSpecification : serviceSpecifications) {
                     itfs.append(' ');
-                    itfs.append(serviceSpecifications[j]);
+                    itfs.append(serviceSpecification);
                 }
                 throw new ConfigurationException("The provided service" + itfs + " is not valid");
             }
 
             // Initialize the description.
-            m_description = new ProvidedServiceHandlerDescription(this, m_providedServices);
+            m_description = new ProvidedServiceHandlerDescription(this, getProvidedServices());
 
         }
     }
@@ -234,12 +209,14 @@
      * @param classes : the set of extended classes
      * @throws ClassNotFoundException : occurs when an interface cannot be loaded.
      */
-    private void computeInterfacesAndSuperClasses(String[] specs, String parent, Bundle bundle, Set interfaces, Set classes) throws ClassNotFoundException {
+    private void computeInterfacesAndSuperClasses(String[] specs, String parent, Bundle bundle,
+                                                  Set<String> interfaces,
+            Set<String> classes) throws ClassNotFoundException {
         // First iterate on found specification in manipulation metadata
-        for (int i = 0; i < specs.length; i++) {
-            interfaces.add(specs[i]);
+        for (String spec : specs) {
+            interfaces.add(spec);
             // Iterate on interfaces implemented by the current interface
-            Class clazz = bundle.loadClass(specs[i]);
+            Class clazz = bundle.loadClass(spec);
             collectInterfaces(clazz, interfaces, bundle);
         }
 
@@ -259,11 +236,11 @@
      * @param bundle : bundle
      * @throws ClassNotFoundException : occurs when an interface cannot be loaded.
      */
-    private void collectInterfaces(Class clazz, Set acc, Bundle bundle) throws ClassNotFoundException {
+    private void collectInterfaces(Class clazz, Set<String> acc, Bundle bundle) throws ClassNotFoundException {
         Class[] clazzes = clazz.getInterfaces();
-        for (int i = 0; i < clazzes.length; i++) {
-            acc.add(clazzes[i].getName());
-            collectInterfaces(clazzes[i], acc, bundle);
+        for (Class clazze : clazzes) {
+            acc.add(clazze.getName());
+            collectInterfaces(clazze, acc, bundle);
         }
     }
 
@@ -275,11 +252,12 @@
      * @param bundle : bundle.
      * @throws ClassNotFoundException : occurs if an interface cannot be load.
      */
-    private void collectInterfacesFromClass(Class clazz, Set acc, Bundle bundle) throws ClassNotFoundException {
+    private void collectInterfacesFromClass(Class clazz, Set<String> acc,
+                                            Bundle bundle) throws ClassNotFoundException {
         Class[] clazzes = clazz.getInterfaces();
-        for (int i = 0; i < clazzes.length; i++) {
-            acc.add(clazzes[i].getName());
-            collectInterfaces(clazzes[i], acc, bundle);
+        for (Class clazze : clazzes) {
+            acc.add(clazze.getName());
+            collectInterfaces(clazze, acc, bundle);
         }
         // Iterate on parent classes
         Class sup = clazz.getSuperclass();
@@ -295,7 +273,8 @@
      * @param bundle : bundle.
      * @throws ClassNotFoundException : occurs if an interface cannot be load.
      */
-    private void collectParentClassesFromClass(Class clazz, Set acc, Bundle bundle) throws ClassNotFoundException {
+    private void collectParentClassesFromClass(Class clazz, Set<String> acc,
+                                               Bundle bundle) throws ClassNotFoundException {
         Class parent = clazz.getSuperclass();
         if (parent != null) {
             acc.add(parent.getName());
@@ -427,17 +406,15 @@
      * @param pojo : the pojo object on which the field is accessed
      * @param fieldName : field name
      * @param value : new value
-     * @see org.apache.felix.ipojo.Handler#onSet(Object,
-     * java.lang.String, java.lang.Object)
+     * @see org.apache.felix.ipojo.FieldInterceptor#onSet(Object, String, Object)
      */
     public void onSet(Object pojo, String fieldName, Object value) {
         // Verify that the field name correspond to a dependency
-        for (int i = 0; i < m_providedServices.length; i++) {
-            ProvidedService svc = m_providedServices[i];
+        for (ProvidedService svc : m_providedServices) {
             boolean update = false;
             for (int j = 0; j < svc.getProperties().length; j++) {
                 Property prop = svc.getProperties()[j];
-                if (fieldName.equals(prop.getField()) && ! prop.getValue().equals(value)) {
+                if (fieldName.equals(prop.getField()) && !prop.getValue().equals(value)) {
                     // it is the associated property
                     prop.setValue(value);
                     update = true;
@@ -451,7 +428,7 @@
                 if (value instanceof Boolean) {
                     ctrl.setValue((Boolean) value);
                 } else {
-                    warn("Boolean value expected for the service controler " + fieldName);
+                    warn("Boolean value expected for the service controller " + fieldName);
                 }
             }
         }
@@ -465,12 +442,10 @@
      * @param fieldName : field name
      * @param value : value pushed by the previous handler
      * @return the stored value or the previous value.
-     * @see org.apache.felix.ipojo.Handler#onGet(Object,
-     * java.lang.String, java.lang.Object)
+     * @see org.apache.felix.ipojo.FieldInterceptor#onGet(Object, String, Object)
      */
     public Object onGet(Object pojo, String fieldName, Object value) {
-        for (int i = 0; i < m_providedServices.length; i++) {
-            ProvidedService svc = m_providedServices[i];
+        for (ProvidedService svc : m_providedServices) {
             for (int j = 0; j < svc.getProperties().length; j++) {
                 Property prop = svc.getProperties()[j];
                 if (fieldName.equals(prop.getField())) {
@@ -480,7 +455,7 @@
             }
             ServiceController ctrl = svc.getController(fieldName);
             if (ctrl != null) {
-                return new Boolean(ctrl.getValue());
+                return ctrl.getValue();
             }
         }
         // Else it is not a property
@@ -488,27 +463,26 @@
     }
 
     /**
-     * Register the services if the new state is VALID. Unregister the services
+     * Register the services if the new state is VALID. Un-register the services
      * if the new state is UNRESOLVED.
      *
      * @param state : the new instance state.
      * @see org.apache.felix.ipojo.Handler#stateChanged(int)
      */
     public void stateChanged(int state) {
-        // If the new state is INVALID => unregister all the services
+        // If the new state is INVALID => un-register all the services
         if (state == InstanceManager.INVALID) {
-            for (int i = 0; i < m_providedServices.length; i++) {
-                m_providedServices[i].unregisterService();
+            for (ProvidedService m_providedService : m_providedServices) {
+                m_providedService.unregisterService();
             }
             return;
         }
 
         // If the new state is VALID => register all the services
         if (state == InstanceManager.VALID) {
-            for (int i = 0; i < m_providedServices.length; i++) {
-                m_providedServices[i].registerService();
+            for (ProvidedService ps : m_providedServices) {
+                ps.registerService();
             }
-            return;
         }
     }
 
@@ -517,9 +491,9 @@
      * @param dict : dictionary of properties to add
      */
     public void addProperties(Dictionary dict) {
-        for (int i = 0; i < m_providedServices.length; i++) {
-            m_providedServices[i].addProperties(dict);
-            m_providedServices[i].update();
+        for (ProvidedService ps : m_providedServices) {
+            ps.addProperties(dict);
+            ps.update();
         }
     }
 
@@ -529,9 +503,9 @@
      * @param dict : dictionary of properties to delete.
      */
     public void removeProperties(Dictionary dict) {
-        for (int i = 0; i < m_providedServices.length; i++) {
-            m_providedServices[i].deleteProperties(dict);
-            m_providedServices[i].update();
+        for (ProvidedService ps : m_providedServices) {
+            ps.deleteProperties(dict);
+            ps.update();
         }
     }
 
@@ -554,10 +528,10 @@
             ProvidedService svc = getProvidedServices()[j];
             Property[] props = svc.getProperties();
             boolean update = false;
-            for (int k = 0; k < props.length; k++) {
-                if (dict.get(props[k].getName()) != null) {
+            for (Property prop : props) {
+                if (dict.get(prop.getName()) != null) {
                     update = true;
-                    props[k].setValue(dict.get(props[k].getName()));
+                    prop.setValue(dict.get(prop.getName()));
                 }
             }
             if (update) {
@@ -578,12 +552,12 @@
         Element[] provides = metadata.getElements("provides");
         PojoMetadata manipulation = getFactory().getPojoMetadata();
 
-        for (int i = 0; i < provides.length; i++) {
+        for (Element provide : provides) {
             // First : create the serviceSpecification list
             String[] serviceSpecification = manipulation.getInterfaces();
             String parent = manipulation.getSuperClass();
-            Set interfaces = new HashSet();
-            Set parentClasses = new HashSet();
+            Set<String> interfaces = new HashSet<String>();
+            Set<String> parentClasses = new HashSet<String>();
             try {
                 computeInterfacesAndSuperClasses(serviceSpecification, parent, desc.getBundleContext().getBundle(), interfaces, parentClasses);
                 getLogger().log(Logger.INFO, "Collected interfaces from " + metadata.getAttribute("classname") + " : " + interfaces);
@@ -592,24 +566,24 @@
                 throw new ConfigurationException("An interface or parent class cannot be loaded", e);
             }
 
-            String serviceSpecificationStr = provides[i].getAttribute("specifications");
+            String serviceSpecificationStr = provide.getAttribute("specifications");
             if (serviceSpecificationStr == null) {
-                serviceSpecificationStr = provides[i].getAttribute("interface");
+                serviceSpecificationStr = provide.getAttribute("interface");
                 if (serviceSpecificationStr != null) {
                     warn("The 'interface' attribute is deprecated, use the 'specifications' attribute instead of 'interface'");
                 }
             }
 
             if (serviceSpecificationStr != null) {
-                List itfs = ParseUtils.parseArraysAsList(serviceSpecificationStr);
-                for (int j = 0; j < itfs.size(); j++) {
-                    if (! interfaces.contains(itfs.get(j))
-                            && ! parentClasses.contains(itfs.get(j))
-                            && ! desc.getFactory().getClassName().equals(itfs.get(j))) {
-                            desc.getFactory().getLogger().log(Logger.ERROR, "The specification " + itfs.get(j) + " is not implemented by " + metadata.getAttribute("classname"));
+                List<String> itfs = ParseUtils.parseArraysAsList(serviceSpecificationStr);
+                for (String itf : itfs)
+                    if (!interfaces.contains(itf)
+                            && !parentClasses.contains(itf)
+                            && !desc.getFactory().getClassName().equals(itf)) {
+                        desc.getFactory().getLogger().log(Logger.ERROR, "The specification " + itf + " is not implemented by " + metadata.getAttribute("classname"));
                     }
-                }
-                interfaces = new HashSet(itfs);
+                interfaces.clear();
+                interfaces.addAll(itfs);
             }
 
             if (interfaces.isEmpty()) {
@@ -618,11 +592,9 @@
             }
 
             StringBuffer specs = null;
-            Set set = new HashSet(interfaces);
+            Set<String> set = new HashSet<String>(interfaces);
             set.remove(Pojo.class.getName()); // Remove POJO.
-            Iterator iterator = set.iterator();
-            while (iterator.hasNext()) {
-                String spec = (String) iterator.next();
+            for (String spec : set) {
                 desc.addProvidedServiceSpecification(spec);
                 if (specs == null) {
                     specs = new StringBuffer("{");
@@ -634,9 +606,9 @@
             }
 
             specs.append('}');
-            provides[i].addAttribute(new Attribute("specifications", specs.toString())); // Add interface attribute to avoid checking in the configure method
+            provide.addAttribute(new Attribute("specifications", specs.toString())); // Add interface attribute to avoid checking in the configure method
 
-            Element[] props = provides[i].getElements("property");
+            Element[] props = provide.getElements("property");
             for (int j = 0; props != null && j < props.length; j++) {
                 String name = props[j].getAttribute("name");
                 String value = props[j].getAttribute("value");
diff --git a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/util/SecurityHelper.java b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/util/SecurityHelper.java
index 04d576f..32d4d36 100644
--- a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/util/SecurityHelper.java
+++ b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/util/SecurityHelper.java
@@ -20,8 +20,10 @@
 
 import java.security.Permission;
 
+import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.ServicePermission;
+import org.osgi.framework.ServiceRegistration;
 
 
 /**
@@ -45,8 +47,8 @@
     public static BundleContext selectContextToRegisterServices(String[] itfs,
             BundleContext comp, BundleContext ipojo) {
         if (System.getSecurityManager() != null) {
-            for (int i = 0; i < itfs.length; i++) {
-                final Permission perm = new ServicePermission(itfs[i],
+            for (String itf : itfs) {
+                final Permission perm = new ServicePermission(itf,
                         ServicePermission.REGISTER);
                 if (!comp.getBundle().hasPermission(perm)) {
                     return ipojo;
@@ -132,8 +134,8 @@
     public static boolean hasPermissionToGetServices(String[] itfs,
             BundleContext comp) {
         if (System.getSecurityManager() != null) {
-            for (int i = 0; i < itfs.length; i++) {
-                final Permission perm = new ServicePermission(itfs[i],
+            for (String itf : itfs) {
+                final Permission perm = new ServicePermission(itf,
                         ServicePermission.GET);
                 if (!comp.getBundle().hasPermission(perm)) {
                     return false;
@@ -172,8 +174,8 @@
     public static boolean hasPermissionToRegisterServices(String[] itfs,
             BundleContext comp) {
         if (System.getSecurityManager() != null) {
-            for (int i = 0; i < itfs.length; i++) {
-                final Permission perm = new ServicePermission(itfs[i],
+            for (String itf : itfs) {
+                final Permission perm = new ServicePermission(itf,
                         ServicePermission.REGISTER);
                 if (!comp.getBundle().hasPermission(perm)) {
                     return false;
@@ -183,4 +185,34 @@
         return true;
     }
 
+    /**
+     * Checks that the given bundle context is in a state where it is possible to register services.
+     * This methods ensures that the bundle associated to the given context, is starting or active.
+     * @param context the bundle context
+     * @return {@literal true} if the context can register a service, {@literal false} otherwise.
+     */
+    public static boolean canRegisterService(BundleContext context) {
+        return context.getBundle().getState() == Bundle.ACTIVE
+                || context.getBundle().getState() == Bundle.STARTING;
+    }
+
+    /**
+     * Checks that the given service registration can be updated.
+     * This methods ensures that the bundle associated to the given service, is starting or active.
+     * @param registration the service registration
+     * @return {@literal true} if the service can be updated, {@literal false} otherwise.
+     */
+    public static boolean canUpdateService(ServiceRegistration registration) {
+        if (registration == null) {
+            return false;
+        }
+        try {
+            BundleContext context = registration.getReference().getBundle().getBundleContext();
+            return context.getBundle().getState() == Bundle.ACTIVE
+                    || context.getBundle().getState() == Bundle.STARTING;
+        } catch (IllegalStateException e) {
+            return false;
+        }
+    }
+
 }