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 2007/12/21 20:28:13 UTC

svn commit: r606280 [4/6] - in /felix/sandbox/clement/ipojo: composite/ composite/src/ composite/src/main/ composite/src/main/java/ composite/src/main/java/org/ composite/src/main/java/org/apache/ composite/src/main/java/org/apache/felix/ composite/src...

Modified: felix/sandbox/clement/ipojo/core/pom.xml
URL: http://svn.apache.org/viewvc/felix/sandbox/clement/ipojo/core/pom.xml?rev=606280&r1=606279&r2=606280&view=diff
==============================================================================
--- felix/sandbox/clement/ipojo/core/pom.xml (original)
+++ felix/sandbox/clement/ipojo/core/pom.xml Fri Dec 21 11:28:07 2007
@@ -45,6 +45,7 @@
             <Bundle-Vendor>Clement ESCOFFIER</Bundle-Vendor>
             <Bundle-Description> iPOJO </Bundle-Description>
             <Bundle-Activator>org.apache.felix.ipojo.Extender</Bundle-Activator>
+            <IPOJO-Extension>component:org.apache.felix.ipojo.ComponentFactory, handler:org.apache.felix.ipojo.HandlerFactory</IPOJO-Extension>
             <Import-Package>
               org.osgi.framework, 
               org.osgi.service.cm,
@@ -52,17 +53,11 @@
 			  !org.objectweb.asm*
             </Import-Package>
             <Private-Package>
-            	org.apache.felix.ipojo.manipulation,
-    			org.apache.felix.ipojo.composite.architecture,
-    			org.apache.felix.ipojo.composite.service*,
-    			org.apache.felix.ipojo.composite.instance,
     			org.apache.felix.ipojo.handlers.architecture,
     			org.apache.felix.ipojo.handlers.configuration,
-    			org.apache.felix.ipojo.handlers.dependency.nullable,
               	org.apache.felix.ipojo.handlers.lifecycle.callback,
               	org.apache.felix.ipojo.handlers.lifecycle.controller,
-              	!org.objectweb.asm.xml*,
-              	org.objectweb.asm*;-split-package:=merge-first
+              	org.objectweb.asm
             </Private-Package>
             <Export-Package>
               org.apache.felix.ipojo; version="0.7.6", 
@@ -72,7 +67,7 @@
               org.apache.felix.ipojo.util; version="0.7.6",
               org.apache.felix.ipojo.handlers.dependency; version="0.7.6",
               org.apache.felix.ipojo.handlers.providedservice; version="0.7.6", 
-              org.apache.felix.ipojo.composite; version="0.7.6",
+              org.apache.felix.ipojo.context; version="0.7.6",
               org.osgi.service.cm,
               org.osgi.service.log
             </Export-Package>

Added: felix/sandbox/clement/ipojo/core/src/main/java/org/apache/felix/ipojo/AbstractFactory.java
URL: http://svn.apache.org/viewvc/felix/sandbox/clement/ipojo/core/src/main/java/org/apache/felix/ipojo/AbstractFactory.java?rev=606280&view=auto
==============================================================================
--- felix/sandbox/clement/ipojo/core/src/main/java/org/apache/felix/ipojo/AbstractFactory.java (added)
+++ felix/sandbox/clement/ipojo/core/src/main/java/org/apache/felix/ipojo/AbstractFactory.java Fri Dec 21 11:28:07 2007
@@ -0,0 +1,807 @@
+/* 
+ * 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.util.ArrayList;
+import java.util.Dictionary;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+
+import org.apache.felix.ipojo.architecture.ComponentTypeDescription;
+import org.apache.felix.ipojo.metadata.Element;
+import org.apache.felix.ipojo.util.Logger;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.cm.ManagedServiceFactory;
+
+/**
+ * This class abstracts iPOJO factories.
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public abstract class AbstractFactory implements Factory, ManagedServiceFactory  {
+    
+    /**
+     * List of the managed instance name. This list is shared by all factories.
+     */
+    protected static List m_instancesName = new ArrayList();
+    
+    /**
+     * Component-Type description exposed by the factory service.
+     */
+    protected ComponentTypeDescription m_componentDesc;
+    
+    /**
+     * List of the managed instance managers. The key of this map is the
+     * name (i.e. instance names) of the created instance
+     */
+    protected Map m_componentInstances = new HashMap();
+    
+    /**
+     * Component Type provided by this factory.
+     */
+    protected Element m_componentMetadata;
+    
+    /**
+     * The bundle context reference.
+     */
+    protected BundleContext m_context = null;    
+    
+    /**
+     * Factory Name. Could be the component class name if the
+     * factory name is not set.
+     */
+    protected String m_factoryName;
+
+    /**
+     * List of required handler.
+     */
+    protected List m_requiredHandlers = new ArrayList();
+
+    /**
+     * List of listeners.
+     */
+    protected List m_listeners = new ArrayList(2);
+    
+    /**
+     * Logger for the factory (and all component instance).
+     */
+    protected Logger m_logger;
+    
+    /**
+     * Is the factory public (expose as a service). 
+     */
+    protected boolean m_isPublic;
+    
+    /**
+     * Service Registration of this factory (Factory & ManagedServiceFactory).
+     */
+    protected ServiceRegistration m_sr;
+    
+    /**
+     * Factory state.
+     */
+    protected int m_state = Factory.INVALID;
+    
+    /**
+     * Index used to generate instance name if not set.
+     */
+    private long m_index = 0;
+    
+    /**
+     * Flag indicating if this factory has already a computed description or not.
+     */
+    private boolean m_described;
+    
+    /**
+     * Constructor.
+     * @param bc : bundle context of the bundle containing the factory.
+     * @param cm : description of the component type.
+     */
+    public AbstractFactory(BundleContext bc, Element cm) {
+        m_context = bc;
+        m_componentMetadata = cm;
+        m_factoryName = getFactoryName();
+        String fac = cm.getAttribute("factory");
+        m_isPublic = fac == null || ! fac.equalsIgnoreCase("false");
+        m_logger = new Logger(m_context, m_factoryName, Logger.WARNING);
+        m_requiredHandlers = getRequiredHandlerList();
+    }
+    
+    public ComponentTypeDescription getComponentTypeDescription() {
+        return new ComponentTypeDescription(this);
+    }
+
+    /**
+     * Add a factory listener.
+     * @param l : the factory listener to add.
+     * @see org.apache.felix.ipojo.Factory#addFactoryStateListener(org.apache.felix.ipojo.FactoryStateListener)
+     */
+    public void addFactoryStateListener(FactoryStateListener l) {
+        synchronized (m_listeners) {
+            m_listeners.add(l);
+        }
+    }
+    
+    /**
+     * Get the logger used by instances of he current factory.
+     * @return the factory logger.
+     */
+    public Logger getLogger() {
+        return m_logger;
+    }
+    
+    /**
+     * Compute the factory name.
+     * @return the factory name.
+     */
+    public abstract String getFactoryName();
+    
+    /**
+     * Compute the required handler list.
+     * @return the required handler list
+     */
+    public abstract List getRequiredHandlerList();
+    
+    /**
+     * Create an instance.
+     * @param configuration : instance configuration
+     * @param context : ipojo context to use
+     * @param handlers : handler array to use
+     * @return the new component instance.
+     * @throws ConfigurationException : occurs when the instance creation failed during the configuration process.
+     */
+    public abstract ComponentInstance createInstance(Dictionary configuration, IPojoContext context, HandlerManager[] handlers) throws ConfigurationException;
+
+
+    /**
+     * Create an instance. The given configuration needs to contain the 'name'
+     * property.
+     * @param configuration : configuration of the created instance.
+     * @return the created component instance.
+     * @throws UnacceptableConfiguration : occurs if the given configuration is
+     * not consistent with the component type of this factory.
+     * @throws MissingHandlerException  : occurs if an handler is unavailable when the instance is created.
+     * @throws org.apache.felix.ipojo.ConfigurationException : occurs when the instance or type configuration are not correct.
+     * @see org.apache.felix.ipojo.Factory#createComponentInstance(java.util.Dictionary)
+     */
+    public ComponentInstance createComponentInstance(Dictionary configuration) throws UnacceptableConfiguration, MissingHandlerException, ConfigurationException {
+        return createComponentInstance(configuration, null);
+    }
+    
+    /**
+     * Create an instance. The given configuration needs to contain the 'name'
+     * property.
+     * @param configuration : configuration of the created instance.
+     * @param serviceContext : the service context to push for this instance.
+     * @return the created component instance.
+     * @throws UnacceptableConfiguration : occurs if the given configuration is
+     * not consistent with the component type of this factory.
+     * @throws MissingHandlerException : occurs when an handler is unavailable when creating the instance.
+     * @throws org.apache.felix.ipojo.ConfigurationException : when the instance configuration failed.
+     * @see org.apache.felix.ipojo.Factory#createComponentInstance(java.util.Dictionary)
+     */
+    public ComponentInstance createComponentInstance(Dictionary configuration, ServiceContext serviceContext) throws UnacceptableConfiguration, MissingHandlerException, ConfigurationException {
+        if (configuration == null) {
+            configuration = new Properties();
+        }
+        
+        try {
+            checkAcceptability(configuration);
+        } catch (UnacceptableConfiguration e) {
+            m_logger.log(Logger.ERROR, "The configuration is not acceptable : " + e.getMessage());
+            throw new UnacceptableConfiguration("The configuration " + configuration + " is not acceptable for " + m_factoryName + ": " + e.getMessage());
+        }
+
+        
+        String n = null;
+        if (configuration.get("name") != null) {
+            n = (String) configuration.get("name");
+            if (m_instancesName.contains(n)) {
+                throw new UnacceptableConfiguration("Name already used : " + n);
+            }
+        } else {
+            n = generateName();
+            configuration.put("name", n);
+        }
+        m_instancesName.add(n);
+
+        IPojoContext context = null;
+        if (serviceContext == null) {
+            context = new IPojoContext(m_context);
+        } else {
+            context = new IPojoContext(m_context, serviceContext);
+        }
+        
+        HandlerManager[] handlers = new HandlerManager[m_requiredHandlers.size()];
+        for (int i = 0; i < handlers.length; i++) {
+            RequiredHandler hi = (RequiredHandler) m_requiredHandlers.get(i);
+            handlers[i] = getHandler(hi, serviceContext);
+        }
+        
+        ComponentInstance instance = createInstance(configuration, context, handlers);
+        
+        m_componentInstances.put(n, instance);
+        
+        return instance;
+    }
+
+    public BundleContext getBundleContext() {
+        return m_context;
+    }
+
+    /**
+     * Get the factory class name.
+     * @return the factory classname.
+     * @see org.apache.felix.ipojo.Factory#getClassName()
+     */
+    public abstract String getClassName();
+
+    /**
+     * Get the component type description.
+     * @return the component type description object. Null if not already computed.
+     */
+    public ComponentTypeDescription getComponentDescription() {
+        return m_componentDesc;
+    }
+
+    /**
+     * Get the component type description (Element-Attribute form).
+     * @return the component type description.
+     * @see org.apache.felix.ipojo.Factory#getDescription()
+     */
+    public Element getDescription() {
+        if (m_componentDesc == null) { return new Element("No description available for " + m_factoryName, ""); }
+        return m_componentDesc.getDescription();
+    }
+
+    /**
+     * Compute the list of missing handlers.
+     * @return list of missing handlers.
+     * @see org.apache.felix.ipojo.Factory#getMissingHandlers()
+     */
+    public List getMissingHandlers() {
+        List l = new ArrayList();
+        for (int i = 0; i < m_requiredHandlers.size(); i++) {
+            RequiredHandler hi = (RequiredHandler) m_requiredHandlers.get(i);
+            if (hi.getReference() == null) {
+                l.add(hi.getFullName());
+            }
+        }
+        return l;
+    }
+
+    public String getName() {
+        return m_factoryName;
+    }
+
+    /**
+     * Get the list of required handlers.
+     * @return list of required handlers.
+     * @see org.apache.felix.ipojo.Factory#getRequiredHandlers()
+     */
+    public List getRequiredHandlers() {
+        List l = new ArrayList();
+        for (int i = 0; i < m_requiredHandlers.size(); i++) {
+            RequiredHandler hi = (RequiredHandler) m_requiredHandlers.get(i);
+            l.add(hi.getFullName());
+        }
+        return l;
+    }
+
+    public int getState() {
+        return m_state;
+    }
+
+    /**
+     * Check if the configuration is acceptable.
+     * @param conf : the configuration to test.
+     * @return true if the configuration is acceptable.
+     * @see org.apache.felix.ipojo.Factory#isAcceptable(java.util.Dictionary)
+     */
+    public boolean isAcceptable(Dictionary conf) {
+        if (m_state == Factory.INVALID) {
+            return false;
+        }
+        
+        List props = m_componentDesc.getRequiredProperties();
+        for (int i = 0; i < props.size(); i++) {
+            // Failed if the props has no default value and the configuration does not push a value
+            if (conf.get(props.get(i)) == null) {
+                return false;
+            }
+        }
+        return true;
+    }
+    
+    /**
+     * Check if the configuration is acceptable.
+     *  @param conf : the configuration to test.
+     * @throws UnacceptableConfiguration occurs if the configuration is unacceptable.
+     * @throws MissingHandlerException occurs if an handler is missing.
+     */
+    public void checkAcceptability(Dictionary conf) throws UnacceptableConfiguration, MissingHandlerException {
+        if (m_state == Factory.INVALID) {
+            throw new MissingHandlerException(getMissingHandlers());
+        }
+        
+        List props = m_componentDesc.getRequiredProperties();
+        for (int i = 0; i < props.size(); i++) {
+            // Failed if the props has no default value and the configuration does not push a value
+            if (conf.get(props.get(i)) == null) {
+                throw new UnacceptableConfiguration("The property " + props.get(i) + " is missing");
+            }
+        }
+    }
+
+    /**
+     * Reconfigure an existing instance.
+     * @param properties : the new configuration to push.
+     * @throws UnacceptableConfiguration : occurs if the new configuration is
+     * not consistent with the component type.
+     * @throws MissingHandlerException : occurs if the current factory is not valid.
+     * @see org.apache.felix.ipojo.Factory#reconfigure(java.util.Dictionary)
+     */
+    public synchronized void reconfigure(Dictionary properties) throws UnacceptableConfiguration, MissingHandlerException {
+        if (properties == null || properties.get("name") == null) {
+            throw new UnacceptableConfiguration("The configuration does not contains the \"name\" property");
+        }
+        String name = (String) properties.get("name");
+        ComponentInstance cm = (ComponentInstance) m_componentInstances.get(name);
+        
+        if (cm == null) {
+            return; // The instance does not exist.
+        } else {
+            checkAcceptability(properties); // Test if the configuration is acceptable
+            cm.reconfigure(properties); // re-configure the component
+        }
+    }
+
+    /**
+     * Remove a factory listener.
+     * @param l : the factory listener to remove.
+     * @see org.apache.felix.ipojo.Factory#removeFactoryStateListener(org.apache.felix.ipojo.FactoryStateListener)
+     */
+    public void removeFactoryStateListener(FactoryStateListener l) {
+        synchronized (m_listeners) {
+            m_listeners.remove(l);
+        }
+    }
+    
+    /**
+     * Stopping method.
+     * This method is call when the factory is stopping.
+     */
+    public abstract void stopping();
+    
+    /**
+     * Stop all the instance managers.
+     */
+    public synchronized void  stop() {
+        if (m_sr != null) {
+            m_sr.unregister();
+            m_sr = null;
+        }
+
+        stopping();
+        
+        if (m_state == VALID) {
+            for (int i = 0; i < m_listeners.size(); i++) {
+                ((FactoryStateListener) m_listeners.get(i)).stateChanged(this, INVALID); 
+            }
+        }
+        m_state = 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 ci = (ComponentInstance) m_componentInstances.get(keys[i]);
+            if (ci.getState() != ComponentInstance.DISPOSED) {
+                ci.dispose();
+            }
+        }
+        
+        // Release each handler
+        for (int i = 0; i < m_requiredHandlers.size(); i++) {
+            ((RequiredHandler) m_requiredHandlers.get(i)).unRef();
+        }
+        
+        m_described = false;
+        m_componentDesc = null;
+    }
+    
+    /**
+     * Starting method.
+     * This method is called when the factory is starting.
+     */
+    public abstract void starting();
+    
+    /**
+     * Start the factory.
+     */
+    public synchronized void start() {
+        if (m_described) { // Already started.
+            return;
+        } 
+        
+        m_componentDesc = getComponentTypeDescription();
+        
+        starting();
+        
+        try {
+            computeFactoryState();
+        } catch (org.apache.felix.ipojo.ConfigurationException e) {
+            m_logger.log(Logger.ERROR, "The component type metadata are not correct : " + e.getMessage());
+            stop();
+            return;
+        }
+        
+        if (m_isPublic) {        
+            // Exposition of the factory service
+            m_sr = m_context.registerService(new String[] { Factory.class.getName(), ManagedServiceFactory.class.getName() }, this, m_componentDesc.getPropertiesToPublish());
+        }
+    }
+    
+    /**
+     * Create of update an instance.
+     * @param in : name of the instance
+     * @param properties : 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)
+     */
+    public synchronized void updated(String in, Dictionary properties) throws org.osgi.service.cm.ConfigurationException {
+        final InstanceManager cm = (InstanceManager) m_componentInstances.get(in);
+        if (cm == null) {
+            try {
+                properties.put("name", in); // Add the name in the configuration
+                createComponentInstance(properties);
+            } catch (UnacceptableConfiguration e) {
+                m_logger.log(Logger.ERROR, "The configuration is not acceptable : " + e.getMessage());
+                throw new org.osgi.service.cm.ConfigurationException(properties.toString(), e.getMessage());
+            } catch (MissingHandlerException e) {
+                m_logger.log(Logger.ERROR, "Handler not available : " + e.getMessage());
+                throw new org.osgi.service.cm.ConfigurationException(properties.toString(), e.getMessage());
+            } catch (ConfigurationException e) {
+                m_logger.log(Logger.ERROR, "The Component Type metadata are not correct : " + e.getMessage());
+                throw new org.osgi.service.cm.ConfigurationException(properties.toString(), e.getMessage());
+            }
+        } else {
+            try {
+                properties.put("name", in); // Add the name in the configuration
+                reconfigure(properties); // re-configure the component
+            } catch (UnacceptableConfiguration e) {
+                m_logger.log(Logger.ERROR, "The configuration is not acceptable : " + e.getMessage());
+                throw new org.osgi.service.cm.ConfigurationException(properties.toString(), e.getMessage());
+            } catch (MissingHandlerException e) {
+                m_logger.log(Logger.ERROR, "The facotry is not valid, at least one handler is missing : " + e.getMessage());
+                throw new org.osgi.service.cm.ConfigurationException(properties.toString(), e.getMessage());
+            }
+        }
+    }
+    
+    /**
+     * Delete an instance.
+     * @param in : name of the instance to delete
+     * @see org.osgi.service.cm.ManagedServiceFactory#deleted(java.lang.String)
+     */
+    public synchronized void deleted(String in) {
+        m_instancesName.remove(in);
+        ComponentInstance cm = (ComponentInstance) m_componentInstances.remove(in);
+        if (cm != null) {
+            cm.dispose();
+        }
+    }
+    
+    /**
+     * Callback called by instance when disposed.
+     * @param ci : the destroyed instance
+     */
+    public void disposed(ComponentInstance ci) {
+        String name = ci.getInstanceName();
+        m_instancesName.remove(name);
+        m_componentInstances.remove(name);
+    }
+    
+    /**
+     * Compute the component type description.
+     * The factory must be valid when calling this method.
+     * @throws org.apache.felix.ipojo.ConfigurationException if one handler has rejected the configuration.
+     */
+    protected void computeDescription() throws org.apache.felix.ipojo.ConfigurationException {         
+        for (int i = 0; i < m_requiredHandlers.size(); i++) {
+            RequiredHandler hi = (RequiredHandler) m_requiredHandlers.get(i);
+            HandlerManager hm = getHandler(hi, null);
+            Handler ch =  hm.getHandler();
+            try {
+                ch.setLogger(getLogger());
+                ch.initializeComponentFactory(m_componentDesc, m_componentMetadata);
+                ((Pojo) ch).getComponentInstance().dispose();
+            } catch (org.apache.felix.ipojo.ConfigurationException e) {
+                ((Pojo) ch).getComponentInstance().dispose();
+                throw new org.apache.felix.ipojo.ConfigurationException(e.getMessage(), m_factoryName);
+            }
+        }
+    }
+    
+    /**
+     * Compute factory state.
+     * @throws org.apache.felix.ipojo.ConfigurationException : occurs when the component type cannot be initialize.
+     */
+    protected void computeFactoryState() throws org.apache.felix.ipojo.ConfigurationException {
+        boolean isValid = true;
+        for (int i = 0; isValid && i < m_requiredHandlers.size(); i++) {
+            RequiredHandler hi = (RequiredHandler) m_requiredHandlers.get(i);
+            isValid = hi.getReference() != null;
+        }
+        
+        if (isValid) {
+            if (m_state == INVALID) {
+                
+                if (!m_described) {
+                    computeDescription();
+                    m_described = true;
+                }
+                
+                m_state = VALID;
+                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);
+                }
+                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);
+                }
+
+                // 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 ci = (ComponentInstance) m_componentInstances.get(keys[i]);
+                    if (ci.getState() != ComponentInstance.DISPOSED) {
+                        ci.dispose();
+                    }
+                    m_instancesName.remove(ci.getInstanceName());
+                }
+
+                m_componentInstances.clear();
+
+                if (m_sr != null) {
+                    m_sr.setProperties(m_componentDesc.getPropertiesToPublish());
+                }
+                
+                return;
+            }
+        }
+    }
+    
+    /**
+     * Check if the given handler identifier and the service reference can match.
+     * @param hi : the handler identifier.
+     * @param ref : the service reference.
+     * @return true if the service reference can fulfill the handler requirement
+     */
+    protected boolean match(RequiredHandler hi, ServiceReference ref) {
+        String name = (String) ref.getProperty(Handler.HANDLER_NAME_PROPERTY);
+        String ns = (String) ref.getProperty(Handler.HANDLER_NAMESPACE_PROPERTY);
+        if (IPojoConfiguration.IPOJO_NAMESPACE.equals(ns)) {
+            return name.equals(hi.getName()) && hi.getNamespace() == null;
+        }
+        return name.equals(hi.getName()) && ns.equals(hi.getNamespace()); 
+    }
+
+    /**
+     * Return the handler object for the given required handler.
+     * The handler is instantiated in the given service context.
+     * @param hi : handler to create.
+     * @param sc : service context in which create the handler (instance context).
+     * @return the Handler object.
+     */
+    protected HandlerManager getHandler(RequiredHandler hi, ServiceContext sc) {
+        try {
+            return (HandlerManager) hi.getFactory().createComponentInstance(null, sc);
+        } catch (MissingHandlerException e) {
+            m_logger.log(Logger.ERROR, "The creation of the handler " + hi.getFullName() + " has failed: " + e.getMessage());
+            stop();
+            return null;
+        } catch (UnacceptableConfiguration e) {
+            m_logger.log(Logger.ERROR, "The creation of the handler " + hi.getFullName() + " has failed (UnacceptableConfiguration): " + e.getMessage());
+            stop();
+            return null;
+        } catch (org.apache.felix.ipojo.ConfigurationException e) {
+            m_logger.log(Logger.ERROR, "The configuration of the handler " + hi.getFullName() + " has failed (ConfigurationException): " + e.getMessage());
+            stop();
+            return null;
+        }
+    }
+    
+    
+    /**
+     * Helping method generating a new unique name.
+     * @return an non already used name
+     */
+    protected synchronized String generateName() {
+        String name = m_factoryName + "-" + m_index;
+        while (m_instancesName.contains(name)) {
+            m_index = m_index + 1;
+            name = m_factoryName + "-" + m_index;
+        }
+        return name;
+    }
+
+    /**
+     * Structure storing required handlers.
+     */
+    protected class RequiredHandler implements Comparable {
+        /**
+         * Factory to create this handler.
+         */
+        private HandlerFactory m_factory;
+        
+        /**
+         * Handler name.
+         */
+        private String m_name;
+        
+        /**
+         * Handler start level.
+         */
+        private int m_level = Integer.MAX_VALUE;
+        
+        /**
+         * Handler namespace.
+         */
+        private String m_namespace;
+        
+        /**
+         * Service Reference of the handler factory.
+         */
+        private ServiceReference m_reference;
+        
+        /**
+         * Constructor.
+         * @param n : handler name.
+         * @param ns : handler namespace.
+         */
+        public RequiredHandler(String n, String ns) {
+            m_name = n;
+            m_namespace = ns;
+        }
+        
+        /**
+         * Equals method.
+         * Two handlers are equals if they have same name and namespace or they share the same service reference.
+         * @param o : object to compare to the current object.
+         * @return : true if the two compared object are equals
+         * @see java.lang.Object#equals(java.lang.Object)
+         */
+        public boolean equals(Object o) {
+            if (m_namespace == null) {
+                return ((RequiredHandler) o).m_name.equalsIgnoreCase(m_name) && ((RequiredHandler) o).m_namespace == null;
+            } else {
+                return ((RequiredHandler) o).m_name.equalsIgnoreCase(m_name) && m_namespace.equalsIgnoreCase(((RequiredHandler) o).m_namespace);
+            }
+        }
+        
+        /**
+         * Get the factory object used for this handler.
+         * The object is get when used for the first time.
+         * @return the factory object.
+         */
+        public HandlerFactory getFactory() {
+            if (m_reference == null) {
+                return null;
+            }
+            if (m_factory == null) {
+                m_factory = (HandlerFactory) m_context.getService(getReference());
+            }
+            return m_factory;
+        }
+        
+        /**
+         * Get the handler full name (namespace:name).
+         * @return the handler full name
+         */
+        public String getFullName() {
+            if (m_namespace == null) {
+                return IPojoConfiguration.IPOJO_NAMESPACE + ":" + m_name;
+            } else {
+                return m_namespace + ":" + m_name;
+            }
+        }
+        
+        public String getName() {
+            return m_name;
+        }
+        
+        public String getNamespace() {
+            return m_namespace;
+        }
+        
+        public ServiceReference getReference() {
+            return m_reference;
+        }
+        
+        public int getLevel() {
+            return m_level;
+        }
+        
+        /**
+         * Release the reference of the used factory.
+         */
+        public void unRef() {
+            if (m_reference != null) {
+                m_context.ungetService(m_reference);
+                m_factory = null;
+                m_reference = null;
+            }
+        }
+        
+        /**
+         * Set the service reference.
+         * If the new service reference is null, it unget the used factory (if already get).
+         * @param ref : new service reference.
+         */
+        public void setReference(ServiceReference ref) {            
+            m_reference = ref;
+            Integer p = (Integer) m_reference.getProperty(Handler.HANDLER_LEVEL_PROPERTY);
+            if (p != null) {
+                m_level = p.intValue();
+            }
+        }
+    
+        /**
+         * Start level Comparison.
+         * This method is used to sort the handler array.
+         * @param o : object on which compare.
+         * @return -1, 0, +1 according to the comparison of their start level.
+         * @see java.lang.Comparable#compareTo(java.lang.Object)
+         */
+        public int compareTo(Object o) {
+            if (o instanceof RequiredHandler) {
+                RequiredHandler hi = (RequiredHandler) o;
+                if (this.m_level == hi.m_level) {
+                    return 0;
+                } else if (this.m_level < hi.m_level) {
+                    return -1;
+                } else {
+                    return +1;
+                }
+            }
+            return 0;
+        }
+    }
+    
+    
+
+}

Modified: felix/sandbox/clement/ipojo/core/src/main/java/org/apache/felix/ipojo/ComponentFactory.java
URL: http://svn.apache.org/viewvc/felix/sandbox/clement/ipojo/core/src/main/java/org/apache/felix/ipojo/ComponentFactory.java?rev=606280&r1=606279&r2=606280&view=diff
==============================================================================
--- felix/sandbox/clement/ipojo/core/src/main/java/org/apache/felix/ipojo/ComponentFactory.java (original)
+++ felix/sandbox/clement/ipojo/core/src/main/java/org/apache/felix/ipojo/ComponentFactory.java Fri Dec 21 11:28:07 2007
@@ -21,27 +21,21 @@
 import java.net.URL;
 import java.security.ProtectionDomain;
 import java.util.ArrayList;
-import java.util.Collection;
 import java.util.Collections;
 import java.util.Dictionary;
 import java.util.HashMap;
-import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
-import java.util.Properties;
 
-import org.apache.felix.ipojo.architecture.ComponentDescription;
+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.util.Logger;
 import org.apache.felix.ipojo.util.Tracker;
 import org.apache.felix.ipojo.util.TrackerCustomizer;
 import org.osgi.framework.BundleContext;
-import org.osgi.framework.Constants;
 import org.osgi.framework.InvalidSyntaxException;
 import org.osgi.framework.ServiceReference;
-import org.osgi.framework.ServiceRegistration;
-import org.osgi.service.cm.ConfigurationException;
-import org.osgi.service.cm.ManagedServiceFactory;
 
 /**
  * The component factory manages component instance objects. This management
@@ -50,59 +44,7 @@
  * 
  * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
  */
-public class ComponentFactory implements Factory, ManagedServiceFactory, TrackerCustomizer {
-
-    /**
-     * List of the managed instance name. This list is shared by all factories.
-     */
-    protected static List m_instancesName = new ArrayList();
-    
-    /**
-     * Component-Type description exposed by the factory service.
-     */
-    protected ComponentDescription m_componentDesc;
-    
-    /**
-     * List of the managed instance managers. The key of this map is the
-     * name (i.e. instance names) of the created instance
-     */
-    protected Map m_componentInstances = new HashMap();
-    
-    /**
-     * Component Type provided by this factory.
-     */
-    protected Element m_componentMetadata;
-    
-    /**
-     * The bundle context reference.
-     */
-    protected BundleContext m_context = null;    
-    
-    /**
-     * Factory Name. Could be the component class name if the
-     * factory name is not set.
-     */
-    protected String m_factoryName;
-
-    /**
-     * List of required handler.
-     */
-    protected List m_handlerIdentifiers = new ArrayList();
-
-    /**
-     * List of listeners.
-     */
-    protected List m_listeners = new ArrayList(5);
-    
-    /**
-     * Logger for the factory (and all component instance).
-     */
-    protected Logger m_logger;
-
-    /**
-     * Factory state.
-     */
-    protected int m_state = Factory.INVALID;
+public class ComponentFactory extends AbstractFactory implements TrackerCustomizer {
 
     /**
      * Tracker used to track required handler factories.
@@ -110,11 +52,6 @@
     protected Tracker m_tracker;
     
     /**
-     * Is the factory public (expose as a service). 
-     */
-    protected boolean m_isPublic;
-
-    /**
      * Class loader to delegate loading.
      */
     private FactoryClassloader m_classLoader = null;
@@ -130,16 +67,6 @@
     private String m_componentClassName = null;
     
     /**
-     * Index used to generate instance name if not set.
-     */
-    private long m_index = 0;
-    
-    /**
-     * Service Registration of this factory (Factory & ManagedServiceFactory).
-     */
-    private ServiceRegistration m_sr;
-    
-    /**
      * Create a instance manager factory. The class is given in parameter. The
      * component type is not a composite.
      * @param bc : bundle context
@@ -157,72 +84,15 @@
      * @param cm : metadata of the component to create
      */
     public ComponentFactory(BundleContext bc, Element cm) {
-        m_context = bc;
-        m_componentMetadata = cm;
+        super(bc, cm);
         
         if (! check(cm)) {
             return;
-        }
-        
-        computeFactoryName();        
-        m_logger = new Logger(m_context, m_factoryName, Logger.WARNING);
-        
-        String fac = cm.getAttribute("factory");
-        m_isPublic = fac == null || ! fac.equalsIgnoreCase("false");
-        
-        computeRequiredHandlers();
-        
-    }
-    
-    /**
-     * Add a factory listener.
-     * @param l : the factory listener to add
-     * @see org.apache.felix.ipojo.Factory#addFactoryStateListener(org.apache.felix.ipojo.FactoryStateListener)
-     */
-    public void addFactoryStateListener(FactoryStateListener l) {
-        synchronized (m_listeners) {
-            m_listeners.add(l);
-        }
-        // TODO do we need to notify the actual state of the factory to the new listener ?
-    }
-
-    /**
-     * A new handler factory is detected.
-     * Test if the factory can be used or not.
-     * @param reference : the new service reference.
-     * @return true if the given factory reference match with a required handler.
-     * @see org.apache.felix.ipojo.util.TrackerCustomizer#addingService(org.osgi.framework.ServiceReference)
-     */
-    public boolean addingService(ServiceReference reference) {
-        for (int i = 0; i < m_handlerIdentifiers.size(); i++) {
-            HandlerIdentifier hi = (HandlerIdentifier) m_handlerIdentifiers.get(i);
-            if (hi.m_reference == null && match(hi, reference)) {
-                int oldP = hi.m_level;
-                hi.setReference(reference);
-                // If the priority has changed, sort the list.
-                if (oldP != hi.m_level) {
-                    Collections.sort(m_handlerIdentifiers);
-                }
-                return true;
-            }
-        }
-        return false;
+        }        
     }
     
-    /**
-     * A matching service has been added to the tracker, we can no compute the factory state.
-     * @param reference : added reference.
-     * @see org.apache.felix.ipojo.util.TrackerCustomizer#addedService(org.osgi.framework.ServiceReference)
-     */
-    public void addedService(ServiceReference reference) {
-        if (m_state == INVALID) {
-            try {
-                computeFactoryState();
-            } catch (org.apache.felix.ipojo.ConfigurationException e) {
-                m_logger.log(Logger.ERROR, "The component type metadata are not correct : " + e.getMessage());
-                stop();
-            }
-        }
+    public ComponentTypeDescription getComponentTypeDescription() {
+        return new PrimitiveTypeDescription(this);
     }
 
     /**
@@ -239,83 +109,29 @@
         } else {
             return true;
         }
-    }
-
-    /**
-     * Create an instance. The given configuration needs to contain the 'name'
-     * property.
-     * @param configuration : configuration of the created instance.
-     * @return the created component instance.
-     * @throws UnacceptableConfiguration : occurs if the given configuration is
-     * not consistent with the component type of this factory.
-     * @throws MissingHandlerException  : occurs if an handler is unavailable when the instance is created.
-     * @throws org.apache.felix.ipojo.ConfigurationException : occurs when the instance or type configuration are not correct.
-     * @see org.apache.felix.ipojo.Factory#createComponentInstance(java.util.Dictionary)
-     */
-    public ComponentInstance createComponentInstance(Dictionary configuration) throws UnacceptableConfiguration, MissingHandlerException, org.apache.felix.ipojo.ConfigurationException {
-        return createComponentInstance(configuration, null);
+    } 
+    
+    public String getClassName() {
+        return m_componentClassName;
     }
     
     /**
-     * Create an instance. The given configuration needs to contain the 'name'
-     * property.
-     * @param configuration : configuration of the created instance.
-     * @param serviceContext : the service context to push for this instance.
-     * @return the created component instance.
-     * @throws UnacceptableConfiguration : occurs if the given configuration is
-     * not consistent with the component type of this factory.
-     * @throws MissingHandlerException : occurs when an handler is unavailable when creating the instance.
-     * @throws org.apache.felix.ipojo.ConfigurationException : when the instance configuration failed.
-     * @see org.apache.felix.ipojo.Factory#createComponentInstance(java.util.Dictionary)
+     * Create a primitive instance.
+     * @param configuration : instance configuration
+     * @param context : service context.
+     * @param handlers : handler to use
+     * @return the created instance
+     * @throws org.apache.felix.ipojo.ConfigurationException : if the configuration process failed.
+     * @see org.apache.felix.ipojo.AbstractFactory#createInstance(java.util.Dictionary, org.apache.felix.ipojo.IPojoContext, org.apache.felix.ipojo.HandlerManager[])
      */
-    public synchronized ComponentInstance createComponentInstance(Dictionary configuration, ServiceContext serviceContext) throws UnacceptableConfiguration, MissingHandlerException, org.apache.felix.ipojo.ConfigurationException {        
-        if (configuration == null) {
-            configuration = new Properties();
-        }
-        
-        try {
-            checkAcceptability(configuration);
-        } catch (UnacceptableConfiguration e) {
-            m_logger.log(Logger.ERROR, "The configuration is not acceptable : " + e.getMessage());
-            throw new UnacceptableConfiguration("The configuration " + configuration + " is not acceptable for " + m_factoryName + ": " + e.getMessage());
-        }
-
-        
-        String n = null;
-        if (configuration.get("name") != null) {
-            n = (String) configuration.get("name");
-            if (m_instancesName.contains(n)) {
-                throw new UnacceptableConfiguration("Name already used : " + n);
-            }
-        } else {
-            n = generateName();
-            configuration.put("name", n);
-        }
-        m_instancesName.add(n);
-
-        BundleContext context = null;
-        if (serviceContext == null) {
-            context = new IPojoContext(m_context);
-        } else {
-            context = new IPojoContext(m_context, serviceContext);
-        }
-        
-        List handlers = new ArrayList();
-        for (int i = 0; i < m_handlerIdentifiers.size(); i++) {
-            HandlerIdentifier hi = (HandlerIdentifier) m_handlerIdentifiers.get(i);
-            handlers.add(getHandlerInstance(hi, serviceContext));
-        }
-        
-        InstanceManager instance = new InstanceManager(this, context, (HandlerManager[]) handlers.toArray(new HandlerManager[m_handlerIdentifiers.size()]));
+    public ComponentInstance createInstance(Dictionary configuration, IPojoContext context, HandlerManager[] handlers) throws org.apache.felix.ipojo.ConfigurationException {
+        InstanceManager instance = new InstanceManager(this, context, handlers);
         try {
             instance.configure(m_componentMetadata, configuration);
+            instance.start();
         } catch (org.apache.felix.ipojo.ConfigurationException e) {
             throw new org.apache.felix.ipojo.ConfigurationException(e.getMessage(), m_factoryName);
         }
-
-        m_componentInstances.put(n, instance);
-        instance.start();
-
         return instance;
     }
 
@@ -334,95 +150,6 @@
     }
     
     /**
-     * Delete an instance.
-     * @param in : name of the instance to delete
-     * @see org.osgi.service.cm.ManagedServiceFactory#deleted(java.lang.String)
-     */
-    public synchronized void deleted(String in) {
-        m_instancesName.remove(in);
-        final ComponentInstance cm = (ComponentInstance) m_componentInstances.remove(in);
-        if (cm == null) {
-            return; // do nothing, the component does not exist !
-        } else {
-            cm.dispose();
-        }
-    }
-
-    /**
-     * Get the component type description.
-     * @return the component type description object. Null if not already computed.
-     */
-    public ComponentDescription getComponentDescription() {
-        return m_componentDesc;
-    }
-
-    /**
-     * Get the component type description attached to this factory.
-     * @return : the component type description
-     * @see org.apache.felix.ipojo.Factory#getDescription()
-     */
-    public Element getDescription() {
-        if (m_componentDesc == null) { return new Element("No description available for " + m_factoryName, ""); }
-        return m_componentDesc.getDescription();
-    }
-    
-    /**
-     * Get the logger used by instances of he current factory.
-     * @return the factory logger.
-     */
-    public Logger getLogger() {
-        return m_logger;
-    }
-    
-    /**
-     * Get the list of missing handlers.
-     * @return the list of missing handlers (namespace:name)
-     * @see org.apache.felix.ipojo.Factory#getMissingHandlers()
-     */
-    public List getMissingHandlers() {
-        List l = new ArrayList();
-        for (int i = 0; i < m_handlerIdentifiers.size(); i++) {
-            HandlerIdentifier hi = (HandlerIdentifier) m_handlerIdentifiers.get(i);
-            if (hi.m_reference == null) {
-                l.add(hi.getFullName());
-            }
-        }
-        return l;
-    }
-
-    /**
-     * Get the name of this factory.
-     * 
-     * @return the name of this factory
-     * @see org.apache.felix.ipojo.Factory#getName()
-     */
-    public String getName() {
-        return m_factoryName;
-    }
-
-    /**
-     * Get the list of required handlers.
-     * @return the list of required handlers (namespace:name)
-     * @see org.apache.felix.ipojo.Factory#getRequiredHandlers()
-     */
-    public List getRequiredHandlers() {
-        List l = new ArrayList();
-        for (int i = 0; i < m_handlerIdentifiers.size(); i++) {
-            HandlerIdentifier hi = (HandlerIdentifier) m_handlerIdentifiers.get(i);
-            l.add(hi.getFullName());
-        }
-        return l;
-    }
-    
-    public String getClassName() {
-        return m_componentClassName;
-    }
-
-    public int getState() {
-        return m_state;
-    }
-    
-    /**
      * Return the URL of a resource.
      * @param resName : resource name
      * @return the URL of the resource
@@ -432,24 +159,6 @@
     }
 
     /**
-     * Check if the given configuration is acceptable as a component instance
-     * configuration. This method checks that if all the configurable properties
-     * have a value.
-     * @param conf : the configuration to check
-     * @return true when the configuration seems to be acceptable
-     */
-    public boolean isAcceptable(Dictionary conf) {
-        try {
-            checkAcceptability(conf);
-        } catch (UnacceptableConfiguration e) { 
-            return false; 
-        } catch (MissingHandlerException e) { 
-            return false;  
-        }
-        return true;
-    }
-
-    /**
      * Load a class.
      * @param className : name of the class to load
      * @return the resulting Class object
@@ -472,85 +181,14 @@
         return m_context.getBundle().loadClass(className);
     }
 
-    /**
-     * A used handler factory is modified.
-     * @param reference : the service reference
-     * @param service : the Factory object (if already get)
-     * @see org.apache.felix.ipojo.util.TrackerCustomizer#modifiedService(org.osgi.framework.ServiceReference, java.lang.Object)
-     */
-    public void modifiedService(ServiceReference reference, Object service) {
-        // Noting to do
-    }
-
-    /**
-     * Reconfigure an existing instance.
-     * @param properties : the new configuration to push.
-     * @throws UnacceptableConfiguration : occurs if the new configuration is
-     * not consistent with the component type.
-     * @throws MissingHandlerException : occurs if the current factory is not valid.
-     * @see org.apache.felix.ipojo.Factory#reconfigure(java.util.Dictionary)
-     */
-    public synchronized void reconfigure(Dictionary properties) throws UnacceptableConfiguration, MissingHandlerException {
-        if (properties == null || properties.get("name") == null) {
-            throw new UnacceptableConfiguration("The configuration does not contains the \"name\" property");
-        }
-        final String name = (String) properties.get("name");
-        InstanceManager cm = (InstanceManager) m_componentInstances.get(name);
-        
-        if (cm == null) {
-            return; // The instance does not exist.
-        } else {
-            checkAcceptability(properties); // Test if the configuration is acceptable
-            cm.reconfigure(properties); // re-configure the component
-        }
-    }
-
-    /**
-     * A used factory disappears.
-     * @param reference : service reference.
-     * @param service : factory object.
-     * @see org.apache.felix.ipojo.util.TrackerCustomizer#removedService(org.osgi.framework.ServiceReference, java.lang.Object)
-     */
-    public void removedService(ServiceReference reference, Object service) {
-        // Look for the implied reference and invalid the handler identifier
-        for (int i = 0; i < m_handlerIdentifiers.size(); i++) {
-            HandlerIdentifier hi = (HandlerIdentifier) m_handlerIdentifiers.get(i);
-            if (reference.equals(hi.getReference())) {
-                hi.unRef(); // This method will unget the service.
-                try {
-                    computeFactoryState();
-                } catch (org.apache.felix.ipojo.ConfigurationException e) {
-                    m_logger.log(Logger.ERROR, "The component type metadata are not correct : " + e.getMessage());
-                    stop();
-                }
-                return; // The factory can be used only once.
-            }
-        }
-    }
-
-    /**
-     * Remove a factory listener.
-     * @param l : the factory listener to remove
-     * @see org.apache.felix.ipojo.Factory#removeFactoryStateListener(org.apache.felix.ipojo.FactoryStateListener)
-     */
-    public void removeFactoryStateListener(FactoryStateListener l) {
-        synchronized (m_listeners) {
-            m_listeners.remove(l);
-        }
-    }
 
     /**
      * Start the factory.
      */
-    public synchronized void start() {
-        if (m_componentDesc != null) { // Already started.
-            return;
-        } 
-        
-        if (m_handlerIdentifiers.size() != 0) {
+    public synchronized void starting() {        
+        if (m_requiredHandlers.size() != 0) {
             try {
-                String filter = "(&(" + Constants.OBJECTCLASS + "=" + Factory.class.getName() + ")"
-                        + "(" + Handler.HANDLER_TYPE_PROPERTY + "=" + PrimitiveHandler.HANDLER_TYPE + ")" 
+                String filter = "(&(" + Handler.HANDLER_TYPE_PROPERTY + "=" + PrimitiveHandler.HANDLER_TYPE + ")" 
                         + "(factory.state=1)"
                         + ")";
                 m_tracker = new Tracker(m_context, m_context.createFilter(filter), this);
@@ -561,485 +199,134 @@
                 return;
             }
         }
-            
-        try {
-            computeFactoryState();
-        } catch (org.apache.felix.ipojo.ConfigurationException e) {
-            m_logger.log(Logger.ERROR, "The component type metadata are not correct : " + e.getMessage());
-            stop();
-            return;
-        }
-
-        if (m_isPublic) {        
-            // Exposition of the factory service
-            m_sr = m_context.registerService(new String[] { Factory.class.getName(), ManagedServiceFactory.class.getName() }, this, getProperties());
-        }
     }
 
     /**
      * Stop all the instance managers.
      */
-    public synchronized void stop() {
-        if (m_sr != null) {
-            m_sr.unregister();
-            m_sr = null;
-        }
-        
-        if (m_tracker != null) {        
-            m_tracker.close();
-        }
-        
-        final Collection col = m_componentInstances.values();
-        final Iterator it = col.iterator();
-        while (it.hasNext()) {
-            InstanceManager ci = (InstanceManager) it.next();
-            if (ci.getState() != ComponentInstance.DISPOSED) {
-                ci.kill();
-            }
-            m_instancesName.remove(ci.getInstanceName());
-        }
-        
-        m_componentInstances.clear();
-        
-        // Release each handler
-        for (int i = 0; i < m_handlerIdentifiers.size(); i++) {
-            ((HandlerIdentifier) m_handlerIdentifiers.get(i)).unRef();
-        }
-        
-        m_tracker = null;
-        m_componentDesc = null;
+    public synchronized void stopping() {
         m_classLoader = null;
         m_clazz = null;
-        m_state = INVALID;
     }
     
-    /**
-     * Create of update an instance.
-     * @param in : name of the instance
-     * @param properties : configuration of the instance
-     * @throws ConfigurationException : if the configuration is not consistent
-     * for this component type
-     * @see org.osgi.service.cm.ManagedServiceFactory#updated(java.lang.String,
-     * java.util.Dictionary)
-     */
-    public synchronized void updated(String in, Dictionary properties) throws ConfigurationException {
-        final InstanceManager cm = (InstanceManager) m_componentInstances.get(in);
-        if (cm == null) {
-            try {
-                properties.put("name", in); // Add the name in the configuration
-                createComponentInstance(properties);
-            } catch (UnacceptableConfiguration e) {
-                m_logger.log(Logger.ERROR, "The configuration is not acceptable : " + e.getMessage());
-                throw new ConfigurationException(properties.toString(), e.getMessage());
-            } catch (MissingHandlerException e) {
-                m_logger.log(Logger.ERROR, "Handler not available : " + e.getMessage());
-                throw new ConfigurationException(properties.toString(), e.getMessage());
-            } catch (org.apache.felix.ipojo.ConfigurationException e) {
-                m_logger.log(Logger.ERROR, "The Component Type metadata are not correct : " + e.getMessage());
-                throw new ConfigurationException(properties.toString(), e.getMessage());
-            }
-        } else {
-            try {
-                properties.put("name", in); // Add the name in the configuration
-                reconfigure(properties); // re-configure the component
-            } catch (UnacceptableConfiguration e) {
-                m_logger.log(Logger.ERROR, "The configuration is not acceptable : " + e.getMessage());
-                throw new ConfigurationException(properties.toString(), e.getMessage());
-            } catch (MissingHandlerException e) {
-                m_logger.log(Logger.ERROR, "The facotry is not valid, at least one handler is missing : " + e.getMessage());
-                throw new ConfigurationException(properties.toString(), e.getMessage());
-            }
-        }
-    }
-
-    /**
-     * Test is a configuration is acceptable for the factory.
-     * @param conf : the configuration to test.
-     * @throws UnacceptableConfiguration : the configuration is not acceptable.
-     * @throws MissingHandlerException : the factory is not valid.
-     */
-    protected void checkAcceptability(Dictionary conf) throws UnacceptableConfiguration, MissingHandlerException {
-        if (m_state == Factory.INVALID) {
-            throw new MissingHandlerException(getMissingHandlers());
-        }
-        
-        List props = m_componentDesc.getRequiredProperties();
-        for (int i = 0; i < props.size(); i++) {
-            // Failed if the props has no default value and the configuration does not push a value
-            if (conf.get(props.get(i)) == null) {
-                throw new UnacceptableConfiguration("The configuration does not contains the \"" + props.get(i) + "\" property");
-            }
-        }
-    }
-    
-    /**
-     * Compute the component type description.
-     * The factory must be valid when calling this method.
-     * @throws org.apache.felix.ipojo.ConfigurationException if one handler has rejected the configuration.
-     */
-    protected void computeDescription() throws org.apache.felix.ipojo.ConfigurationException {
-        m_componentDesc = new ComponentDescription(this);
-         
-        for (int i = 0; i < m_handlerIdentifiers.size(); i++) {
-            HandlerIdentifier hi = (HandlerIdentifier) m_handlerIdentifiers.get(i);
-            HandlerManager hm = getHandlerInstance(hi, null);
-            Handler ch =  hm.getHandler();
-            try {
-                ch.setLogger(getLogger());
-                ch.initializeComponentFactory(m_componentDesc, m_componentMetadata);
-                ((Pojo) ch).getComponentInstance().dispose();
-            } catch (org.apache.felix.ipojo.ConfigurationException e) {
-                ((Pojo) ch).getComponentInstance().dispose();
-                throw new org.apache.felix.ipojo.ConfigurationException(e.getMessage(), m_factoryName);
-            }
-        }
-    }
 
     /**
      * Compute the factory name.
+     * @return the factory name.
      */
-    protected void computeFactoryName() {
-        m_factoryName = m_componentMetadata.getAttribute("name");
-        if (m_factoryName == null) { // No factory name, try with factory attribute
-            m_factoryName = m_componentMetadata.getAttribute("factory");
-            if (m_factoryName == null || m_factoryName.equalsIgnoreCase("true") || m_factoryName.equalsIgnoreCase("false")) { // Avoid boolean case
-                m_factoryName = m_componentMetadata.getAttribute("className");
-            }
-        }
-    }
-    
-    /**
-     * Compute factory state.
-     * @throws org.apache.felix.ipojo.ConfigurationException : occurs when the component type cannot be initialize.
-     */
-    protected void computeFactoryState() throws org.apache.felix.ipojo.ConfigurationException {
-        boolean isValid = true;
-        for (int i = 0; isValid && i < m_handlerIdentifiers.size(); i++) {
-            HandlerIdentifier hi = (HandlerIdentifier) m_handlerIdentifiers.get(i);
-            isValid = hi.m_reference != null;
-        }
-        
-        if (isValid) {
-            if (m_state == INVALID) {
-                
-                if (m_componentDesc == null) {
-                    computeDescription();
-                }
-                
-                m_state = VALID;
-                if (m_sr != null) {
-                    m_sr.setProperties(getProperties());
-                }
-                for (int i = 0; i < m_listeners.size(); i++) {
-                    ((FactoryStateListener) m_listeners.get(i)).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);
-                }
-
-                // Dispose created instances.
-                final Collection col = m_componentInstances.values();
-                final Iterator it = col.iterator();
-                while (it.hasNext()) {
-                    InstanceManager ci = (InstanceManager) it.next();
-                    if (ci.getState() != ComponentInstance.DISPOSED) {
-                        ci.kill();
-                    }
-                    m_instancesName.remove(ci.m_name);
-                }
-
-                m_componentInstances.clear();
-
-                // Update service properties TODO : really useful ?
-                if (m_sr != null) {
-                    m_sr.setProperties(getProperties());
-                }
-                
-                return;
+    public String getFactoryName() {
+        String s = m_componentMetadata.getAttribute("name");
+        if (s == null) { // No factory name, try with factory attribute
+            s = m_componentMetadata.getAttribute("factory");
+            if (s == null || s.equalsIgnoreCase("true") || s.equalsIgnoreCase("false")) { // Avoid boolean case
+                s = m_componentMetadata.getAttribute("className");
             }
         }
+        return s;
     }
     
     /**
      * Compute required handlers.
+     * @return the required handler list.
      */
-    protected void computeRequiredHandlers() {
+    public List getRequiredHandlerList() {
+        List list = new ArrayList();
         Element[] elems = m_componentMetadata.getElements();
         for (int i = 0; i < elems.length; i++) {
             Element current = elems[i]; 
             if (current.getName().equals("manipulation")) { continue; }
-            HandlerIdentifier hi = new HandlerIdentifier(current.getName(), current.getNameSpace());
-            if (! m_handlerIdentifiers.contains(hi)) { m_handlerIdentifiers.add(hi); }
+            RequiredHandler hi = new RequiredHandler(current.getName(), current.getNameSpace());
+            if (! list.contains(hi)) { list.add(hi); }
         }
         
         // Add architecture if architecture != 'false'
-        HandlerIdentifier hi = new HandlerIdentifier("architecture", null);
+        RequiredHandler hi = new RequiredHandler("architecture", null);
         String arch = m_componentMetadata.getAttribute("architecture");
         if (arch == null || arch.equalsIgnoreCase("true")) {
-            m_handlerIdentifiers.add(hi);
+            list.add(hi);
         }
         
         // Add lifecycle callback if immediate = true
-        HandlerIdentifier hi2 = new HandlerIdentifier("callback", null);
+        RequiredHandler hi2 = new RequiredHandler("callback", null);
         String imm = m_componentMetadata.getAttribute("immediate");
-        if (! m_handlerIdentifiers.contains(hi2) && imm != null && imm.equalsIgnoreCase("true")) {
-            m_handlerIdentifiers.add(hi2);
+        if (! list.contains(hi2) && imm != null && imm.equalsIgnoreCase("true")) {
+            list.add(hi2);
         }
-    }
-
-    /**
-     * Callback called by instance when disposed.
-     * @param ci : the destroyed instance
-     */
-    protected void disposed(ComponentInstance ci) {
-        String name = ci.getInstanceName();
-        m_instancesName.remove(name);
-        m_componentInstances.remove(name);
+        
+        return list;
     }
     
     /**
-     * Generate an instance name.
-     * @return an non already used name
+     * A new handler factory is detected.
+     * Test if the factory can be used or not.
+     * @param reference : the new service reference.
+     * @return true if the given factory reference match with a required handler.
+     * @see org.apache.felix.ipojo.util.TrackerCustomizer#addingService(org.osgi.framework.ServiceReference)
      */
-    protected synchronized String generateName() {
-        String name = m_factoryName + "-" + m_index;
-        while (m_instancesName.contains(name)) {
-            m_index = m_index + 1;
-            name = m_factoryName + "-" + m_index;
+    public boolean addingService(ServiceReference reference) {
+        for (int i = 0; i < m_requiredHandlers.size(); i++) {
+            RequiredHandler hi = (RequiredHandler) m_requiredHandlers.get(i);
+            if (hi.getReference() == null && match(hi, reference)) {
+                int oldP = hi.getLevel();
+                hi.setReference(reference);
+                // If the priority has changed, sort the list.
+                if (oldP != hi.getLevel()) {
+                    Collections.sort(m_requiredHandlers);
+                }
+                return true;
+            }
         }
-        return name;
+        return false;
     }
     
     /**
-     * Return the bundle context.
-     * @return the Bundle Context.
-     */
-    public BundleContext getBundleContext() {
-        return m_context;
-    }
-
-    /**
-     * Get the implementation class of the component type.
-     * 
-     * @return the name of the component-type implementation class.
-     */
-    protected String getComponentClassName() {
-        return m_componentClassName;
-    }
-
-    /**
-     * Compute factory properties.
-     * @return the properties.
+     * A matching service has been added to the tracker, we can no compute the factory state.
+     * @param reference : added reference.
+     * @see org.apache.felix.ipojo.util.TrackerCustomizer#addedService(org.osgi.framework.ServiceReference)
      */
-    protected Properties getProperties() {
-        final Properties props = new Properties();
-
-        props.put("component.class", m_componentClassName);
-       
-        props.put("factory.name", m_factoryName);
-        props.put(Constants.SERVICE_PID, m_factoryName); // Service PID is required for the integration in the configuration admin.
-        
-        if (m_componentDesc != null) {
-            props.put("component.providedServiceSpecifications", m_componentDesc.getprovidedServiceSpecification());
-            props.put("component.properties", m_componentDesc.getProperties());
-            props.put("component.description", m_componentDesc);
+    public void addedService(ServiceReference reference) {
+        if (m_state == INVALID) {
+            try {
+                computeFactoryState();
+            } catch (org.apache.felix.ipojo.ConfigurationException e) {
+                m_logger.log(Logger.ERROR, "The component type metadata are not correct : " + e.getMessage());
+                stop();
+            }
         }
-        
-        // Add factory state
-        props.put("factory.state", "" + m_state);
-        
-        return props;
     }
     
     /**
-     * Check if the given handler identifier and the service reference can match.
-     * @param hi : the handler identifier.
-     * @param ref : the service reference.
-     * @return true if the service reference can fulfill the handler requirement
-     */
-    protected boolean match(HandlerIdentifier hi, ServiceReference ref) {
-        String name = (String) ref.getProperty(Handler.HANDLER_NAME_PROPERTY);
-        String ns = (String) ref.getProperty(Handler.HANDLER_NAMESPACE_PROPERTY);
-        if (IPojoConfiguration.IPOJO_NAMESPACE.equals(ns)) {
-            return name.equals(hi.m_name) && hi.m_namespace == null;
-        }
-        return name.equals(hi.m_name) && ns.equals(hi.m_namespace); 
-    }
-
-    /**
-     * Return an handler object.
-     * @param hi : handler to create.
-     * @param sc : service context in which create the handler (instance context).
-     * @return the Handler object.
+     * A used factory disappears.
+     * @param reference : service reference.
+     * @param service : factory object.
+     * @see org.apache.felix.ipojo.util.TrackerCustomizer#removedService(org.osgi.framework.ServiceReference, java.lang.Object)
      */
-    private HandlerManager getHandlerInstance(HandlerIdentifier hi, ServiceContext sc) {
-        try {
-            return (HandlerManager) hi.getFactory().createComponentInstance(null, sc);
-        } catch (MissingHandlerException e) {
-            m_logger.log(Logger.ERROR, "The creation of the handler " + hi.getFullName() + " has failed: " + e.getMessage());
-            stop();
-            return null;
-        } catch (UnacceptableConfiguration e) {
-            m_logger.log(Logger.ERROR, "The creation of the handler " + hi.getFullName() + " has failed (UnacceptableConfiguration): " + e.getMessage());
-            stop();
-            return null;
-        } catch (org.apache.felix.ipojo.ConfigurationException e) {
-            m_logger.log(Logger.ERROR, "The configuration of the handler " + hi.getFullName() + " has failed (ConfigurationException): " + e.getMessage());
-            stop();
-            return null;
+    public void removedService(ServiceReference reference, Object service) {
+        // Look for the implied reference and invalid the handler identifier
+        for (int i = 0; i < m_requiredHandlers.size(); i++) {
+            RequiredHandler hi = (RequiredHandler) m_requiredHandlers.get(i);
+            if (reference.equals(hi.getReference())) {
+                hi.unRef(); // This method will unget the service.
+                try {
+                    computeFactoryState();
+                } catch (org.apache.felix.ipojo.ConfigurationException e) {
+                    m_logger.log(Logger.ERROR, "The component type metadata are not correct : " + e.getMessage());
+                    stop();
+                }
+                return; // The factory can be used only once.
+            }
         }
     }
-
+    
     /**
-     * Structure storing required handlers.
+     * A used handler factory is modified.
+     * @param reference : the service reference
+     * @param service : the Factory object (if already get)
+     * @see org.apache.felix.ipojo.util.TrackerCustomizer#modifiedService(org.osgi.framework.ServiceReference, java.lang.Object)
      */
-    class HandlerIdentifier implements Comparable {
-        /**
-         * Factory to create this handler.
-         */
-        private HandlerFactory m_factory;
-        
-        /**
-         * Handler name.
-         */
-        private String m_name;
-        
-        /**
-         * Handler start level.
-         */
-        private int m_level = Integer.MAX_VALUE;
-        
-        /**
-         * Handler namespace.
-         */
-        private String m_namespace;
-        
-        /**
-         * Service Reference of the handler factory.
-         */
-        private ServiceReference m_reference;
-        
-        /**
-         * Constructor.
-         * @param n : handler name.
-         * @param ns : handler namespace.
-         */
-        public HandlerIdentifier(String n, String ns) {
-            m_name = n;
-            m_namespace = ns;
-        }
-        
-        /**
-         * Equals method.
-         * Two handlers are equals if they have same name and namespace or they share the same service reference.
-         * @param o : object to compare to the current object.
-         * @return : true if the two compared object are equals
-         * @see java.lang.Object#equals(java.lang.Object)
-         */
-        public boolean equals(Object o) {
-            if (m_namespace == null) {
-                return ((HandlerIdentifier) o).m_name.equalsIgnoreCase(m_name) && ((HandlerIdentifier) o).m_namespace == null;
-            } else {
-                return ((HandlerIdentifier) o).m_name.equalsIgnoreCase(m_name) && m_namespace.equalsIgnoreCase(((HandlerIdentifier) o).m_namespace);
-            }
-        }
-        
-        /**
-         * Get the factory object used for this handler.
-         * The object is get when used for the first time.
-         * @return the factory object.
-         */
-        public HandlerFactory getFactory() {
-            if (m_reference == null) {
-                return null;
-            }
-            if (m_factory == null) {
-                m_factory = (HandlerFactory) m_tracker.getService(getReference());
-            }
-            return m_factory;
-        }
-        
-        /**
-         * Get the handler full name (namespace:name).
-         * @return the handler full name
-         */
-        public String getFullName() {
-            if (m_namespace == null) {
-                return IPojoConfiguration.IPOJO_NAMESPACE + ":" + m_name;
-            } else {
-                return m_namespace + ":" + m_name;
-            }
-        }
-        
-        public String getName() {
-            return m_name;
-        }
-        
-        public String getNamespace() {
-            return m_namespace;
-        }
-        
-        public ServiceReference getReference() {
-            return m_reference;
-        }
-        
-        public int getLevel() {
-            return m_level;
-        }
-        
-        /**
-         * Release the reference of the used factory.
-         */
-        public void unRef() {
-            if (m_reference != null) {
-                m_tracker.ungetService(m_reference);
-                m_factory = null;
-                m_reference = null;
-            }
-        }
-        
-        /**
-         * Set the service reference.
-         * If the new service reference is null, it unget the used factory (if already get).
-         * @param ref : new service reference.
-         */
-        public void setReference(ServiceReference ref) {            
-            m_reference = ref;
-            Integer p = (Integer) m_reference.getProperty(Handler.HANDLER_LEVEL_PROPERTY);
-            if (p != null) {
-                m_level = p.intValue();
-            }
-        }
-
-        /**
-         * Start level Comparison.
-         * This method is used to sort the handler array.
-         * @param o : object on which compare.
-         * @return -1, 0, +1 according to the comparison of their start level.
-         * @see java.lang.Comparable#compareTo(java.lang.Object)
-         */
-        public int compareTo(Object o) {
-            if (o instanceof HandlerIdentifier) {
-                HandlerIdentifier hi = (HandlerIdentifier) o;
-                if (this.m_level == hi.m_level) {
-                    return 0;
-                } else if (this.m_level < hi.m_level) {
-                    return -1;
-                } else {
-                    return +1;
-                }
-            }
-            return 0;
-        }
+    public void modifiedService(ServiceReference reference, Object service) {
+        // Noting to do
     }
-
     /**
      * FactoryClassloader.
      */
@@ -1086,6 +373,42 @@
          */
         protected Class loadClass(final String name, final boolean resolve) throws ClassNotFoundException {
             return m_context.getBundle().loadClass(name);
+        }
+    }
+    
+    private final class PrimitiveTypeDescription extends ComponentTypeDescription {
+
+        /**
+         * Constructor.
+         * @param factory : the represented factory.
+         */
+        private PrimitiveTypeDescription(Factory factory) {
+            super(factory);
+        }
+        
+        /**
+         * Compute the properties to publish : 
+         * component.class contains the pojo class name.
+         * @return the dictionary of properties to publish
+         * @see org.apache.felix.ipojo.architecture.ComponentTypeDescription#getPropertiesToPublish()
+         */
+        public Dictionary getPropertiesToPublish() {
+            Dictionary dict = super.getPropertiesToPublish(); 
+            if (m_componentClassName != null) { 
+                dict.put("component.class", m_componentClassName); 
+            }
+            return dict;
+        }
+        
+        /**
+         * Add 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_componentClassName));
+            return elem;
         }
     }
 }