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 2008/03/28 16:35:29 UTC

svn commit: r642265 [3/11] - in /felix/trunk/ipojo: ./ annotations/ ant/ ant/src/main/java/org/apache/felix/ipojo/task/ arch/ arch/src/main/java/org/apache/felix/ipojo/arch/ arch/src/main/resources/ composite/ composite/src/ composite/src/main/ composi...

Modified: felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/ConfigurationException.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/ConfigurationException.java?rev=642265&r1=642264&r2=642265&view=diff
==============================================================================
--- felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/ConfigurationException.java (original)
+++ felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/ConfigurationException.java Fri Mar 28 08:33:36 2008
@@ -29,11 +29,6 @@
      * Serialization Id.
      */
     private static final long serialVersionUID = 1L;
-
-    /**
-     * Message.
-     */
-    private String m_message;
     
     /**
      * Component Type on which the error occurs.
@@ -46,8 +41,8 @@
      * @param typ : component type
      */
     ConfigurationException(String mes, String typ) {
+        super(mes);
         m_type = typ;
-        m_message = mes;
     }
     
     /**
@@ -55,7 +50,7 @@
      * @param mes : message
      */
     public ConfigurationException(String mes) {
-        m_message = mes;
+        super(mes);
     }
     
     /**
@@ -64,10 +59,10 @@
      * @see java.lang.Throwable#getMessage()
      */
     public String getMessage() {
-        if (m_type != null) {
-            return "The configuration is not correct for the type " + m_type + " : " + m_message;
+        if (m_type == null) {
+            return super.getMessage();
         } else {
-            return m_message;
+            return "The configuration is not correct for the type " + m_type + " : " + super.getMessage();
         }
     }
 

Modified: felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/Extender.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/Extender.java?rev=642265&r1=642264&r2=642265&view=diff
==============================================================================
--- felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/Extender.java (original)
+++ felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/Extender.java Fri Mar 28 08:33:36 2008
@@ -19,20 +19,27 @@
 package org.apache.felix.ipojo;
 
 import java.io.IOException;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
 import java.util.Dictionary;
-import java.util.Enumeration;
-import java.util.Hashtable;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
 
 import org.apache.felix.ipojo.metadata.Element;
 import org.apache.felix.ipojo.parser.ManifestMetadataParser;
 import org.apache.felix.ipojo.parser.ParseException;
+import org.apache.felix.ipojo.parser.ParseUtils;
+import org.apache.felix.ipojo.util.Logger;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleActivator;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.BundleEvent;
-import org.osgi.framework.ServiceReference;
 import org.osgi.framework.SynchronousBundleListener;
-import org.osgi.service.log.LogService;
 
 /**
  * iPOJO Extender.
@@ -42,39 +49,52 @@
 public class Extender implements SynchronousBundleListener, BundleActivator {
 
     /**
-     * iPOJO Manifest header.
+     * iPOJO Component Type and Instance declaration header.
      */
     private static final String IPOJO_HEADER = "iPOJO-Components";
-    
+
+    /**
+     * iPOJO Extension declaration header. 
+     */
+    private static final String IPOJO_EXTENSION = "IPOJO-Extension";
+
+    /**
+     * iPOJO Extender logger.
+     */
+    private Logger m_logger;
+
     /**
      * iPOJO Bundle Context.
      */
     private BundleContext m_context;
-    
+
+    /**
+     * Declared instance manager.
+     */
+    private InstanceCreator m_creator;
+
     /**
-     * Dictionary of [BundleId, Factory List]. 
+     * iPOJO Bundle.
      */
-    private Dictionary m_components;
-    
+    private Bundle m_bundle;
+
     /**
-     * Dictionary of [BundleId, Instance Creator]. 
+     * List of factory types.
      */
-    private Dictionary m_creators;
-    
+    private List m_factoryTypes = new ArrayList();
+
     /**
-     * iPOJO Bundle Id.
+     * List of unbound types.
      */
-    private long m_bundleId;
-    
+    private final List m_unboundTypes = new ArrayList();
+
     /**
      * Bundle Listener Notification.
      * @param event : the bundle event.
      * @see org.osgi.framework.BundleListener#bundleChanged(org.osgi.framework.BundleEvent)
      */
     public synchronized void bundleChanged(BundleEvent event) {
-        if (event.getBundle().getBundleId() == m_bundleId) {
-            return;
-        }
+        if (event.getBundle() == m_bundle) { return; }
 
         switch (event.getType()) {
             case BundleEvent.STARTED:
@@ -83,7 +103,7 @@
             case BundleEvent.STOPPING:
                 closeManagementFor(event.getBundle());
                 break;
-            default: 
+            default:
                 break;
         }
 
@@ -94,42 +114,109 @@
      * @param bundle : the bundle.
      */
     private void closeManagementFor(Bundle bundle) {
-        ComponentFactory[] cfs = (ComponentFactory[]) m_components.get(bundle);
-        InstanceCreator creator = (InstanceCreator) m_creators.get(bundle);
-        if (cfs == null && creator == null) { return; }
-        for (int i = 0; cfs != null && i < cfs.length; i++) {
-            ComponentFactory factory = cfs[i];
-            factory.stop();
-        }
-        if (creator != null) { creator.stop(); }
-        
-        m_components.remove(bundle);
-        m_creators.remove(bundle);
-        
+        List toRemove = new ArrayList();
+        for (int k = 0; k < m_factoryTypes.size(); k++) {
+            ManagedAbstractFactoryType mft = (ManagedAbstractFactoryType) m_factoryTypes.get(k);
+
+            // Delete instances declared in the leaving bundle.
+            m_creator.removeInstancesFromBundle(bundle.getBundleId());
+
+            // Look for component type created from this bundle.
+            if (mft.m_created != null) {
+                List cfs = (List) mft.m_created.remove(bundle);
+                for (int i = 0; cfs != null && i < cfs.size(); i++) {
+                    IPojoFactory factory = (IPojoFactory) cfs.get(i);
+                    m_creator.removeFactory(factory);
+                    factory.stop();
+                }
+            }
+
+            // If the leaving bundle has declared mft : destroy all created factories.
+            if (mft.m_bundle == bundle) {
+                if (mft.m_created != null) {
+                    Iterator iterator = mft.m_created.keySet().iterator();
+                    while (iterator.hasNext()) {
+                        Bundle key = (Bundle) iterator.next();
+                        List list = (List) mft.m_created.get(key);
+                        for (int i = 0; i < list.size(); i++) {
+                            IPojoFactory factory = (IPojoFactory) list.get(i);
+                            factory.stop();
+                            m_unboundTypes.add(new UnboundComponentType(mft.m_type, factory.m_componentMetadata, factory.getBundleContext()
+                                    .getBundle()));
+                        }
+                    }
+                }
+                toRemove.add(mft);
+            }
+        }
+
+        for (int i = 0; i < toRemove.size(); i++) {
+            ManagedAbstractFactoryType mft = (ManagedAbstractFactoryType) toRemove.get(i);
+            m_logger.log(Logger.WARNING, "The factory type available: " + mft.m_type + " is no more available");
+            mft.m_bundle = null;
+            mft.m_clazz = null;
+            mft.m_created = null;
+            mft.m_type = null;
+            m_factoryTypes.remove(mft);
+        }
     }
 
     /**
-     * Check if the given bundle is an iPOJO bundle, and begin the iPOJO management is true. 
+     * Check if the given bundle is an iPOJO bundle, and begin the iPOJO management is true.
      * @param bundle : the bundle to check.
      */
     private void startManagementFor(Bundle bundle) {
-        // Check bundle
         Dictionary dict = bundle.getHeaders();
+        // Check for abstract factory type
+        String typeHeader = (String) dict.get(IPOJO_EXTENSION);
+        if (typeHeader != null) {
+            parseAbstractFactoryType(bundle, typeHeader);
+        }
+
+        // Check bundle
         String header = (String) dict.get(IPOJO_HEADER);
-        if (header == null) {
-            return;
-        } else {
+        if (header != null) {
             try {
                 parse(bundle, header);
             } catch (IOException e) {
-                err("An exception occurs during the parsing of the bundle " + bundle.getBundleId(), e);
+                m_logger.log(Logger.ERROR, "An exception occurs during the parsing of the bundle " + bundle.getBundleId(), e);
             } catch (ParseException e) {
-                err("A parse exception occurs during the parsing of the bundle " + bundle.getBundleId(), e);
+                m_logger.log(Logger.ERROR, "A parse exception occurs during the parsing of the bundle " + bundle.getBundleId(), e);
             }
         }
-        
     }
-    
+
+    /**
+     * Parse an IPOJO-Extension manifest header.
+     * @param bundle : bundle containing the header.
+     * @param header : header to parse.
+     */
+    private void parseAbstractFactoryType(Bundle bundle, String header) {
+        String[] arr = ParseUtils.split(header, ",");
+        for (int i = 0; arr != null && i < arr.length; i++) {
+            String[] arr2 = ParseUtils.split(arr[i], ":");
+            String type = arr2[0];
+            Class clazz;
+            try {
+                clazz = bundle.loadClass(arr2[1]);
+            } catch (ClassNotFoundException e) {
+                m_logger.log(Logger.ERROR, "Cannot load the extension " + type, e);
+                return;
+            }
+            ManagedAbstractFactoryType mft = new ManagedAbstractFactoryType(clazz, type, bundle);
+            m_factoryTypes.add(mft);
+            m_logger.log(Logger.WARNING, "New factory type available: " + type);
+
+            for (int j = m_unboundTypes.size() - 1; j >= 0; j--) {
+                UnboundComponentType unbound = (UnboundComponentType) m_unboundTypes.get(j);
+                if (unbound.m_type.equals(type)) {
+                    createAbstractFactory(unbound.m_bundle, unbound.m_description);
+                    m_unboundTypes.remove(unbound);
+                }
+            }
+        }
+    }
+
     /**
      * Parse the internal metadata (from the manifest (in the iPOJO-Components property)).
      * @param bundle : the owner bundle.
@@ -140,35 +227,40 @@
     private void parse(Bundle bundle, String components) throws IOException, ParseException {
         ManifestMetadataParser parser = new ManifestMetadataParser();
         parser.parseHeader(components);
-          
-        Element[] componentsMetadata = parser.getComponentsMetadata(); // Get the component type declaration
-        for (int i = 0; i < componentsMetadata.length; i++) { addComponentFactory(bundle, componentsMetadata[i]); }
-        
-        start(bundle, parser.getInstances());
+
+        Element[] metadata = parser.getComponentsMetadata(); // Get the component type declaration
+        for (int i = 0; i < metadata.length; i++) {
+            createAbstractFactory(bundle, metadata[i]);
+        }
+
+        Dictionary[] instances = parser.getInstances();
+        for (int i = 0; instances != null && i < instances.length; i++) {
+            m_creator.addInstance(instances[i], bundle.getBundleId());
+        }
     }
 
     /**
      * iPOJO Starting method.
-     * @param bc : iPOJO bundle context.
-     * @throws Exception : the start method failed.
+     * @param context : iPOJO bundle context.
      * @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext)
      */
-    public void start(BundleContext bc) throws Exception {
-        m_context = bc;
-        m_bundleId = bc.getBundle().getBundleId();
-        m_components = new Hashtable();
-        m_creators = new Hashtable();
+    public void start(BundleContext context) {
+        m_context = context;
+        m_bundle = context.getBundle();
+        m_creator = new InstanceCreator(context);
+
+        m_logger = new Logger(m_context, "IPOJO Extender");
 
         // Begin by initializing core handlers
-        startManagementFor(bc.getBundle());
+        startManagementFor(m_bundle);
 
         synchronized (this) {
             // listen to any changes in bundles.
             m_context.addBundleListener(this);
             // compute already started bundles.
-            for (int i = 0; i < bc.getBundles().length; i++) {
-                if (bc.getBundles()[i].getState() == Bundle.ACTIVE) {
-                    startManagementFor(bc.getBundles()[i]);
+            for (int i = 0; i < context.getBundles().length; i++) {
+                if (context.getBundles()[i].getState() == Bundle.ACTIVE) {
+                    startManagementFor(context.getBundles()[i]);
                 }
             }
         }
@@ -176,96 +268,238 @@
 
     /**
      * Stop the iPOJO Management.
-     * @param bc : bundle context.
-     * @throws Exception : the stop method failed.
+     * @param context : bundle context.
      * @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext)
      */
-    public void stop(BundleContext bc) throws Exception {
+    public void stop(BundleContext context) {
         m_context.removeBundleListener(this);
-        Enumeration e = m_components.keys();
-        while (e.hasMoreElements()) {
-            ComponentFactory[] cfs = (ComponentFactory[]) m_components.get(e.nextElement());
-            for (int i = 0; i < cfs.length; i++) {
-                cfs[i].stop();
-            }
-        }
-        m_components = null;
-        Enumeration e2 = m_creators.keys();
-        while (e2.hasMoreElements()) {
-            InstanceCreator creator = (InstanceCreator) m_creators.remove(e2.nextElement());
-            creator.stop();
+
+        for (int k = 0; k < m_factoryTypes.size(); k++) {
+            ManagedAbstractFactoryType mft = (ManagedAbstractFactoryType) m_factoryTypes.get(k);
+
+            if (mft.m_created != null) {
+                Iterator iterator = mft.m_created.keySet().iterator();
+                while (iterator.hasNext()) {
+                    Bundle key = (Bundle) iterator.next();
+                    List list = (List) mft.m_created.get(key);
+                    for (int i = 0; i < list.size(); i++) {
+                        IPojoFactory factory = (IPojoFactory) list.get(i);
+                        m_creator.removeFactory(factory);
+                        factory.dispose();
+                    }
+                }
+            }
         }
-        m_creators = null;
+
+        m_factoryTypes = null;
+        m_creator = null;
     }
-    
+
     /**
      * Add a component factory to the factory list.
-     * @param cm : the new component metadata.
+     * @param metadata : the new component metadata.
      * @param bundle : the bundle.
      */
-    private void addComponentFactory(Bundle bundle, Element cm) {
-        ComponentFactory factory = null;
-        if (cm.getName().equalsIgnoreCase("component")) {
-            factory = new ComponentFactory(bundle.getBundleContext(), cm);
-        } else if (cm.getName().equalsIgnoreCase("composite")) {
-            factory = new CompositeFactory(bundle.getBundleContext(), cm);
-        } else if (cm.getName().equalsIgnoreCase("handler")) {
-            factory = new HandlerFactory(bundle.getBundleContext(), cm);
-        } else {
-            err("Not recognized element type : " + cm.getName(), null);
-        }
-
-        ComponentFactory[] cfs = (ComponentFactory[]) m_components.get(bundle);
-        
-        // If the factory array is not empty add the new factory at the end
-        if (cfs != null && cfs.length != 0) {
-            ComponentFactory[] newFactory = new ComponentFactory[cfs.length + 1];
-            System.arraycopy(cfs, 0, newFactory, 0, cfs.length);
-            newFactory[cfs.length] = factory;
-            cfs = newFactory;
-            m_components.put(bundle, cfs);
-        } else {
-            m_components.put(bundle, new ComponentFactory[] {factory}); // Else create an array of size one with the new Factory 
-        }
-    }
-    
-    /**
-     * Start the management of factories and create instances.
-     * @param bundle : the bundle. 
-     * @param confs : the instances to create.
-     */
-    private void start(Bundle bundle, Dictionary[] confs) {
-        ComponentFactory[] cfs = (ComponentFactory[]) m_components.get(bundle);
-        
-        // Start the factories
-        if (cfs != null) {
-            for (int j = 0; j < cfs.length; j++) {
-                cfs[j].start();
+    private void createAbstractFactory(Bundle bundle, Element metadata) {
+        ManagedAbstractFactoryType factoryType = null;
+        // First, look for factory-type (component, handler, composite ...)
+        for (int i = 0; i < m_factoryTypes.size(); i++) {
+            ManagedAbstractFactoryType type = (ManagedAbstractFactoryType) m_factoryTypes.get(i);
+            if (type.m_type.equals(metadata.getName())) {
+                factoryType = type;
+                break;
+            }
+        }
+
+        // If not found, return. It will wait for a new component type factory.
+        if (factoryType == null) {
+            m_logger.log(Logger.WARNING, "Type of component not yet recognized : " + metadata.getName());
+            m_unboundTypes.add(new UnboundComponentType(metadata.getName(), metadata, bundle));
+            return;
+        }
+
+        // Once found, we invoke the AbstractFactory constructor to create the component factory. 
+        Class clazz = factoryType.m_clazz;
+        try {
+            // Look for the constructor, and invoke it.
+            Constructor cst = clazz.getConstructor(new Class[] { BundleContext.class, Element.class });
+            IPojoFactory factory = (IPojoFactory) cst.newInstance(new Object[] { getBundleContext(bundle), metadata });
+
+            // Add the created factory in the m_createdFactories map.
+            if (factoryType.m_created == null) {
+                factoryType.m_created = new HashMap();
+                List list = new ArrayList();
+                list.add(factory);
+                factoryType.m_created.put(bundle, list);
+            } else {
+                List list = (List) factoryType.m_created.get(bundle);
+                if (list == null) {
+                    list = new ArrayList();
+                    list.add(factory);
+                    factoryType.m_created.put(bundle, list);
+                } else {
+                    list.add(factory);
+                }
+            }
+
+            // Start the created factory.
+            factory.start();
+            // Then add the factory to the instance creator.
+            m_creator.addFactory(factory);
+
+        } catch (SecurityException e) {
+            m_logger.log(Logger.ERROR, "Cannot instantiate an abstract factory from " + clazz.getName(), e);
+        } catch (NoSuchMethodException e) {
+            m_logger.log(Logger.ERROR, "Cannot instantiate an abstract factory from " + clazz.getName() + ": the given class constructor cannot be found");
+        } catch (IllegalArgumentException e) {
+            m_logger.log(Logger.ERROR, "Cannot instantiate an abstract factory from " + clazz.getName(), e);
+        } catch (InstantiationException e) {
+            m_logger.log(Logger.ERROR, "Cannot instantiate an abstract factory from " + clazz.getName(), e);
+        } catch (IllegalAccessException e) {
+            m_logger.log(Logger.ERROR, "Cannot instantiate an abstract factory from " + clazz.getName(), e);
+        } catch (InvocationTargetException e) {
+            m_logger.log(Logger.ERROR, "Cannot instantiate an abstract factory from " + clazz.getName(), e.getTargetException());
+        }
+    }
+
+    /**
+     * Structure storing an iPOJO extension.
+     */
+    private final class ManagedAbstractFactoryType {
+        /**
+         * TYpe (i.e.) name of the extension.
+         */
+        String m_type;
+
+        /**
+         * Abstract Factory class.
+         */
+        Class m_clazz;
+
+        /**
+         * Bundle object containing the declaration of the extension.
+         */
+        Bundle m_bundle;
+
+        /**
+         * Factories created by this extension. 
+         */
+        private Map m_created;
+
+        /**
+         * Constructor.
+         * @param factory : abstract factory class.
+         * @param type : name of the extension.
+         * @param bundle : bundle declaring the extension.
+         */
+        protected ManagedAbstractFactoryType(Class factory, String type, Bundle bundle) {
+            m_bundle = bundle;
+            m_clazz = factory;
+            m_type = type;
+        }
+    }
+
+    /**
+     * Structure storing unbound component type declaration.
+     * Unbound means that there is no extension able to manage it.
+     */
+    private final class UnboundComponentType {
+        /**
+         * Component type description.
+         */
+        private final Element m_description;
+
+        /**
+         * Bundle declaring this type.
+         */
+        private final Bundle m_bundle;
+
+        /**
+         * Required extension name.
+         */
+        private final String m_type;
+
+        /**
+         * Constructor.
+         * @param description : description of the component type.
+         * @param bundle : bundle declaring this type.
+         * @param type : required extension name.
+         */
+        protected UnboundComponentType(String type, Element description, Bundle bundle) {
+            m_type = type;
+            m_description = description;
+            m_bundle = bundle;
+        }
+    }
+
+    /**
+     * Compute the bundle context from the bundle class by introspection.
+     * @param bundle : bundle.
+     * @return the bundle context object or null if not found.
+     */
+    public BundleContext getBundleContext(Bundle bundle) {
+        if (bundle == null) { return null; }
+
+        // getBundleContext (OSGi 4.1)
+        Method meth = null;
+        try {
+            meth = bundle.getClass().getMethod("getBundleContext", new Class[0]);
+        } catch (SecurityException e) {
+            // Nothing do to, will try the Equinox method
+        } catch (NoSuchMethodException e) {
+            // Nothing do to, will try the Equinox method
+        }
+
+        // try Equinox getContext if not found.
+        if (meth == null) {
+            try {
+                meth = bundle.getClass().getMethod("getContext", new Class[0]);
+            } catch (SecurityException e) {
+                // Nothing do to, will try field inspection
+            } catch (NoSuchMethodException e) {
+                // Nothing do to, will try field inspection
+            }
+        }
+
+        if (meth != null) {
+            if (! meth.isAccessible()) { 
+                // If not accessible, try to set the accessibility.
+                meth.setAccessible(true);
+            }
+            try {
+                return (BundleContext) meth.invoke(bundle, new Object[0]);
+            } catch (IllegalArgumentException e) {
+                m_logger.log(Logger.ERROR, "Cannot get the BundleContext by invoking " + meth.getName(), e);
+                return null;
+            } catch (IllegalAccessException e) {
+                m_logger.log(Logger.ERROR, "Cannot get the BundleContext by invoking " + meth.getName(), e);
+                return null;
+            } catch (InvocationTargetException e) {
+                m_logger.log(Logger.ERROR, "Cannot get the BundleContext by invoking " + meth.getName(), e.getTargetException());
+                return null;
             }
         }
 
-        // Create the instance creator if needed.
-        if (confs.length > 0) {
-            m_creators.put(bundle, new InstanceCreator(bundle.getBundleContext(), confs, cfs));
-        }
-    }
-    
-    /**
-     * Log an error message in a log service (if available) and display the message in the console.
-     * @param message : the message to log
-     * @param t : an attached error (can be null)
-     */
-    private void err(String message, Throwable t) {
-        ServiceReference ref = m_context.getServiceReference(LogService.class.getName());
-        if (ref != null) {
-            LogService log = (LogService) m_context.getService(ref);
-            log.log(LogService.LOG_ERROR, message, t);
-            m_context.ungetService(ref);
-        }
-        if (t != null) {
-            System.err.println("[iPOJO-Core] " + message + " : " + t.getMessage());
-        } else {
-            System.err.println("[iPOJO-Core] " + message);
+        // Else : Field inspection (KF and Prosyst)        
+        Field[] fields = bundle.getClass().getDeclaredFields();
+        for (int i = 0; i < fields.length; i++) {
+            if (BundleContext.class.isAssignableFrom(fields[i].getType())) {
+                if (!fields[i].isAccessible()) {
+                    fields[i].setAccessible(true);
+                }
+                try {
+                    return (BundleContext) fields[i].get(bundle);
+                } catch (IllegalArgumentException e) {
+                    m_logger.log(Logger.ERROR, "Cannot get the BundleContext by invoking " + meth.getName(), e);
+                    return null;
+                } catch (IllegalAccessException e) {
+                    m_logger.log(Logger.ERROR, "Cannot get the BundleContext by invoking " + meth.getName(), e);
+                    return null;
+                }
+            }
         }
+        m_logger.log(Logger.ERROR, "Cannot find the BundleContext for " + bundle.getSymbolicName(), null);
+        return null;
     }
+
 }

Modified: felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/Factory.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/Factory.java?rev=642265&r1=642264&r2=642265&view=diff
==============================================================================
--- felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/Factory.java (original)
+++ felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/Factory.java Fri Mar 28 08:33:36 2008
@@ -21,7 +21,7 @@
 import java.util.Dictionary;
 import java.util.List;
 
-import org.apache.felix.ipojo.architecture.ComponentDescription;
+import org.apache.felix.ipojo.architecture.ComponentTypeDescription;
 import org.apache.felix.ipojo.metadata.Element;
 import org.osgi.framework.BundleContext;
 
@@ -72,7 +72,7 @@
      * Get the component type description.
      * @return the component type description object
      */
-    ComponentDescription getComponentDescription();
+    ComponentTypeDescription getComponentDescription();
 
     /**
      * Check if the given configuration is acceptable as a configuration of a component instance.
@@ -97,15 +97,15 @@
 
     /**
      * Add a factory state listener on the current factory.
-     * @param l : the listener to add
+     * @param listener : the listener to add
      */
-    void addFactoryStateListener(FactoryStateListener l);
+    void addFactoryStateListener(FactoryStateListener listener);
 
     /**
      * Remove the given factory state listener from the listener list.
-     * @param l : the listener to remove
+     * @param listener : the listener to remove
      */
-    void removeFactoryStateListener(FactoryStateListener l);
+    void removeFactoryStateListener(FactoryStateListener listener);
 
     /**
      * Get the list of missing handlers.

Modified: felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/Handler.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/Handler.java?rev=642265&r1=642264&r2=642265&view=diff
==============================================================================
--- felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/Handler.java (original)
+++ felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/Handler.java Fri Mar 28 08:33:36 2008
@@ -20,7 +20,7 @@
 
 import java.util.Dictionary;
 
-import org.apache.felix.ipojo.architecture.ComponentDescription;
+import org.apache.felix.ipojo.architecture.ComponentTypeDescription;
 import org.apache.felix.ipojo.architecture.HandlerDescription;
 import org.apache.felix.ipojo.metadata.Element;
 import org.apache.felix.ipojo.util.Logger;
@@ -31,17 +31,17 @@
  * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
  */
 public abstract class Handler {
-    
+
     /**
      * Handler namespace property.
      */
     public static final String HANDLER_NAMESPACE_PROPERTY = "handler.namespace";
-    
+
     /**
      * Handler name property. 
      */
     public static final String HANDLER_NAME_PROPERTY = "handler.name";
-    
+
     /**
      * Handler type property. 
      */
@@ -51,39 +51,73 @@
      * Handler priority.
      */
     public static final String HANDLER_LEVEL_PROPERTY = "handler.level";
-    
+
     /**
-     * Handler logger.
+     * Handler validity.
      */
-    private Logger m_logger;
-    
+    protected boolean m_isValid = true;
+
+    /**
+     * HandlerManager managing the current handler.
+     */
+    protected HandlerManager m_instance;
+
+    /**
+     * Set the factory attached to this handler object.
+     * This method must be override to depend on each component factory type. 
+     * @param factory : the factory.
+     */
+    public abstract void setFactory(Factory factory);
+
     /**
-     * Set the logger use by this handler.
-     * @param logger : the logger object to use.
+     * Get the logger to use in the handler.
+     * This method must be override to depend on each component factory type logging policy.
+     * @return the logger.
      */
-    final void setLogger(Logger logger) {
-        m_logger = logger;
+    public abstract Logger getLogger();
+
+    /**
+     * Log method (warning).
+     * @param message : message to log
+     */
+    public final void warn(String message) {
+        getLogger().log(Logger.WARNING, message);
     }
-    
+
     /**
-     * Log method.
-     * @param level : message level (Logger class constant)
+     * Log method (error).
      * @param message : message to log
      */
-    public final void log(int level, String message) {
-        m_logger.log(level, message);
+    public final void error(String message) {
+        getLogger().log(Logger.ERROR, message);
     }
-    
+
     /**
-     * Log method.
-     * @param level : message level (Logger class constant)
+     * Log method (info).
      * @param message : message to log
-     * @param ex : exception to attach to the message
      */
-    public final void log(int level, String message, Throwable ex) {
-        m_logger.log(level, message, ex);
+    public final void info(String message) {
+        getLogger().log(Logger.INFO, message);
     }
-    
+
+    /**
+     * Log method (warning).
+     * @param message : message to log
+     * @param exception : exception to attach to the message
+     */
+    public final void warn(String message, Throwable exception) {
+        getLogger().log(Logger.WARNING, message, exception);
+    }
+
+    /**
+     * Log method (error).
+     * @param message : message to log
+     * @param exception : exception to attach to the message
+     */
+    public final void error(String message, Throwable exception) {
+        getLogger().log(Logger.ERROR, message, exception);
+    }
+
     /**
      * Get a plugged handler of the same container.
      * This method must be call only in the start method (or after). 
@@ -93,41 +127,65 @@
      * @return the handler object or null if the handler is not found.
      */
     public abstract Handler getHandler(String name);
-    
+
     /**
      * Attach the current handler object to the given component instance.
      * An attached handler becomes a part of the instance container.
-     * @param ci : the component instance on which the current handler will be attached.
+     * @param instance : the component instance on which the current handler will be attached.
      */
-    protected abstract void attach(ComponentInstance ci);
-    
+    protected abstract void attach(ComponentInstance instance);
+
     /**
      * Check if the current handler is valid.
+     * This check test the handlers validity.
      * This method must not be override.
      * @return true if the handler is valid.
      */
     public final boolean isValid() {
         return ((Pojo) this).getComponentInstance().getState() == ComponentInstance.VALID;
     }
-    
-    
+
+    /**
+     * Set the validity of the current handler.
+     * @param isValid : if true the handler becomes valid, else it becomes invalid.
+     */
+    public final void setValidity(boolean isValid) {
+        if (m_isValid != isValid) {
+            m_isValid = isValid;
+            HandlerManager instance = getHandlerManager();
+            if (isValid) {
+                instance.stateChanged(instance, ComponentInstance.VALID);
+            } else {
+                instance.stateChanged(instance, ComponentInstance.INVALID);
+            }
+        }
+    }
+
+    public final boolean getValidity() {
+        return m_isValid;
+    }
+
     /**
      * Get the component instance of the current handler.
      * @return : the component instance.
      */
-    public final ComponentInstance getInstance() {
-        return ((Pojo) this).getComponentInstance();
+    public final HandlerManager getHandlerManager() {
+        if (m_instance != null) { return m_instance; }
+        m_instance = (HandlerManager) ((Pojo) this).getComponentInstance();
+        return m_instance;
     }
-    
+
     /**
      * Initialize component factory.
      * This method aims to gather component factory properties. Each handler wanting to contribute need to override this 
      * method and add properties to the given component description.
-     * @param cd : component description.
+     * @param typeDesc : component description.
      * @param metadata : component type metadata.
      * @throws ConfigurationException : if the metadata are not correct (early detection).
      */
-    public void initializeComponentFactory(ComponentDescription cd, Element metadata) throws ConfigurationException {  }
+    public void initializeComponentFactory(ComponentTypeDescription typeDesc, Element metadata) throws ConfigurationException {
+        // The default implementation does nothing.
+    }
 
     /**
      * Configure the handler.
@@ -151,7 +209,9 @@
      * This method is called when the component state changed.
      * @param state : the new state
      */
-    public void stateChanged(int state) { }
+    public void stateChanged(int state) {
+        // The default implementation does nothing.
+    }
 
     /**
      * Return the current handler description.
@@ -166,5 +226,7 @@
      * The instance is reconfiguring.
      * @param configuration : New instance configuration.
      */
-    public void reconfigure(Dictionary configuration) { }
+    public void reconfigure(Dictionary configuration) {
+        // The default implementation does nothing.
+    }
 }

Modified: felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/HandlerFactory.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/HandlerFactory.java?rev=642265&r1=642264&r2=642265&view=diff
==============================================================================
--- felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/HandlerFactory.java (original)
+++ felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/HandlerFactory.java Fri Mar 28 08:33:36 2008
@@ -18,20 +18,12 @@
  */
 package org.apache.felix.ipojo;
 
-import java.util.ArrayList;
-import java.util.Collection;
 import java.util.Dictionary;
-import java.util.Iterator;
-import java.util.List;
 import java.util.Properties;
 
-import org.apache.felix.ipojo.architecture.ComponentDescription;
+import org.apache.felix.ipojo.architecture.ComponentTypeDescription;
 import org.apache.felix.ipojo.metadata.Element;
-import org.apache.felix.ipojo.util.Logger;
-import org.apache.felix.ipojo.util.Tracker;
 import org.osgi.framework.BundleContext;
-import org.osgi.framework.InvalidSyntaxException;
-import org.osgi.framework.ServiceRegistration;
 
 /**
  * The component factory manages component instance objects. This management
@@ -43,20 +35,20 @@
 public class HandlerFactory extends ComponentFactory implements Factory {
 
     /**
-     * Service Registration of this factory (Factory & ManagedServiceFactory).
+     * iPOJO Default Namespace.
      */
-    private ServiceRegistration m_sr;
-    
+    public static final String IPOJO_NAMESPACE = "org.apache.felix.ipojo";
+
     /**
      * Handler type (composite|primitive).
      * Default: handler.
      */
     private String m_type = "primitive";
-    
+
     /**
      * Default iPOJO Namespace.
      */
-    private String m_namespace = IPojoConfiguration.IPOJO_NAMESPACE;
+    private String m_namespace = IPOJO_NAMESPACE;
 
     /**
      * Get the handler start level.
@@ -67,114 +59,67 @@
 
     /**
      * Create a composite factory.
-     * @param bc : bundle context
-     * @param cm : metadata of the component to create
+     * @param context : bundle context
+     * @param metadata : metadata of the component to create
+     * @throws ConfigurationException occurs when the element describing the factory is malformed.
      */
-    public HandlerFactory(BundleContext bc, Element cm) {
-        super(bc, cm);
-        
+    public HandlerFactory(BundleContext context, Element metadata) throws ConfigurationException {
+        super(context, metadata);
+
         // Get the name
-        m_factoryName = cm.getAttribute("name").toLowerCase();
-        if (m_factoryName == null) {
-            System.err.println("An Handler needs a name");
-            return;
-        }
-        
+        m_factoryName = metadata.getAttribute("name");
+        if (m_factoryName == null) { throw new ConfigurationException("An Handler needs a name"); }
+
         // Get the type
-        String t = cm.getAttribute("type");
-        if (t != null) {
-            m_type = t;
+        String type = metadata.getAttribute("type");
+        if (type != null) {
+            m_type = type;
         }
-        
-        String l = cm.getAttribute("level");
-        if (l != null) {
-            m_level = new Integer(l).intValue();
+
+        String level = metadata.getAttribute("level");
+        if (level != null) {
+            m_level = new Integer(level).intValue();
         }
-        
+
         // Get the namespace
-        String ns = cm.getAttribute("namespace");
-        if (ns != null) {
-            m_namespace = ns.toLowerCase();
-        }        
+        String namespace = metadata.getAttribute("namespace");
+        if (namespace != null) {
+            m_namespace = namespace.toLowerCase();
+        }
     }
-    
+
     public String getNamespace() {
         return m_namespace;
     }
-    
+
     public String getHandlerName() {
         return m_namespace + ":" + getName();
     }
-    
+
     public String getType() {
         return m_type;
     }
-    
+
     public int getStartLevel() {
         return m_level;
     }
 
-    /**
-     * Start all the instance managers.
-     */
-    public synchronized void start() {
-        if (m_sr != null) { // Already started.
-            return;
-        }
-        
-        if (m_handlerIdentifiers.size() != 0) {
-            try {
-                String filter = "(&(" + Handler.HANDLER_TYPE_PROPERTY + "=" + PrimitiveHandler.HANDLER_TYPE + ")" 
-                    + "(factory.state=1)"
-                    + ")";
-                m_tracker = new Tracker(m_context, m_context.createFilter(filter), this);
-                m_tracker.open();
-            } catch (InvalidSyntaxException e) {
-                m_logger.log(Logger.ERROR, "A factory filter is not valid: " + e.getMessage());
-                stop();
-                return;
-            }
-        }
-                
-        try {
-            computeFactoryState();
-        } catch (ConfigurationException e) {
-            m_logger.log(Logger.ERROR, "Cannot initilize the factory " + e.getMessage());
-            stop();
-            return;
-        }
-        
-        // Exposition of the factory service (always public for handlers)
-        m_sr = m_context.registerService(new String[] { Factory.class.getName()}, this, getProperties());
+    public ComponentTypeDescription getComponentTypeDescription() {
+        return new HandlerTypeDescription(this);
     }
-    
+
     /**
      * Stop the factory.
      * This method does not disposed created instances.
      * These instances will be disposed by the instance managers.
      */
-    public synchronized void stop() {
-        if (m_sr != null) {
-            m_sr.unregister();
-            m_sr = null;
-        }
-        
+    public synchronized void stopping() {
         if (m_tracker != null) {
             m_tracker.close();
             m_tracker = null;
         }
-        
-        // Release each handler
-        for (int i = 0; i < m_handlerIdentifiers.size(); i++) {
-            ((HandlerIdentifier) m_handlerIdentifiers.get(i)).unRef();
-        }
-        
-        m_handlerIdentifiers.clear();        
-        m_listeners.clear();
-        m_state = INVALID;        
     }
-    
-    
+
     /**
      * Compute factory service properties.
      * This method add three mandatory handler factory properties (name, namespace and type)
@@ -183,164 +128,53 @@
      */
     protected Properties getProperties() {
         Properties props = new Properties();
-        
-        // Add factory state
-        props.put("factory.state", "" + m_state);
-
-        props.put(Handler.HANDLER_NAME_PROPERTY, m_factoryName);
-        props.put(Handler.HANDLER_NAMESPACE_PROPERTY, m_namespace);
-        props.put(Handler.HANDLER_TYPE_PROPERTY, m_type);
-        if (m_level != Integer.MAX_VALUE) {
-            props.put(Handler.HANDLER_LEVEL_PROPERTY, new Integer(m_level));
-        }
-        
+
         return props;
     }
-    
-    /**
-     * Compute handler factory state.
-     * @throws ConfigurationException : occurs when an handler cannot be initialized.
-     */
-    protected void computeFactoryState() throws ConfigurationException {
-        boolean isValid = true;
-        for (int i = 0; isValid && i < m_handlerIdentifiers.size(); i++) {
-            HandlerIdentifier hi = (HandlerIdentifier) m_handlerIdentifiers.get(i);
-            isValid = hi.getReference() != null;
-        }
-        
-        if (isValid) {            
-            if (m_state == INVALID) {
-                m_state = VALID;
-                
-                if (m_sr == null) {
-                    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);
-                        hm.getHandler();
-                        Handler ch = hm.getHandler();
-                        ch.setLogger(getLogger());
-                        ch.initializeComponentFactory(m_componentDesc, m_componentMetadata);
-                        ((Pojo) ch).getComponentInstance().dispose();
-                    }
-                }
-                
-                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();
-
-                if (m_sr != null) {
-                    m_sr.setProperties(getProperties());
-                }
-                
-                return;
-            }
-        }
-    }
-    
+
     /**
      * 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.
+     * @param context : the service context to push for this instance.
+     * @param handlers : handler array to used.
      * @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 synchronized ComponentInstance createComponentInstance(Dictionary configuration, ServiceContext serviceContext) throws UnacceptableConfiguration, MissingHandlerException, org.apache.felix.ipojo.ConfigurationException {
-        if (m_state == Factory.INVALID) {
-            throw new MissingHandlerException(getMissingHandlers());
-        }
-        
-        if (configuration == null) {
-            configuration = new Properties();
-        }
-        
-        String in = null;
-        if (configuration.get("name") != null) {
-            in = (String) configuration.get("name");
-        } else {
-            in = generateName();
-            configuration.put("name", in);
-        }
-        
-        if (m_instancesName.contains(in)) {
-            throw new UnacceptableConfiguration("Name already used : " + in);
-        } else {
-            m_instancesName.add(in);
-        }
-
-        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));
-        }
-        
-        HandlerManager instance = new HandlerManager(this, context, (HandlerManager[]) handlers.toArray(new HandlerManager[handlers.size()]));
+    public ComponentInstance createInstance(Dictionary configuration, IPojoContext context, HandlerManager[] handlers) throws ConfigurationException {
+        HandlerManager instance = new HandlerManager(this, context, handlers);
         instance.configure(m_componentMetadata, configuration);
-
-        m_componentInstances.put(in, instance);
-        
-        
         return instance;
     }
-    
-    /**
-     * Return an handler object.
-     * @param hi : handler to create.
-     * @param sc : service context in which create the handler (instance context).
-     * @return the Handler 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;
+
+    private class HandlerTypeDescription extends ComponentTypeDescription {
+
+        /**
+         * Constructor.
+         * @param factory : factory.
+         */
+        public HandlerTypeDescription(Factory factory) {
+            super(factory);
+        }
+
+        /**
+         * Add properties to publish : 
+         * handler.name, handler.namespace, handler.type and handler.level if the level is not Integer.MAX.
+         * @return return the dictionary to publish.
+         * @see org.apache.felix.ipojo.architecture.ComponentTypeDescription#getPropertiesToPublish()
+         */
+        public Dictionary getPropertiesToPublish() {
+            Dictionary props = super.getPropertiesToPublish();
+
+            props.put(Handler.HANDLER_NAME_PROPERTY, m_factoryName);
+            props.put(Handler.HANDLER_NAMESPACE_PROPERTY, m_namespace);
+            props.put(Handler.HANDLER_TYPE_PROPERTY, m_type);
+            if (m_level != Integer.MAX_VALUE) {
+                props.put(Handler.HANDLER_LEVEL_PROPERTY, new Integer(m_level));
+            }
+            return props;
         }
     }
 }

Modified: felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/HandlerManager.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/HandlerManager.java?rev=642265&r1=642264&r2=642265&view=diff
==============================================================================
--- felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/HandlerManager.java (original)
+++ felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/HandlerManager.java Fri Mar 28 08:33:36 2008
@@ -24,12 +24,12 @@
 import org.osgi.framework.BundleContext;
 
 /**
-* The handler manager manages an handler instance.
-* 
-* @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
-*/
+ * The handler manager manages an handler instance.
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
 public class HandlerManager extends InstanceManager {
-    
+
     /**
      * Handler object (contained).
      */
@@ -38,13 +38,13 @@
     /**
      * Constructor.
      * @param factory : handler factory
-     * @param bc : bundle context
+     * @param context : bundle context
      * @param handlers : handler array
      */
-    public HandlerManager(ComponentFactory factory, BundleContext bc, HandlerManager[] handlers) {
-        super(factory, bc, handlers);
+    public HandlerManager(ComponentFactory factory, BundleContext context, HandlerManager[] handlers) {
+        super(factory, context, handlers);
     }
-    
+
     /**
      * Get the contained handler object.
      * If not already created it creates the object.
@@ -56,73 +56,68 @@
         }
         return m_handler;
     }
-    
+
     /**
      * Create and initialize the handler object.
-     * @param ci : component instance on which the handler will be attached.
-     * @param cm : component metadata.
+     * @param instance : component instance on which the handler will be attached.
+     * @param metadata : component metadata.
      * @param configuration : instance configuration.
      * @throws ConfigurationException if the handler configuration failed.
      */
-    public void init(ComponentInstance ci, Element cm, Dictionary configuration) throws ConfigurationException {
+    public void init(ComponentInstance instance, Element metadata, Dictionary configuration) throws ConfigurationException {
         createHandlerObject();
-        m_handler.attach(ci);
-        m_handler.configure(cm, configuration);
+        m_handler.setFactory(instance.getFactory());
+        m_handler.attach(instance);
+        m_handler.configure(metadata, configuration);
     }
-    
+
     /**
      * Create the handler object.
      * This method does nothing if the object is already created.
      */
     private void createHandlerObject() {
         if (m_handler != null) { return; }
-        Handler h  = (Handler) createPojoObject();
-        if (h instanceof PrimitiveHandler) {
-            m_handler = (PrimitiveHandler) h;
-        } else {
-            m_handler = (CompositeHandler) h;
-        }
+        m_handler = (Handler) createPojoObject();
     }
-    
+
     /**
      * Start the instance manager.
      */
     public synchronized void start() {
-        if (m_state != STOPPED) {
-            return;
-        } // Instance already started
+        if (m_state != STOPPED) { return; } // Instance already started
 
         for (int i = 0; i < m_handlers.length; i++) {
             m_handlers[i].addInstanceStateListener(this);
             m_handlers[i].start();
         }
-        
+
         m_handler.start(); // Call the handler start method.
-        
+
         for (int i = 0; i < m_handlers.length; i++) {
-            if (! m_handlers[i].getHandler().isValid()) {
+            if (!m_handlers[i].getHandler().isValid()) {
                 setState(INVALID);
                 return;
             }
         }
-        setState(VALID);
+        if (m_handler.getValidity()) {
+            setState(VALID);
+        } else {
+            setState(INVALID);
+        }
     }
-    
+
     /**
      * Stop the instance manager.
      */
     public synchronized void stop() {
-        if (m_state == STOPPED) {
-            return;
-        } // Instance already stopped
-        
+        if (m_state == STOPPED) { return; } // Instance already stopped
 
         setState(INVALID);
-        
+
         if (m_handler != null) {
             m_handler.stop();
         }
-        
+
         // Stop all the handlers
         for (int i = m_handlers.length - 1; i > -1; i--) {
             m_handlers[i].removeInstanceStateListener(this);
@@ -130,13 +125,13 @@
         }
 
         m_state = STOPPED;
-        if (m_instanceListeners != null) {
-            for (int i = 0; i < m_instanceListeners.size(); i++) {
-                ((InstanceStateListener) m_instanceListeners.get(i)).stateChanged(this, STOPPED);
+        if (m_listeners != null) {
+            for (int i = 0; i < m_listeners.size(); i++) {
+                ((InstanceStateListener) m_listeners.get(i)).stateChanged(this, STOPPED);
             }
         }
     }
-    
+
     /** 
      * Dispose the instance.
      * @see org.apache.felix.ipojo.ComponentInstance#dispose()
@@ -145,7 +140,7 @@
         super.dispose();
         m_handler = null;
     }
-    
+
     /**
      * Kill the current instance.
      * Only the factory of this instance can call this method.
@@ -153,6 +148,33 @@
     protected void kill() {
         super.dispose();
         m_handler = null;
+    }
+
+    /**
+     * State Change listener callback.
+     * This method is notified at each time a plugged handler becomes invalid.
+     * @param instance : changing instance 
+     * @param newState : new state
+     * @see org.apache.felix.ipojo.InstanceStateListener#stateChanged(org.apache.felix.ipojo.ComponentInstance, int)
+     */
+    public synchronized void stateChanged(ComponentInstance instance, int newState) {
+        if (m_state <= STOPPED) { return; }
+
+        // Update the component state if necessary
+        if (newState == INVALID && m_state == VALID) {
+            // Need to update the state to UNRESOLVED
+            setState(INVALID);
+            return;
+        }
+        if (newState == VALID && m_state == INVALID) {
+            // An handler becomes valid => check if all handlers are valid
+            if (!m_handler.getValidity()) { return; }
+            for (int i = 0; i < m_handlers.length; i++) {
+                if (m_handlers[i].getState() != VALID) { return; }
+            }
+            setState(VALID);
+            return;
+        }
     }
 
 }

Modified: felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/IPojoContext.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/IPojoContext.java?rev=642265&r1=642264&r2=642265&view=diff
==============================================================================
--- felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/IPojoContext.java (original)
+++ felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/IPojoContext.java Fri Mar 28 08:33:36 2008
@@ -54,25 +54,24 @@
     /**
      * Constructor. Used when the service context = the bundle context
      * 
-     * @param bc : bundle context
+     * @param context : bundle context
      */
-    public IPojoContext(BundleContext bc) {
-        m_bundleContext = bc;
+    public IPojoContext(BundleContext context) {
+        m_bundleContext = context;
     }
 
     /**
      * Constructor. Used when the service context and the bundle context are
      * different
      * 
-     * @param bc : bundle context
-     * @param sc : service context
+     * @param bundleContext : bundle context
+     * @param serviceContext : service context
      */
-    public IPojoContext(BundleContext bc, ServiceContext sc) {
-        m_bundleContext = bc;
-        m_serviceContext = sc;
+    public IPojoContext(BundleContext bundleContext, ServiceContext serviceContext) {
+        m_bundleContext = bundleContext;
+        m_serviceContext = serviceContext;
     }
 
-   
     /**
      * Add a bundle listener.
      * @param listener : the listener to add
@@ -119,7 +118,6 @@
         }
     }
 
-
     /**
      * Create a Filter object.
      * @param filter : the string form of the LDAP filter to create
@@ -158,12 +156,12 @@
 
     /**
      * Get the bundle object with the given id.
-     * @param id : bundle id
+     * @param bundleId : bundle id
      * @return the bundle object
      * @see org.osgi.framework.BundleContext#getBundle(long)
      */
-    public Bundle getBundle(long id) {
-        return m_bundleContext.getBundle(id);
+    public Bundle getBundle(long bundleId) {
+        return m_bundleContext.getBundle(bundleId);
     }
 
     /**
@@ -175,7 +173,6 @@
         return m_bundleContext.getBundles();
     }
 
-
     /**
      * Get a data file.
      * @param filename : File name.
@@ -340,7 +337,7 @@
             return m_serviceContext.ungetService(reference);
         }
     }
-    
+
     /**
      * Get the global context, i.e. the bundle context of the factory.
      * @return the global bundle context.
@@ -348,15 +345,12 @@
     public BundleContext getGlobalContext() {
         return m_bundleContext;
     }
-    
+
     /**
      * Get the service context, i.e. the composite context.
      * @return the service context.
      */
     public ServiceContext getServiceContext() {
-        if (m_serviceContext == null) {
-            return this;
-        }
         return m_serviceContext;
     }
 

Modified: felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/InstanceCreator.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/InstanceCreator.java?rev=642265&r1=642264&r2=642265&view=diff
==============================================================================
--- felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/InstanceCreator.java (original)
+++ felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/InstanceCreator.java Fri Mar 28 08:33:36 2008
@@ -18,208 +18,204 @@
  */
 package org.apache.felix.ipojo;
 
+import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Dictionary;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
 
 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.InvalidSyntaxException;
-import org.osgi.framework.ServiceReference;
 
 /**
- * An instance creator aims to create instances and to track their factories.
- * It's allow to create instance from outside factories.
- * 
+ * An instance creator aims to create instances and to track their factories. It's allow to create instance from outside factories.
  * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
  */
-public class InstanceCreator implements TrackerCustomizer, FactoryStateListener {
-    /**
-     * Bundle Context.
-     */
-    private BundleContext m_context;
+public class InstanceCreator implements FactoryStateListener {
 
     /**
      * Logger to log messages if error occurs.
      */
     private Logger m_logger;
-    
+
     /**
-     * Private factories.
+     * Configurations to create and maintains.
      */
-    private ComponentFactory[] m_factories;
+    private List m_idle = new ArrayList();
 
     /**
-     * This structure aims to manage a configuration. It stores all necessary
-     * information to create an instance and to track the factory.
+     * Map storing created instance. [AbstractFactory, List [ManagedInstance]]
      */
-    private class ManagedConfiguration {
-        /**
-         * Configuration of the instance to create.
-         */
-        private Dictionary m_configuration;
+    private Map m_attached = new HashMap();
 
-        /**
-         * Factory name.
-         */
-        private String m_factoryName;
+    /**
+     * Abstract Factory list.
+     */
+    private List m_factories = new ArrayList();
 
-        /**
-         * Created instance.
-         */
-        private ComponentInstance m_instance;
+    /**
+     * Constructor.
+     * @param context : iPOJO bundle context.
+     */
+    public InstanceCreator(BundleContext context) {
+        m_logger = new Logger(context, "iPOJO Instance Creator");
+    }
 
-        /**
-         * Constructor.
-         * 
-         * @param conf : the configuration to create.
-         */
-        ManagedConfiguration(Dictionary conf) {
-            m_configuration = conf;
+    /**
+     * Add an instance to manage.
+     * @param instance : instance configuration
+     * @param bundle : bundle id declaring the instance
+     */
+    synchronized void addInstance(Dictionary instance, long bundle) {
+        ManagedInstance managed = new ManagedInstance(instance, bundle);
+        for (int i = 0; i < m_factories.size(); i++) {
+            IPojoFactory factory = (IPojoFactory) m_factories.get(i);
+            if (factory.getState() == Factory.VALID && managed.match(factory)) {
+                managed.create(factory);
+                List list = (List) m_attached.get(factory);
+                if (list == null) {
+                    list = new ArrayList();
+                    list.add(managed);
+                    m_attached.put(factory, list);
+                    // Subscribe to the factory state change
+                    factory.addFactoryStateListener(this);
+                } else {
+                    list.add(managed);
+                }
+                return;
+            }
         }
+        // If there is no matching factory, add the instance to the idle list
+        m_idle.add(managed);
+    }
 
-        /**
-         * Return the managed configuration.
-         * @return the configuration.
-         */
-        Dictionary getConfiguration() {
-            return m_configuration;
+    /**
+     * Dispose and stop to manage all instances declared by the given bundle.
+     * @param bundle : bundle.
+     */
+    void removeInstancesFromBundle(long bundle) {
+        // Disposes instance from attached instances
+        Collection col = m_attached.keySet();
+        Iterator iterator = col.iterator();
+        List instanceToRemove = new ArrayList();
+        List factoryToRemove = new ArrayList();
+        while (iterator.hasNext()) {
+            IPojoFactory factory = (IPojoFactory) iterator.next();
+            List list = (List) m_attached.get(factory);
+            for (int i = 0; i < list.size(); i++) {
+                ManagedInstance managed = (ManagedInstance) list.get(i);
+                if (managed.m_bundleId == bundle) {
+                    managed.dispose();
+                    instanceToRemove.add(managed);
+                }
+            }
+            if (!instanceToRemove.isEmpty()) {
+                list.removeAll(instanceToRemove);
+                if (list.isEmpty()) {
+                    factory.removeFactoryStateListener(this);
+                    factoryToRemove.add(factory);
+                }
+            }
         }
 
-        /**
-         * Return the used factory name.
-         * @return the factory
-         */
-        String getFactory() {
-            return m_factoryName;
+        for (int i = 0; i < factoryToRemove.size(); i++) {
+            m_attached.remove(factoryToRemove.get(i));
         }
 
-        /**
-         * Return the created instance.
-         * @return the instance (or null if no instance are created).
-         */
-        ComponentInstance getInstance() {
-            return m_instance;
+        // Delete idle instances
+        instanceToRemove.clear();
+        for (int i = 0; i < m_idle.size(); i++) {
+            ManagedInstance managed = (ManagedInstance) m_idle.get(i);
+            if (managed.m_bundleId == bundle) {
+                instanceToRemove.add(managed);
+            }
         }
+        m_idle.removeAll(instanceToRemove);
+    }
 
-        /**
-         * Set the factory name.
-         * 
-         * @param name : the factory name.
-         */
-        void setFactory(String name) {
-            m_factoryName = name;
+    /**
+     * A new factory appears.
+     * @param factory : the new factory.
+     */
+    public synchronized void addFactory(IPojoFactory factory) {
+        List createdInstances = new ArrayList(1);
+        m_factories.add(factory);
+        for (int i = 0; i < m_idle.size(); i++) {
+            ManagedInstance managed = (ManagedInstance) m_idle.get(i);
+            if (managed.match(factory)) {
+                // We have to subscribe to the factory.
+                factory.addFactoryStateListener(this);
+                if (factory.getState() == Factory.VALID) {
+                    managed.create(factory);
+                    List list = (List) m_attached.get(factory);
+                    if (list == null) {
+                        list = new ArrayList();
+                        list.add(managed);
+                        m_attached.put(factory, list);
+                    } else {
+                        list.add(managed);
+                    }
+                    createdInstances.add(managed);
+                }
+            }
         }
-
-        /**
-         * Set the instance object.
-         * 
-         * @param instance : the instance
-         */
-        void setInstance(ComponentInstance instance) {
-            m_instance = instance;
+        if (!createdInstances.isEmpty()) {
+            m_idle.removeAll(createdInstances);
         }
     }
 
     /**
-     * Configurations to create and maintains.
+     * A factory is leaving.
+     * @param factory : the leaving factory
      */
-    private ManagedConfiguration[] m_configurations = new ManagedConfiguration[0];
+    void removeFactory(IPojoFactory factory) {
+        factory.removeFactoryStateListener(this);
+        m_factories.remove(factory);
+        onInvalidation(factory);
+        m_attached.remove(factory);
+    }
 
     /**
-     * Service Tracker tracking factories.
+     * The given factory becomes valid.
+     * @param factory : the factory becoming valid.
      */
-    private Tracker m_tracker;
-
-    /**
-     * Constructor.
-     * 
-     * @param context : the bundle context.
-     * @param configurations : configuration set to create and maintain.
-     * @param factories : private factories.
-     */
-    public InstanceCreator(BundleContext context, Dictionary[] configurations, ComponentFactory[] factories) {
-        m_context = context;
-        m_logger = new Logger(context, "InstanceCreator" + context.getBundle().getBundleId(), Logger.WARNING);
-        
-        m_configurations = new ManagedConfiguration[configurations.length];
-        m_factories = factories;
-       
-        for (int i = 0; i < configurations.length; i++) {
-            ManagedConfiguration conf = new ManagedConfiguration(configurations[i]);
-            m_configurations[i] = conf;
-            // Get the component type name :
-            String componentType = (String) conf.getConfiguration().get("component");
-
-            boolean found = false;
-            for (int j = 0; m_factories != null && !found && j < m_factories.length; j++) {
-                if (m_factories[j].m_state == Factory.VALID && (m_factories[j].getName().equals(componentType) || (m_factories[j].getComponentClassName() != null && m_factories[j].getComponentClassName().equals(componentType)))) {
-                    createInstance(m_factories[j], conf);
-                    found = true;
+    private void onValidation(IPojoFactory factory) {
+        List toRemove = new ArrayList();
+        for (int i = 0; i < m_idle.size(); i++) {
+            ManagedInstance managed = (ManagedInstance) m_idle.get(i);
+            if (managed.match(factory)) {
+                managed.create(factory);
+                List list = (List) m_attached.get(factory);
+                if (list == null) {
+                    list = new ArrayList();
+                    list.add(managed);
+                    m_attached.put(factory, list);
+                } else {
+                    list.add(managed);
                 }
+                toRemove.add(managed);
             }
         }
-        
-        for (int i = 0; m_factories != null && i < m_factories.length; i++) {
-            m_factories[i].addFactoryStateListener(this);
-        }
-       
-        
-        String filter = "(&(objectclass=" + Factory.class.getName() + ")(factory.state=1))";
-        try {
-            m_tracker = new Tracker(m_context, m_context.createFilter(filter), this);
-            m_tracker.open();
-        } catch (InvalidSyntaxException e) {
-            e.printStackTrace();
-            return;
-        } 
-    }
-
-    /**
-     * Create an instance using the given factory and the given configuration.
-     * 
-     * @param fact : the factory name to used.
-     * @param config : the configuration.
-     */
-    private void createInstance(Factory fact, ManagedConfiguration config) {
-        Dictionary conf = config.getConfiguration();
-        try {
-            config.setInstance(fact.createComponentInstance(conf));
-            config.setFactory(fact.getName());
-        } catch (UnacceptableConfiguration e) {
-            m_logger.log(Logger.ERROR, "A factory is available for the configuration but the configuration is not acceptable", e);
-            stop();
-        } catch (MissingHandlerException e) {
-            m_logger.log(Logger.ERROR, "The instance creation has failed, at least one handler is missing", e);
-            stop();
-        } catch (ConfigurationException e) {
-            m_logger.log(Logger.ERROR, "The instance creation has failed, an error during the configuration has occured", e);
-            stop();
+        if (!toRemove.isEmpty()) {
+            m_idle.removeAll(toRemove);
         }
     }
 
     /**
-     * Stop all created instances.
+     * The given factory becomes invalid.
+     * @param factory : factory which becomes invalid.
      */
-    public synchronized void stop() {
-        m_tracker.close();
-        
-        for (int i = 0; m_factories != null && i < m_factories.length; i++) {
-            m_factories[i].removeFactoryStateListener(this);
-        }
-        
-        for (int i = 0; i < m_configurations.length; i++) {
-            if (m_configurations[i].getInstance() != null) {
-                m_configurations[i].getInstance().dispose();
+    private void onInvalidation(IPojoFactory factory) {
+        List instances = (List) m_attached.remove(factory);
+        if (instances != null) {
+            for (int i = 0; i < instances.size(); i++) {
+                ManagedInstance managed = (ManagedInstance) instances.get(i);
+                managed.dispose();
+                m_idle.add(managed);
             }
-            m_configurations[i].setInstance(null);
-            m_configurations[i].setFactory(null);
         }
-        
-        m_factories = null;
-        m_tracker = null;
-        m_logger = null;
-        m_configurations = null;
     }
 
     /**
@@ -230,88 +226,116 @@
      */
     public void stateChanged(Factory factory, int newState) {
         if (newState == Factory.VALID) {
-            for (int i = 0; i < m_configurations.length; i++) {
-                if (m_configurations[i].getInstance() == null
-                        && (m_configurations[i].getConfiguration().get("component").equals(factory.getName()) || m_configurations[i].getConfiguration().get(
-                                "component").equals(((ComponentFactory) factory).getComponentClassName()))) {
-                    Factory fact = factory;
-                    createInstance(fact, m_configurations[i]);
-                }
-            }
-            return;
+            onValidation((IPojoFactory) factory);
         } else {
-            // newState == INVALID
-            for (int i = 0; i < m_configurations.length; i++) {
-                if (m_configurations[i].getInstance() != null && m_configurations[i].getFactory().equals(factory.getName())) {
-                    m_configurations[i].setInstance(null);
-                    m_configurations[i].setFactory(null);
-                }
-            }
-            return;
+            onInvalidation((IPojoFactory) factory);
         }
     }
 
     /**
-     * A new factory has been detected.
-     * @param ref : the factory service reference.
-     * @return true if the factory can be used to create a managed instance.
-     * @see org.apache.felix.ipojo.util.TrackerCustomizer#addingService(org.osgi.framework.ServiceReference)
-     */
-    public boolean addingService(ServiceReference ref) {
-        String factoryName = (String) ref.getProperty("factory.name");
-        String componentClass = (String) ref.getProperty("component.class");
-        boolean isValid = ((String) ref.getProperty("factory.state")).equals("" + Factory.VALID); 
-        Factory fact = (Factory) m_tracker.getService(ref);
-
-        boolean used = false;
-        if (isValid) {
-            for (int i = 0; i < m_configurations.length; i++) {
-                if (m_configurations[i].getInstance() == null
-                        && (m_configurations[i].getConfiguration().get("component").equals(factoryName) || m_configurations[i].getConfiguration().get("component").equals(componentClass))) {
-                    createInstance(fact, m_configurations[i]);
-                    used = true;
+     * This structure aims to manage a configuration. It stores all necessary information to create an instance and to track the factory.
+     */
+    private class ManagedInstance {
+        /**
+         * Configuration of the instance to create.
+         */
+        private Dictionary m_configuration;
+
+        /**
+         * Bundle which create the instance.
+         */
+        private long m_bundleId;
+
+        /**
+         * Factory used to create the instance.
+         */
+        private IPojoFactory m_factory;
+
+        /**
+         * Created instance.
+         */
+        private ComponentInstance m_instance;
+
+        /**
+         * Constructor.
+         * @param conf : the configuration to create.
+         * @param bundle : the bundle in which the instance is declared.
+         */
+        ManagedInstance(Dictionary conf, long bundle) {
+            m_configuration = conf;
+            m_bundleId = bundle;
+        }
+
+        /**
+         * Return the used factory name.
+         * @return the factory
+         */
+        IPojoFactory getFactory() {
+            return m_factory;
+        }
+
+        /**
+         * Return the created instance.
+         * @return the instance (or null if no instance are created).
+         */
+        ComponentInstance getInstance() {
+            return m_instance;
+        }
+
+        /**
+         * Test if the given factory match with the factory required by this instance. A factory matches if its name or its class name is equals to
+         * the 'component' property of the instance. Then the acceptability of the configuration is checked.
+         * @param factory : the factory to confront against the current instance.
+         * @return true if the factory match.
+         */
+        public boolean match(IPojoFactory factory) {
+            // Test factory name (and classname)
+            String component = (String) m_configuration.get("component");
+            if (factory.getName().equals(component) || factory.getClassName().equalsIgnoreCase(component)) {
+                // Test factory accessibility
+                if (factory.m_isPublic || factory.getBundleContext().getBundle().getBundleId() == m_bundleId) {
+                    // Test the configuration validity.
+                    if (factory.isAcceptable(m_configuration)) {
+                        return true;
+                    } else {
+                        m_logger.log(Logger.ERROR, "An instance can be bound to a matching factory, however the configuration seems unacceptable : "
+                                + m_configuration);
+                    }
                 }
             }
+            return false;
         }
-        return used;
-    }
-    
-    /**
-     * A matching service has been added to the tracker.
-     * Nothing to do, as all action are computed in the adding method.
-     * @param ref : added reference.
-     * @see org.apache.felix.ipojo.util.TrackerCustomizer#addedService(org.osgi.framework.ServiceReference)
-     */
-    public void addedService(ServiceReference ref) { }
-
-    /**
-     * A used factory is modified.
-     * @param ref : modified reference.
-     * @param obj : factory object.
-     * @see org.apache.felix.ipojo.util.TrackerCustomizer#modifiedService(org.osgi.framework.ServiceReference, java.lang.Object)
-     */
-    public void modifiedService(ServiceReference ref, Object obj) { }
-
-    /**
-     * A used factory disappears.
-     * All created instance are disposed.
-     * @param ref : service reference.
-     * @param obj : factory object.
-     * @see org.apache.felix.ipojo.util.TrackerCustomizer#removedService(org.osgi.framework.ServiceReference, java.lang.Object)
-     */
-    public void removedService(ServiceReference ref, Object obj) {
-        String name = (String) ref.getProperty("factory.name");
-        if (name == null) { return; }
-        for (int i = 0; i < m_configurations.length; i++) {
-            if (m_configurations[i].getFactory() != null && m_configurations[i].getFactory().equals(name)) {
-                if (m_configurations[i].getInstance() != null) {
-                    m_configurations[i].getInstance().dispose();
-                    m_configurations[i].setInstance(null);
-                }
-                m_configurations[i].setFactory(null);
+
+        /**
+         * Create the instance by using the given factory.
+         * @param factory : the factory to use to create the instance. The factory must match.
+         */
+        public void create(IPojoFactory factory) {
+            try {
+                m_factory = factory;
+                m_instance = m_factory.createComponentInstance(m_configuration);
+            } catch (UnacceptableConfiguration e) {
+                m_logger.log(Logger.ERROR, "A matching factory was found for " + m_configuration + ", but the instantiation failed : "
+                        + e.getMessage());
+            } catch (MissingHandlerException e) {
+                m_logger.log(Logger.ERROR, "A matching factory was found for " + m_configuration + ", but the instantiation failed : "
+                        + e.getMessage());
+            } catch (ConfigurationException e) {
+                m_logger.log(Logger.ERROR, "A matching factory was found for " + m_configuration + ", but the instantiation failed : "
+                        + e.getMessage());
+            }
+        }
+
+        /**
+         * Dispose the current instance.
+         */
+        public void dispose() {
+            if (m_instance != null) {
+                m_instance.dispose();
             }
+            m_instance = null;
+            m_factory = null;
         }
-        m_tracker.ungetService(ref);
     }
 
 }