You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by cl...@apache.org on 2013/04/29 14:59:53 UTC

svn commit: r1477027 [3/3] - in /felix/trunk/ipojo/runtime: core-it/src/it/ipojo-core-configuration-admin-test/ core-it/src/it/ipojo-core-configuration-admin-test/src/ core-it/src/it/ipojo-core-configuration-admin-test/src/main/ core-it/src/it/ipojo-co...

Added: felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/ConfigurationTracker.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/ConfigurationTracker.java?rev=1477027&view=auto
==============================================================================
--- felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/ConfigurationTracker.java (added)
+++ felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/ConfigurationTracker.java Mon Apr 29 12:59:52 2013
@@ -0,0 +1,332 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo;
+
+import org.apache.felix.ipojo.extender.internal.Extender;
+import org.apache.felix.ipojo.util.Log;
+import org.apache.felix.ipojo.util.Logger;
+import org.apache.felix.ipojo.util.ServiceLocator;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.cm.*;
+import org.osgi.service.cm.ConfigurationException;
+
+import java.io.IOException;
+import java.util.*;
+
+/**
+ * An object tracking configuration from the configuration admin. It delegates to the underlying factories or
+ * component instance the action.
+ * <p/>
+ * This class implements a Configuration Listener, so events are received asynchronously.
+ */
+public class ConfigurationTracker implements ConfigurationListener {
+
+    /**
+     * The tracker instance.
+     */
+    private static ConfigurationTracker m_singleton;
+    private final ServiceRegistration<ConfigurationListener> m_registration;
+    private final BundleContext m_context;
+    private final Logger m_logger;
+    private Map<String, IPojoFactory> m_factories = new HashMap<String, IPojoFactory>();
+
+    public ConfigurationTracker() {
+        m_context = Extender.getIPOJOBundleContext();
+        m_logger = new Logger(m_context, "iPOJO Configuration Admin listener", Log.INFO);
+        // register as listener for configurations
+        Dictionary<String, Object> props = new Hashtable<String, Object>();
+        props.put(Constants.SERVICE_DESCRIPTION, "iPOJO Configuration Admin Listener");
+        props.put(Constants.SERVICE_VENDOR, "The Apache Software Foundation");
+        m_registration = m_context.registerService(ConfigurationListener.class, this, props);
+    }
+
+    public static void initialize() {
+        synchronized (ConfigurationTracker.class) {
+            if (m_singleton == null) {
+                m_singleton = new ConfigurationTracker();
+            }
+        }
+    }
+
+    public static void shutdown() {
+        m_singleton.dispose();
+    }
+
+    public static ConfigurationTracker get() {
+        return m_singleton;
+    }
+
+    /**
+     * This method must be called by the iPOJO System itself, and only once.
+     */
+    public synchronized void dispose() {
+        if (m_registration != null) {
+            m_registration.unregister();
+        }
+        m_factories.clear();
+    }
+
+    public synchronized void registerFactory(IPojoFactory factory) {
+        m_factories.put(factory.getFactoryName(), factory);
+
+        ServiceLocator<ConfigurationAdmin> locator = new ServiceLocator<ConfigurationAdmin>(ConfigurationAdmin
+                .class, m_context);
+        final ConfigurationAdmin admin = locator.get();
+        if (admin == null) {
+            return;
+        }
+
+        List<Configuration> configurations = findFactoryConfiguration(admin, factory);
+        for (Configuration configuration : configurations) {
+            try {
+                factory.updated(configuration.getPid(), configuration.getProperties());
+            } catch (ConfigurationException e) {
+                m_logger.log(Log.ERROR, "Cannot reconfigure instance " + configuration.getPid() + " from " +
+                        configuration.getFactoryPid() + " with the configuration : " + configuration.getProperties(),
+                        e);
+            }
+        }
+    }
+
+    public synchronized void instanceCreated(IPojoFactory factory, ComponentInstance instance) {
+        ServiceLocator<ConfigurationAdmin> locator = new ServiceLocator<ConfigurationAdmin>(ConfigurationAdmin
+                .class, m_context);
+        final ConfigurationAdmin admin = locator.get();
+        if (admin == null) {
+            return;
+        }
+
+        Configuration configuration = findSingletonConfiguration(admin, instance.getInstanceName());
+        if (configuration != null) {
+            Hashtable<String, Object> conf = copyConfiguration(configuration);
+            if (!conf.containsKey(Factory.INSTANCE_NAME_PROPERTY)) {
+                conf.put(Factory.INSTANCE_NAME_PROPERTY, configuration.getPid());
+            }
+            try {
+                instance.getFactory().reconfigure(conf);
+            } catch (UnacceptableConfiguration unacceptableConfiguration) {
+                m_logger.log(Log.ERROR, "Cannot reconfigure the instance " + configuration.getPid() + " - the " +
+                        "configuration is unacceptable", unacceptableConfiguration);
+            } catch (MissingHandlerException e) {
+                m_logger.log(Log.ERROR, "Cannot reconfigure the instance " + configuration.getPid() + " - factory is " +
+                        "invalid", e);
+            }
+        }
+    }
+
+    public synchronized void unregisterFactory(IPojoFactory factory) {
+        m_factories.remove(factory.getFactoryName());
+    }
+
+    public void configurationEvent(ConfigurationEvent event) {
+        String pid = event.getPid();
+        String factoryPid = event.getFactoryPid();
+
+        if (factoryPid == null) {
+            ComponentInstance instance = retrieveInstance(pid);
+            if (instance != null) {
+                manageConfigurationEventForSingleton(instance, event);
+            }
+        } else {
+            IPojoFactory factory = retrieveFactory(factoryPid);
+            if (factory != null) {
+                manageConfigurationEventForFactory(factory, event);
+            }
+            // Else the factory is unknown, do nothing.
+        }
+
+    }
+
+    private void manageConfigurationEventForFactory(final IPojoFactory factory, final ConfigurationEvent event) {
+        ServiceLocator<ConfigurationAdmin> locator = new ServiceLocator<ConfigurationAdmin>(ConfigurationAdmin
+                .class, m_context);
+
+        switch (event.getType()) {
+            case ConfigurationEvent.CM_DELETED:
+                factory.deleted(event.getPid());
+                break;
+            case ConfigurationEvent.CM_UPDATED:
+                final ConfigurationAdmin admin = locator.get();
+                if (admin == null) {
+                    break;
+                }
+                final Configuration config = getConfiguration(admin, event.getPid(),
+                        factory.getBundleContext().getBundle().getLocation());
+                if (config != null) {
+                    try {
+                        factory.updated(event.getPid(), config.getProperties());
+                    } catch (org.osgi.service.cm.ConfigurationException e) {
+                        m_logger.log(Log.ERROR, "Cannot reconfigure instance " + event.getPid() + " with the new " +
+                                "configuration " + config.getProperties(), e);
+                    }
+                }
+            default:
+                // To nothing.
+        }
+
+        locator.unget();
+    }
+
+    private void manageConfigurationEventForSingleton(final ComponentInstance instance,
+                                                      final ConfigurationEvent event) {
+        ServiceLocator<ConfigurationAdmin> locator = new ServiceLocator<ConfigurationAdmin>(ConfigurationAdmin
+                .class, m_context);
+
+        switch (event.getType()) {
+            case ConfigurationEvent.CM_DELETED:
+                instance.dispose();
+                break;
+            case ConfigurationEvent.CM_UPDATED:
+                final ConfigurationAdmin admin = locator.get();
+                if (admin == null) {
+                    break;
+                }
+                final Configuration config = getConfiguration(admin, event.getPid(),
+                        instance.getFactory().getBundleContext().getBundle().getLocation());
+                if (config != null) {
+                    Hashtable<String, Object> conf = copyConfiguration(config);
+                    if (!conf.containsKey(Factory.INSTANCE_NAME_PROPERTY)) {
+                        conf.put(Factory.INSTANCE_NAME_PROPERTY, event.getPid());
+                    }
+                    try {
+                        instance.getFactory().reconfigure(conf);
+                    } catch (UnacceptableConfiguration unacceptableConfiguration) {
+                        m_logger.log(Log.ERROR, "Cannot reconfigure the instance " + event.getPid() + " - the " +
+                                "configuration is unacceptable", unacceptableConfiguration);
+                    } catch (MissingHandlerException e) {
+                        m_logger.log(Log.ERROR, "Cannot reconfigure the instance " + event.getPid() + " - factory is " +
+                                "invalid", e);
+                    }
+                }
+            default:
+                // To nothing.
+        }
+
+        locator.unget();
+    }
+
+    private Hashtable<String, Object> copyConfiguration(Configuration config) {
+        Hashtable<String, Object> conf = new Hashtable<String, Object>();
+        // Copy configuration
+        Enumeration keys = config.getProperties().keys();
+        while (keys.hasMoreElements()) {
+            String key = (String) keys.nextElement();
+            conf.put(key, config.getProperties().get(key));
+        }
+        return conf;
+    }
+
+    private IPojoFactory retrieveFactory(String factoryPid) {
+        synchronized (this) {
+            return m_factories.get(factoryPid);
+        }
+    }
+
+    private ComponentInstance retrieveInstance(String instanceName) {
+        Collection<IPojoFactory> factories;
+        synchronized (this) {
+            factories = m_factories.values();
+        }
+        for (IPojoFactory factory : factories) {
+            ComponentInstance instance = factory.getInstanceByName(instanceName);
+            if (instance != null) {
+                return instance;
+            }
+        }
+        return null;
+    }
+
+    private Configuration getConfiguration(final ConfigurationAdmin admin, final String pid,
+                                           final String bundleLocation) {
+        if (admin == null) {
+            return null;
+        }
+
+        try {
+            // Even if it is possible, we don't build the filter with bundle.location to detect the case where the
+            // configuration exists but can't be managed by iPOJO.
+            final Configuration cfg = admin.getConfiguration(pid);
+
+            if (bundleLocation.equals(cfg.getBundleLocation())) {
+                return cfg;
+            }
+
+            // Multi-location with only ?
+            if (cfg.getBundleLocation().equals("?")) {
+                return cfg;
+            }
+
+            // Multi-location specifying the pid
+            if (cfg.getBundleLocation().startsWith("?")) {
+                String sn = cfg.getBundleLocation().substring(1); // Remove ?
+                if (sn.equals(pid)) {
+                    return cfg;
+                }
+            }
+
+            // configuration belongs to another bundle, cannot be used here
+            m_logger.log(Log.ERROR, "Cannot use configuration pid=" + pid + " for bundle "
+                    + bundleLocation + " because it belongs to bundle " + cfg.getBundleLocation());
+        } catch (IOException ioe) {
+            m_logger.log(Log.WARNING, "Failed reading configuration for pid=" + pid, ioe);
+        }
+
+        return null;
+    }
+
+    public List<Configuration> findFactoryConfiguration(final ConfigurationAdmin admin, final IPojoFactory factory) {
+        final String filter = "(service.factoryPid=" + factory.getFactoryName() + ")";
+        return findConfigurations(admin, filter);
+    }
+
+    public Configuration findSingletonConfiguration(final ConfigurationAdmin admin, final String pid) {
+        final String filter = "(service.pid=" + pid + ")";
+        List<Configuration> list = findConfigurations(admin, filter);
+        if (list.isEmpty()) {
+            return null;
+        } else {
+            return list.get(0);
+        }
+    }
+
+    private List<Configuration> findConfigurations(final ConfigurationAdmin admin, final String filter) {
+        List<Configuration> configurations = Collections.emptyList();
+        if (admin == null) {
+            return configurations;
+        }
+
+        try {
+            Configuration[] list = admin.listConfigurations(filter);
+            if (list == null) {
+                return configurations;
+            } else {
+                return Arrays.asList(list);
+            }
+        } catch (InvalidSyntaxException e) {
+            m_logger.log(Log.ERROR, "Invalid Configuration selection filter " + filter, e);
+        } catch (IOException e) {
+            m_logger.log(Log.ERROR, "Error when retrieving configurations for filter=" + filter, e);
+        }
+        return configurations;
+    }
+}

Added: felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/FactoryClassloader.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/FactoryClassloader.java?rev=1477027&view=auto
==============================================================================
--- felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/FactoryClassloader.java (added)
+++ felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/FactoryClassloader.java Mon Apr 29 12:59:52 2013
@@ -0,0 +1,88 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo;
+
+import java.net.URL;
+import java.security.ProtectionDomain;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * This class defines the classloader attached to a factory.
+ * This class loader is used to load the implementation (e.g. manipulated)
+ * class.
+ *
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ * @see ClassLoader
+ */
+class FactoryClassloader extends ClassLoader {
+
+    /**
+     * The map of defined classes [Name, Class Object].
+     */
+    private final Map<String, Class<?>> m_definedClasses = new HashMap<String, Class<?>>();
+    private ComponentFactory factory;
+
+    public FactoryClassloader(ComponentFactory factory) {
+        this.factory = factory;
+    }
+
+    /**
+     * The defineClass method.
+     *
+     * @param name   name of the class
+     * @param clazz  the byte array of the class
+     * @param domain the protection domain
+     * @return the defined class.
+     */
+    public Class<?> defineClass(String name, byte[] clazz, ProtectionDomain domain) {
+        if (m_definedClasses.containsKey(name)) {
+            return m_definedClasses.get(name);
+        }
+        Class clas = super.defineClass(name, clazz, 0, clazz.length, domain);
+        m_definedClasses.put(name, clas);
+        return clas;
+    }
+
+    /**
+     * Returns the URL of the required resource.
+     *
+     * @param arg the name of the resource to find.
+     * @return the URL of the resource.
+     * @see ClassLoader#getResource(String)
+     */
+    public URL getResource(String arg) {
+        return factory.m_context.getBundle().getResource(arg);
+    }
+
+    /**
+     * Loads the given class.
+     *
+     * @param name    the name of the class
+     * @param resolve should be the class resolve now ?
+     * @return the loaded class object
+     * @throws ClassNotFoundException if the class to load is not found
+     * @see ClassLoader#loadClass(String, boolean)
+     * @see ClassLoader#loadClass(String, boolean)
+     */
+    protected synchronized Class loadClass(String name, boolean resolve) throws ClassNotFoundException {
+        return factory.m_context.getBundle().loadClass(name);
+    }
+}

Modified: felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/IPojoFactory.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/IPojoFactory.java?rev=1477027&r1=1477026&r2=1477027&view=diff
==============================================================================
--- felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/IPojoFactory.java (original)
+++ felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/IPojoFactory.java Mon Apr 29 12:59:52 2013
@@ -35,8 +35,10 @@ import java.util.*;
 /**
  * This class defines common mechanisms of iPOJO component factories
  * (i.e. component type).
- * This class implements both the Factory and ManagedServiceFactory
- * services.
+ *
+ * The factory is also tracking Factory configuration from the configuration admin to created / delete and update
+ * instances from this factory.
+ *
  * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
  */
 public abstract class IPojoFactory implements Factory, ManagedServiceFactory {
@@ -49,7 +51,7 @@ public abstract class IPojoFactory imple
      * The list of the managed instance name.
      * This list is shared by all factories and is used to assert name uniqueness.
      */
-    protected static final List INSTANCE_NAME = Collections.synchronizedList(new ArrayList());
+    protected static final List<String> INSTANCE_NAME = Collections.synchronizedList(new ArrayList<String>());
 
     /**
      * The component type description exposed by the {@link Factory} service.
@@ -60,7 +62,7 @@ public abstract class IPojoFactory imple
      * The list of the managed instance managers.
      * The key of this map is the name (i.e. instance names) of the created instance
      */
-    protected final Map m_componentInstances = new HashMap();
+    protected final Map<String, ComponentInstance> m_componentInstances = new HashMap<String, ComponentInstance>();
 
     /**
      * The component type metadata.
@@ -82,13 +84,13 @@ public abstract class IPojoFactory imple
     /**
      * The list of required handlers.
      */
-    protected List m_requiredHandlers = new ArrayList();
+    protected List<RequiredHandler> m_requiredHandlers = new ArrayList<RequiredHandler>();
 
     /**
      * The list of factory state listeners.
      * @see FactoryStateListener
      */
-    protected List m_listeners = new ArrayList(1);
+    protected List<FactoryStateListener> m_listeners = new ArrayList<FactoryStateListener>(1);
 
     /**
      * The logger for the factory.
@@ -202,7 +204,7 @@ public abstract class IPojoFactory imple
      * Each sub-type must override this method.
      * @return the required handler list
      */
-    public abstract List getRequiredHandlerList();
+    public abstract List<RequiredHandler> getRequiredHandlerList();
 
     /**
      * Creates an instance.
@@ -292,14 +294,15 @@ public abstract class IPojoFactory imple
         // Here we are sure to be valid until the end of the method.
         HandlerManager[] handlers = new HandlerManager[m_requiredHandlers.size()];
         for (int i = 0; i < handlers.length; i++) {
-            RequiredHandler req = (RequiredHandler) m_requiredHandlers.get(i);
-            handlers[i] = getHandler(req, serviceContext);
+            handlers[i] = getHandler(m_requiredHandlers.get(i), serviceContext);
         }
 
         try {
             ComponentInstance instance = createInstance(configuration, context, handlers);
             m_componentInstances.put(name, instance);
             m_logger.log(Logger.INFO, "Instance " + name + " from factory " + m_factoryName + " created");
+            // Register the instance on the ConfigurationTracker to be updated if needed.
+            ConfigurationTracker.get().instanceCreated(this, instance);
             return instance;
         } catch (ConfigurationException e) {
             INSTANCE_NAME.remove(name);
@@ -361,10 +364,9 @@ public abstract class IPojoFactory imple
      * @return the list of missing handlers.
      * @see org.apache.felix.ipojo.Factory#getMissingHandlers()
      */
-    public List getMissingHandlers() {
-        List list = new ArrayList();
-        for (int i = 0; i < m_requiredHandlers.size(); i++) {
-            RequiredHandler req = (RequiredHandler) m_requiredHandlers.get(i);
+    public List<String> getMissingHandlers() {
+        List<String> list = new ArrayList<String>();
+        for (RequiredHandler req : m_requiredHandlers) {
             if (req.getReference() == null) {
                 list.add(req.getFullName());
             }
@@ -389,10 +391,9 @@ public abstract class IPojoFactory imple
      * @return the list of required handlers.
      * @see org.apache.felix.ipojo.Factory#getRequiredHandlers()
      */
-    public synchronized List getRequiredHandlers() {
-        List list = new ArrayList();
-        for (int i = 0; i < m_requiredHandlers.size(); i++) {
-            RequiredHandler req = (RequiredHandler) m_requiredHandlers.get(i);
+    public synchronized List<String> getRequiredHandlers() {
+        List<String> list = new ArrayList<String>();
+        for (RequiredHandler req : m_requiredHandlers) {
             list.add(req.getFullName());
         }
         return list;
@@ -409,6 +410,17 @@ public abstract class IPojoFactory imple
     }
 
     /**
+     * Gets a component instance created by the current factory.
+     * @param name the instance name
+     * @return the component instance, {@literal null} if not found
+     */
+    public ComponentInstance getInstanceByName(String name) {
+        synchronized (this) {
+            return m_componentInstances.get(name);
+        }
+    }
+
+    /**
      * Checks if the configuration is acceptable.
      * @param conf the configuration to test.
      * @return <code>true</code> if the configuration is acceptable.
@@ -435,7 +447,8 @@ public abstract class IPojoFactory imple
      * @throws UnacceptableConfiguration if the configuration is unacceptable.
      * @throws MissingHandlerException if an handler is missing.
      */
-    public void checkAcceptability(Dictionary conf) throws UnacceptableConfiguration, MissingHandlerException {
+    public void checkAcceptability(Dictionary<String, ?> conf) throws UnacceptableConfiguration,
+            MissingHandlerException {
         PropertyDescription[] props;
         synchronized (this) {
             if (m_state == Factory.INVALID) {
@@ -447,14 +460,15 @@ public abstract class IPojoFactory imple
 
         // Check that the configuration does not override immutable properties.
 
-        for (int i = 0; i < props.length; i++) {
+        for (PropertyDescription prop : props) {
             // Is the property immutable
-            if (props[i].isImmutable() && conf.get(props[i].getName()) != null) {
-                throw new UnacceptableConfiguration("The property " + props[i] + " cannot be overide : immutable property"); // The instance configuration tries to override an immutable property.
+            if (prop.isImmutable() && conf.get(prop.getName()) != null) {
+                throw new UnacceptableConfiguration("The property " + prop + " cannot be overridden : immutable " +
+                        "property"); // The instance configuration tries to override an immutable property.
             }
             // Is the property required ?
-            if (props[i].isMandatory() && props[i].getValue() == null && conf.get(props[i].getName()) == null) {
-                throw new UnacceptableConfiguration("The mandatory property " + props[i].getName() + " is missing"); // The property must be set.
+            if (prop.isMandatory() && prop.getValue() == null && conf.get(prop.getName()) == null) {
+                throw new UnacceptableConfiguration("The mandatory property " + prop.getName() + " is missing"); // The property must be set.
             }
         }
     }
@@ -480,7 +494,7 @@ public abstract class IPojoFactory imple
             name = (String) properties.get("name");
         }
 
-        ComponentInstance instance = (ComponentInstance) m_componentInstances.get(name);
+        ComponentInstance instance = m_componentInstances.get(name);
         if (instance == null) { // The instance does not exists.
             return;
         }
@@ -520,13 +534,16 @@ public abstract class IPojoFactory imple
             m_sr.unregister();
             m_sr = null;
         }
+
+        ConfigurationTracker.get().unregisterFactory(this);
+
         stopping(); // Method called when holding the lock.
         int oldState = m_state; // Create a variable to store the old state. Using a variable is important as
                                 // after the next instruction, the getState() method must return INVALID.
         m_state = INVALID; // Set here to avoid to create instances during the stops.
 
-        Set col = m_componentInstances.keySet();
-        Iterator it = col.iterator();
+        Set<String> col = m_componentInstances.keySet();
+        Iterator<String> it = col.iterator();
         instances = new ComponentInstance[col.size()]; // Stack confinement
         int index = 0;
         while (it.hasNext()) {
@@ -535,23 +552,23 @@ public abstract class IPojoFactory imple
         }
 
         if (oldState == VALID) { // Check if the old state was valid.
-            for (int i = 0; i < m_listeners.size(); i++) {
-                ((FactoryStateListener) m_listeners.get(i)).stateChanged(this, INVALID);
+            for (FactoryStateListener listener : m_listeners) {
+                listener.stateChanged(this, INVALID);
             }
         }
 
         // Dispose created instances.
-        for (int i = 0; i < instances.length; i++) {
-            ComponentInstance instance = instances[i];
+        for (ComponentInstance instance : instances) {
             if (instance.getState() != ComponentInstance.DISPOSED) {
                 instance.dispose();
             }
         }
 
         // Release each handler
-        for (int i = 0; i < m_requiredHandlers.size(); i++) {
-            ((RequiredHandler) m_requiredHandlers.get(i)).unRef();
+        for (RequiredHandler req : m_requiredHandlers) {
+            req.unRef();
         }
+
         m_described = false;
         m_componentDesc = null;
         m_componentInstances.clear();
@@ -601,13 +618,17 @@ public abstract class IPojoFactory imple
         if (m_isPublic) {
             // Exposition of the factory service
             if (m_componentDesc == null) {
-                System.out.println("Description of " + m_factoryName + " " + m_componentDesc);
+                m_logger.log(Logger.ERROR, "Unexpected state, the description of " + m_factoryName + "  is null");
+                return;
             }
             BundleContext bc = SecurityHelper.selectContextToRegisterServices(m_componentDesc.getFactoryInterfacesToPublish(),
                     m_context, getIPOJOBundleContext());
             m_sr =
                     bc.registerService(m_componentDesc.getFactoryInterfacesToPublish(), this, m_componentDesc
                             .getPropertiesToPublish());
+
+            // Register the factory on the ConfigurationTracker
+            ConfigurationTracker.get().registerFactory(this);
         }
 
         m_logger.log(Logger.INFO, "Factory " + m_factoryName + " started");
@@ -637,11 +658,12 @@ public abstract class IPojoFactory imple
      * @param properties the new configuration of the instance
      * @throws org.osgi.service.cm.ConfigurationException if the configuration is not consistent for this component type
      * @see org.osgi.service.cm.ManagedServiceFactory#updated(java.lang.String, java.util.Dictionary)
+     * TODO this method should disappear.
      */
     public void updated(String name, Dictionary properties) throws org.osgi.service.cm.ConfigurationException {
         ComponentInstance instance;
         synchronized (this) {
-            instance = (ComponentInstance) m_componentInstances.get(name);
+            instance = m_componentInstances.get(name);
         }
 
         if (instance == null) {
@@ -677,6 +699,7 @@ public abstract class IPojoFactory imple
      * Deletes an instance.
      * @param name the name of the instance to delete
      * @see org.osgi.service.cm.ManagedServiceFactory#deleted(java.lang.String)
+     * todo this method should disappear.
      */
     public synchronized void deleted(String name) {
         INSTANCE_NAME.remove(name);
@@ -707,9 +730,7 @@ public abstract class IPojoFactory imple
      * This method is called with the lock.
      */
     protected void computeDescription() {
-        for (int i = 0; i < m_requiredHandlers.size(); i++) {
-            RequiredHandler req = (RequiredHandler) m_requiredHandlers.get(i);
-
+        for (RequiredHandler req : m_requiredHandlers) {
             if (getHandler(req, null) == null) {
                 // TODO this does not really looks good.
                 m_logger.log(Logger.ERROR, "Cannot extract handler object from " + m_factoryName + " " + req
@@ -720,7 +741,7 @@ public abstract class IPojoFactory imple
                     handler.setFactory(this);
                     handler.initializeComponentFactory(m_componentDesc, m_componentMetadata);
                     ((Pojo) handler).getComponentInstance().dispose();
-                } catch (org.apache.felix.ipojo.ConfigurationException e) {
+                } catch (ConfigurationException e) {
                     ((Pojo) handler).getComponentInstance().dispose();
                     m_logger.log(Logger.ERROR, e.getMessage());
                     stop();
@@ -739,8 +760,7 @@ public abstract class IPojoFactory imple
      */
     protected void computeFactoryState() {
         boolean isValid = true;
-        for (int i = 0; i < m_requiredHandlers.size(); i++) {
-            RequiredHandler req = (RequiredHandler) m_requiredHandlers.get(i);
+        for (RequiredHandler req : m_requiredHandlers) {
             if (req.getReference() == null) {
                 isValid = false;
                 break;
@@ -760,25 +780,24 @@ public abstract class IPojoFactory imple
                 if (m_sr != null) {
                     m_sr.setProperties(m_componentDesc.getPropertiesToPublish());
                 }
-                for (int i = 0; i < m_listeners.size(); i++) {
-                    ((FactoryStateListener) m_listeners.get(i)).stateChanged(this, VALID);
+                for (FactoryStateListener listener : m_listeners) {
+                    listener.stateChanged(this, VALID);
                 }
-                return;
             }
         } else {
             if (m_state == VALID) {
                 m_state = INVALID;
 
                 // Notify listeners.
-                for (int i = 0; i < m_listeners.size(); i++) {
-                    ((FactoryStateListener) m_listeners.get(i)).stateChanged(this, INVALID);
+                for (FactoryStateListener listener : m_listeners) {
+                    listener.stateChanged(this, INVALID);
                 }
 
                 // Dispose created instances.
-                Set col = m_componentInstances.keySet();
-                String[] keys = (String[]) col.toArray(new String[col.size()]);
-                for (int i = 0; i < keys.length; i++) {
-                    ComponentInstance instance = (ComponentInstance) m_componentInstances.get(keys[i]);
+                // We must create a copy to avoid concurrent exceptions
+                Set<? extends String> keys = new HashSet<String>(m_componentInstances.keySet());
+                for (String key : keys) {
+                    ComponentInstance instance = m_componentInstances.get(key);
                     if (instance.getState() != ComponentInstance.DISPOSED) {
                         instance.dispose();
                     }
@@ -790,8 +809,6 @@ public abstract class IPojoFactory imple
                 if (m_sr != null) {
                     m_sr.setProperties(m_componentDesc.getPropertiesToPublish());
                 }
-
-                return;
             }
         }
     }
@@ -803,7 +820,7 @@ public abstract class IPojoFactory imple
      * @param ref the service reference.
      * @return <code>true</code> if the service reference can fulfill the handler requirement
      */
-    protected boolean match(RequiredHandler req, ServiceReference ref) {
+    protected boolean match(RequiredHandler req, ServiceReference<? extends Object> ref) {
         String name = (String) ref.getProperty(Handler.HANDLER_NAME_PROPERTY);
         String namespace = (String) ref.getProperty(Handler.HANDLER_NAMESPACE_PROPERTY);
         if (HandlerFactory.IPOJO_NAMESPACE.equals(namespace)) {
@@ -927,7 +944,7 @@ public abstract class IPojoFactory imple
                 return null;
             }
             if (m_factory == null) {
-                m_factory = (HandlerFactory) m_context.getService(getReference());
+                m_factory = m_context.getService(getReference());
             }
             return m_factory;
         }
@@ -952,7 +969,7 @@ public abstract class IPojoFactory imple
             return m_namespace;
         }
 
-        public ServiceReference getReference() {
+        public ServiceReference<? extends HandlerFactory> getReference() {
             return m_reference;
         }
 

Added: felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/PrimitiveTypeDescription.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/PrimitiveTypeDescription.java?rev=1477027&view=auto
==============================================================================
--- felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/PrimitiveTypeDescription.java (added)
+++ felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/PrimitiveTypeDescription.java Mon Apr 29 12:59:52 2013
@@ -0,0 +1,228 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo;
+
+import org.apache.felix.ipojo.architecture.ComponentTypeDescription;
+import org.apache.felix.ipojo.metadata.Attribute;
+import org.apache.felix.ipojo.metadata.Element;
+import org.apache.felix.ipojo.parser.PojoMetadata;
+import org.osgi.framework.Bundle;
+
+import java.util.Dictionary;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * This class defines the description of primitive (non-composite) component
+ * types. An instance of this class will be returned when invoking the
+ * {@link org.apache.felix.ipojo.ComponentFactory#getComponentDescription()} method.
+ *
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+final class PrimitiveTypeDescription extends ComponentTypeDescription {
+
+    /**
+     * Set to keep component's all super-class class-names.
+     */
+    private Set<String> m_superClasses = new HashSet<String>();
+
+    /**
+     * Set to keep component's all interface class-names.
+     */
+    private Set<String> m_interfaces = new HashSet<String>();
+
+    /**
+     * The described component factory.
+     */
+    private ComponentFactory m_factory;
+
+    /**
+     * Creates a PrimitiveTypeDescription object.
+     *
+     * @param factory the m_factory attached to this component type description.
+     */
+    public PrimitiveTypeDescription(ComponentFactory factory) {
+        super(factory);
+        this.m_factory = factory;
+
+        try {
+            // The inspection can be done only for primitive components
+            if (factory.getClassName() != null) {
+                // Read inherited classes and interfaces into given Sets.
+                new InheritanceInspector(factory.getPojoMetadata(), getBundleContext().getBundle()).
+                        computeInterfacesAndSuperClasses(m_interfaces, m_superClasses);
+            }
+        } catch (ClassNotFoundException e) {
+            m_interfaces.clear();
+            m_superClasses.clear();
+        }
+
+    }
+
+    /**
+     * Computes the properties to publish.
+     * The <code>component.class</code> property contains the implementation class name.
+     *
+     * @return the dictionary of properties to publish
+     * @see org.apache.felix.ipojo.architecture.ComponentTypeDescription#getPropertiesToPublish()
+     */
+    public Dictionary<String, Object> getPropertiesToPublish() {
+        Dictionary<String, Object> dict = super.getPropertiesToPublish();
+        if (m_factory.getClassName() != null) {
+            dict.put("component.class", m_factory.getClassName());
+        }
+        return dict;
+    }
+
+    /**
+     * Adds the "implementation-class" attribute to the type description.
+     *
+     * @return the component type description.
+     * @see org.apache.felix.ipojo.architecture.ComponentTypeDescription#getDescription()
+     */
+    public Element getDescription() {
+        Element elem = super.getDescription();
+        elem.addAttribute(new Attribute("Implementation-Class", m_factory.getClassName()));
+
+        /* Adding interfaces and super-classes of component into description */
+        Element inheritance = new Element("Inherited", "");
+
+        inheritance.addAttribute(new Attribute("Interfaces", m_interfaces.toString()));
+        inheritance.addAttribute(new Attribute("SuperClasses", m_superClasses.toString()));
+
+        elem.addElement(inheritance);
+
+        return elem;
+    }
+
+    /**
+     * This class is used to collect interfaces and super-classes of given component in specified Sets.
+     *
+     * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+     */
+    private final class InheritanceInspector {
+        /*
+            * PojoMetadata of target Component.
+            */
+        private PojoMetadata m_pojoMetadata;
+        /*
+            * Bundle exposing target component.
+            */
+        private Bundle m_bundle;
+
+
+        /**
+         * Creates a TypeCollector object
+         *
+         * @param pojoMetadata PojoMetadata describing Component.
+         * @param bundle       Bundle which has been exposed the intended Component.
+         */
+        public InheritanceInspector(PojoMetadata pojoMetadata, Bundle bundle) {
+            m_pojoMetadata = pojoMetadata;
+            m_bundle = bundle;
+        }
+
+        /**
+         * Collect interfaces implemented by the POJO into given Sets.
+         *
+         * @param interfaces : the set of implemented interfaces
+         * @param classes    : the set of extended classes
+         * @throws ClassNotFoundException : occurs when an interface cannot be loaded.
+         */
+        public void computeInterfacesAndSuperClasses(Set<String> interfaces, Set<String> classes) throws ClassNotFoundException {
+            String[] immediateInterfaces = m_pojoMetadata.getInterfaces();
+            String parentClass = m_pojoMetadata.getSuperClass();
+
+            // First iterate on found specification in manipulation metadata
+            for (String immediateInterface : immediateInterfaces) {
+                interfaces.add(immediateInterface);
+                // Iterate on interfaces implemented by the current interface
+                Class<?> clazz = m_bundle.loadClass(immediateInterface);
+                collectInterfaces(clazz, interfaces, m_bundle);
+            }
+
+            // Look for parent class.
+            if (parentClass != null) {
+                Class clazz = m_bundle.loadClass(parentClass);
+                collectInterfacesFromClass(clazz, interfaces, m_bundle);
+                classes.add(parentClass);
+                collectParentClassesFromClass(clazz, classes, m_bundle);
+            }
+
+            // Removing Object Class from the inherited classes list.
+            classes.remove(Object.class.getName());
+        }
+
+        /**
+         * Look for inherited interfaces.
+         *
+         * @param clazz  : interface name to explore (class object)
+         * @param acc    : set (accumulator)
+         * @param bundle : bundle
+         * @throws ClassNotFoundException : occurs when an interface cannot be loaded.
+         */
+        private void collectInterfaces(Class<?> clazz, Set<String> acc, Bundle bundle) throws ClassNotFoundException {
+            Class[] clazzes = clazz.getInterfaces();
+            for (Class clazze : clazzes) {
+                acc.add(clazze.getName());
+                collectInterfaces(clazze, acc, bundle);
+            }
+        }
+
+        /**
+         * Collect interfaces for the given class.
+         * This method explores super class to.
+         *
+         * @param clazz  : class object.
+         * @param acc    : set of implemented interface (accumulator)
+         * @param bundle : bundle.
+         * @throws ClassNotFoundException : occurs if an interface cannot be load.
+         */
+        private void collectInterfacesFromClass(Class<?> clazz, Set<String> acc,
+                                                Bundle bundle) throws ClassNotFoundException {
+            Class[] clazzes = clazz.getInterfaces();
+            for (Class clazze : clazzes) {
+                acc.add(clazze.getName());
+                collectInterfaces(clazze, acc, bundle);
+            }
+            // Iterate on parent classes
+            Class sup = clazz.getSuperclass();
+            if (sup != null) {
+                collectInterfacesFromClass(sup, acc, bundle);
+            }
+        }
+
+        /**
+         * Collect parent classes for the given class.
+         *
+         * @param clazz  : class object.
+         * @param acc    : set of extended classes (accumulator)
+         * @param bundle : bundle.
+         * @throws ClassNotFoundException : occurs if an interface cannot be load.
+         */
+        private void collectParentClassesFromClass(Class<?> clazz, Set<String> acc, Bundle bundle) throws ClassNotFoundException {
+            Class<?> parent = clazz.getSuperclass();
+            if (parent != null) {
+                acc.add(parent.getName());
+                collectParentClassesFromClass(parent, acc, bundle);
+            }
+        }
+    }
+}

Modified: felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/architecture/ComponentTypeDescription.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/architecture/ComponentTypeDescription.java?rev=1477027&r1=1477026&r2=1477027&view=diff
==============================================================================
--- felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/architecture/ComponentTypeDescription.java (original)
+++ felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/architecture/ComponentTypeDescription.java Mon Apr 29 12:59:52 2013
@@ -18,11 +18,6 @@
  */
 package org.apache.felix.ipojo.architecture;
 
-import java.util.Dictionary;
-import java.util.Enumeration;
-import java.util.Hashtable;
-import java.util.Properties;
-
 import org.apache.felix.ipojo.Factory;
 import org.apache.felix.ipojo.IPojoFactory;
 import org.apache.felix.ipojo.metadata.Attribute;
@@ -31,34 +26,37 @@ import org.osgi.framework.BundleContext;
 import org.osgi.framework.Constants;
 import org.osgi.service.cm.ManagedServiceFactory;
 
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.Hashtable;
+
 /**
  * Component Type description.
+ *
  * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
  */
 public class ComponentTypeDescription {
 
     /**
+     * Represented factory.
+     */
+    private final IPojoFactory m_factory;
+    /**
      * Provided service by the component type.
      */
     private String[] m_providedServiceSpecification = new String[0];
-
     /**
      * Configuration Properties accepted by the component type.
      */
     private PropertyDescription[] m_properties = new PropertyDescription[0];
-    
     /*
      * Used by custom handlers to keep and retrieve custom info.
      */
     private Dictionary m_handlerInfoSlot = new Hashtable();
 
     /**
-     * Represented factory.
-     */
-    private final IPojoFactory m_factory;
-
-    /**
      * Constructor.
+     *
      * @param factory : represented factory.
      */
     public ComponentTypeDescription(IPojoFactory factory) {
@@ -67,6 +65,7 @@ public class ComponentTypeDescription {
 
     /**
      * Gets the attached factory.
+     *
      * @return the factory
      */
     public IPojoFactory getFactory() {
@@ -75,6 +74,7 @@ public class ComponentTypeDescription {
 
     /**
      * Gets a printable form of the current component type description.
+     *
      * @return printable form of the component type description
      * @see java.lang.Object#toString()
      */
@@ -84,6 +84,7 @@ public class ComponentTypeDescription {
 
     /**
      * Gets the implementation class of this component type.
+     *
      * @return the component type implementation class name.
      * @deprecated
      */
@@ -93,8 +94,9 @@ public class ComponentTypeDescription {
 
     /**
      * Gets the component type version.
+     *
      * @return the component type version or
-     * <code>null</code> if not set.
+     *         <code>null</code> if not set.
      */
     public String getVersion() {
         return m_factory.getVersion();
@@ -102,6 +104,7 @@ public class ComponentTypeDescription {
 
     /**
      * Gets component-type properties.
+     *
      * @return the list of configuration properties accepted by the component type type.
      */
     public PropertyDescription[] getProperties() {
@@ -110,7 +113,8 @@ public class ComponentTypeDescription {
 
     /**
      * Adds a String property in the component type.
-     * @param name : property name.
+     *
+     * @param name  : property name.
      * @param value : property value.
      */
     public void addProperty(String name, String value) {
@@ -119,8 +123,9 @@ public class ComponentTypeDescription {
 
     /**
      * Adds a String property in the component type.
-     * @param name : property name.
-     * @param value : property value.
+     *
+     * @param name      : property name.
+     * @param value     : property value.
      * @param immutable : the property is immutable.
      */
     public void addProperty(String name, String value, boolean immutable) {
@@ -130,6 +135,7 @@ public class ComponentTypeDescription {
 
     /**
      * Adds a configuration properties to the component type.
+     *
      * @param pd : the property to add
      */
     public void addProperty(PropertyDescription pd) { //NOPMD remove the instance name of the 'name' property.
@@ -138,7 +144,9 @@ public class ComponentTypeDescription {
         // Check if the property is not already in the array
         for (int i = 0; i < m_properties.length; i++) {
             PropertyDescription desc = m_properties[i];
-            if (desc.getName().equals(name)) { return; }
+            if (desc.getName().equals(name)) {
+                return;
+            }
         }
 
         PropertyDescription[] newProps = new PropertyDescription[m_properties.length + 1];
@@ -146,35 +154,32 @@ public class ComponentTypeDescription {
         newProps[m_properties.length] = pd;
         m_properties = newProps;
     }
-    
+
     /**
      * Adds the HandlerInfo for specified handler.
-     * @param handlerNs Handler's namespace
+     *
+     * @param handlerNs   Handler's namespace
      * @param handlerName Handler's name
-     * @param info HandlerInfo associated with the given custom handler.
+     * @param info        HandlerInfo associated with the given custom handler.
      */
-    public void setHandlerInfo(String handlerNs, String handlerName, CustomHandlerInfo info)
-    {
-    	String fullHandlerName = handlerNs + ":" + handlerName;
-    	
-    	if(info == null)
-    	{
-    		m_handlerInfoSlot.remove(fullHandlerName);
-    	}
-    	else
-    	{
-    		m_handlerInfoSlot.put(fullHandlerName, info);
-    	}
-    }
-    
-    public CustomHandlerInfo getHandlerInfo(String handlerNs, String handlerName)
-    {
-    	String fullHandlerName = handlerNs + ":" + handlerName;    	
-    	return (CustomHandlerInfo)m_handlerInfoSlot.get(fullHandlerName);
+    public void setHandlerInfo(String handlerNs, String handlerName, CustomHandlerInfo info) {
+        String fullHandlerName = handlerNs + ":" + handlerName;
+
+        if (info == null) {
+            m_handlerInfoSlot.remove(fullHandlerName);
+        } else {
+            m_handlerInfoSlot.put(fullHandlerName, info);
+        }
+    }
+
+    public CustomHandlerInfo getHandlerInfo(String handlerNs, String handlerName) {
+        String fullHandlerName = handlerNs + ":" + handlerName;
+        return (CustomHandlerInfo) m_handlerInfoSlot.get(fullHandlerName);
     }
 
     /**
      * Gets the list of provided service offered by instances of this type.
+     *
      * @return the list of the provided service.
      */
     public String[] getprovidedServiceSpecification() {
@@ -183,6 +188,7 @@ public class ComponentTypeDescription {
 
     /**
      * Adds a provided service to the component type.
+     *
      * @param serviceSpecification : the provided service to add (interface name)
      */
     public void addProvidedServiceSpecification(String serviceSpecification) {
@@ -194,6 +200,7 @@ public class ComponentTypeDescription {
 
     /**
      * Returns the component-type name.
+     *
      * @return the name of this component type
      */
     public String getName() {
@@ -203,10 +210,11 @@ public class ComponentTypeDescription {
     /**
      * Computes the default service properties to publish :
      * factory.name, service.pid, component.providedServiceSpecification, component.properties, component.description, factory.State.
+     *
      * @return : the dictionary of properties to publish.
      */
-    public Dictionary getPropertiesToPublish() {
-        Properties props = new Properties();
+    public Dictionary<String, Object> getPropertiesToPublish() {
+        Hashtable<String, Object> props = new Hashtable<String, Object>();
 
         props.put("factory.name", m_factory.getName());
         props.put(Constants.SERVICE_PID, m_factory.getName()); // Service PID is required for the integration in the configuration admin.
@@ -222,14 +230,14 @@ public class ComponentTypeDescription {
         props.put("component.description", this);
 
         // add every immutable property
-        for (int i = 0; i < m_properties.length; i++) {
-            if (m_properties[i].isImmutable() && m_properties[i].getValue() != null) {
-                props.put(m_properties[i].getName(), m_properties[i].getObjectValue(m_factory.getBundleContext()));
+        for (PropertyDescription m_property : m_properties) {
+            if (m_property.isImmutable() && m_property.getValue() != null) {
+                props.put(m_property.getName(), m_property.getObjectValue(m_factory.getBundleContext()));
             }
         }
 
         // Add factory state
-        props.put("factory.state", new Integer(m_factory.getState()));
+        props.put("factory.state", m_factory.getState());
 
         return props;
 
@@ -238,14 +246,16 @@ public class ComponentTypeDescription {
     /**
      * Gets the interfaces published by the factory.
      * By default publish both {@link Factory} and {@link ManagedServiceFactory}.
+     *
      * @return : the list of interface published by the factory.
      */
     public String[] getFactoryInterfacesToPublish() {
-        return new String[] {Factory.class.getName(), ManagedServiceFactory.class.getName()};
+        return new String[]{Factory.class.getName()};
     }
 
     /**
      * Gets the component type description.
+     *
      * @return : the description
      */
     public Element getDescription() {
@@ -253,8 +263,8 @@ public class ComponentTypeDescription {
 
         desc.addAttribute(new Attribute("name", m_factory.getName()));
         desc.addAttribute(
-                          new Attribute("bundle",
-                                          Long.toString(m_factory.getBundleContext().getBundle().getBundleId())));
+                new Attribute("bundle",
+                        Long.toString(m_factory.getBundleContext().getBundle().getBundleId())));
 
         String state = "valid";
         if (m_factory.getState() == Factory.INVALID) {
@@ -280,24 +290,22 @@ public class ComponentTypeDescription {
             Element prop = new Element("property", "");
             prop.addAttribute(new Attribute("name", m_properties[i].getName()));
             prop.addAttribute(new Attribute("type", m_properties[i].getType()));
-            if (m_properties[i].isMandatory()  && m_properties[i].getValue() == null) {
+            if (m_properties[i].isMandatory() && m_properties[i].getValue() == null) {
                 prop.addAttribute(new Attribute("value", "REQUIRED"));
             } else {
                 prop.addAttribute(new Attribute("value", m_properties[i].getValue()));
             }
             desc.addElement(prop);
         }
-        
-        if(m_handlerInfoSlot.size() > 0)
-        {        	
-        	Enumeration keys = m_handlerInfoSlot.keys();
-            
-            while(keys.hasMoreElements())
-            {
-            	String fullHandlerName = (String) keys.nextElement();
-            	
-            	CustomHandlerInfo handlerInfo = (CustomHandlerInfo)m_handlerInfoSlot.get(fullHandlerName);
-            	desc.addElement( handlerInfo.getDescription() );
+
+        if (m_handlerInfoSlot.size() > 0) {
+            Enumeration keys = m_handlerInfoSlot.keys();
+
+            while (keys.hasMoreElements()) {
+                String fullHandlerName = (String) keys.nextElement();
+
+                CustomHandlerInfo handlerInfo = (CustomHandlerInfo) m_handlerInfoSlot.get(fullHandlerName);
+                desc.addElement(handlerInfo.getDescription());
             }
         }
 

Modified: felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/configuration/Instance.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/configuration/Instance.java?rev=1477027&r1=1477026&r2=1477027&view=diff
==============================================================================
--- felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/configuration/Instance.java (original)
+++ felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/configuration/Instance.java Mon Apr 29 12:59:52 2013
@@ -19,7 +19,6 @@
 
 package org.apache.felix.ipojo.configuration;
 
-import org.apache.felix.ipojo.ComponentInstance;
 import org.apache.felix.ipojo.Factory;
 
 import java.util.*;
@@ -49,6 +48,10 @@ public class Instance {
         return new Pair<K, T>(k, v);
     }
 
+    public static <K, T> Pair<K, T> entry(K k, T v) {
+        return new Pair<K, T>(k, v);
+    }
+
     public String factory() {
         return factory;
     }

Modified: felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/Extender.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/Extender.java?rev=1477027&r1=1477026&r2=1477027&view=diff
==============================================================================
--- felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/Extender.java (original)
+++ felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/Extender.java Mon Apr 29 12:59:52 2013
@@ -19,6 +19,7 @@
 
 package org.apache.felix.ipojo.extender.internal;
 
+import org.apache.felix.ipojo.ConfigurationTracker;
 import org.apache.felix.ipojo.EventDispatcher;
 import org.apache.felix.ipojo.extender.internal.linker.DeclarationLinker;
 import org.apache.felix.ipojo.extender.internal.processor.*;
@@ -115,6 +116,9 @@ public class Extender implements BundleA
             EventDispatcher.create(context);
         }
 
+        // Initialize ConfigurationTracker
+        ConfigurationTracker.initialize();
+
         BundleProcessor extensionBundleProcessor = new ExtensionBundleProcessor(m_logger);
         BundleProcessor componentsProcessor = new ComponentsBundleProcessor(m_logger);
         BundleProcessor configurationProcessor = new ConfigurationProcessor(m_logger);
@@ -169,6 +173,9 @@ public class Extender implements BundleA
     public void stop(BundleContext context) throws Exception {
         context.removeBundleListener(this);
 
+        //Shutdown ConfigurationTracker
+        ConfigurationTracker.shutdown();
+
         m_processor.stop();
 
         if (DISPATCHER_ENABLED) {

Added: felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/util/ServiceLocator.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/util/ServiceLocator.java?rev=1477027&view=auto
==============================================================================
--- felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/util/ServiceLocator.java (added)
+++ felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/util/ServiceLocator.java Mon Apr 29 12:59:52 2013
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.ipojo.util;
+
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+
+/**
+ * A simple utility class to retrive services from the service registry.
+ */
+public class ServiceLocator<T> {
+
+    private final BundleContext m_context;
+    private final Class<T> m_clazz;
+
+    private ServiceReference<T> m_reference;
+    private T m_service;
+
+    public ServiceLocator(Class<T> clazz, BundleContext context) {
+        m_clazz = clazz;
+        m_context = context;
+    }
+
+    public synchronized T get() {
+         if (m_service != null) {
+                return m_service;
+         }
+
+        m_reference = m_context.getServiceReference(m_clazz);
+        if (m_reference == null) {
+            return null;
+        }
+        m_service = m_context.getService(m_reference);
+
+        return m_service;
+    }
+
+    public synchronized void unget() {
+        m_service = null;
+        if (m_reference != null) {
+            m_context.ungetService(m_reference);
+            m_reference = null;
+        }
+    }
+}