felix-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From rickh...@apache.org
Subject svn commit: r447121 [2/3] - in /incubator/felix/trunk/scr/src/main/java/org/apache/felix/scr: ComponentManagerImpl.java ComponentMetadata.java PropertyMetadata.java
Date Sun, 17 Sep 2006 19:43:51 GMT

Modified: incubator/felix/trunk/scr/src/main/java/org/apache/felix/scr/ComponentManagerImpl.java
URL: http://svn.apache.org/viewvc/incubator/felix/trunk/scr/src/main/java/org/apache/felix/scr/ComponentManagerImpl.java?view=diff&rev=447121&r1=447120&r2=447121
==============================================================================
--- incubator/felix/trunk/scr/src/main/java/org/apache/felix/scr/ComponentManagerImpl.java (original)
+++ incubator/felix/trunk/scr/src/main/java/org/apache/felix/scr/ComponentManagerImpl.java Sun Sep 17 12:43:50 2006
@@ -1,1193 +1,1193 @@
-/*
- *   Copyright 2006 The Apache Software Foundation
- *
- *   Licensed 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.scr;
-
-import java.lang.reflect.*;
-import java.util.*;
-
-import org.osgi.framework.*;
-import org.osgi.service.component.ComponentContext;
-import org.osgi.service.component.ComponentInstance;
-
-
-/**
- * The default ComponentManager. Objects of this class are responsible for managing
- * implementation object's lifecycle.  
- *
- */
-public class ComponentManagerImpl implements ComponentManager, ComponentInstance
-{
-	// States of the instance manager
-	static final int INSTANCE_CREATING = 0;
-	static final int INSTANCE_CREATED = 1;
-	static final int INSTANCE_VALIDATING = 2;
-	static final int INSTANCE_VALID = 3;
-	static final int INSTANCE_INVALIDATING = 4;
-	static final int INSTANCE_INVALID = 5;
-	static final int INSTANCE_DESTROYING = 6;
-	static final int INSTANCE_DESTROYED = 7;
-		
-
-    static final String m_states[]={"CREATING","CREATED",
-    								"VALIDATING","VALID",
-    								"INVALIDATING","INVALID",
-    								"DESTROYING","DESTROYED"
-                                    };
-
-    // The state of this instance manager
+/*
+ *   Copyright 2006 The Apache Software Foundation
+ *
+ *   Licensed 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.scr;
+
+import java.lang.reflect.*;
+import java.util.*;
+
+import org.osgi.framework.*;
+import org.osgi.service.component.ComponentContext;
+import org.osgi.service.component.ComponentInstance;
+
+
+/**
+ * The default ComponentManager. Objects of this class are responsible for managing
+ * implementation object's lifecycle.  
+ *
+ */
+public class ComponentManagerImpl implements ComponentManager, ComponentInstance
+{
+	// States of the instance manager
+	static final int INSTANCE_CREATING = 0;
+	static final int INSTANCE_CREATED = 1;
+	static final int INSTANCE_VALIDATING = 2;
+	static final int INSTANCE_VALID = 3;
+	static final int INSTANCE_INVALIDATING = 4;
+	static final int INSTANCE_INVALID = 5;
+	static final int INSTANCE_DESTROYING = 6;
+	static final int INSTANCE_DESTROYED = 7;
+		
+
+    static final String m_states[]={"CREATING","CREATED",
+    								"VALIDATING","VALID",
+    								"INVALIDATING","INVALID",
+    								"DESTROYING","DESTROYED"
+                                    };
+
+    // The state of this instance manager
     private int m_state = INSTANCE_CREATING;
 
     // The metadata
-    private ComponentMetadata m_componentMetadata;
-
-    // The object that implements the service and that is bound to other services
-    private Object m_implementationObject = null;
-
-    // The dependency managers that manage every dependency
-    private List m_dependencyManagers = new ArrayList();
-
-    // The ServiceRegistration
+    private ComponentMetadata m_componentMetadata;
+
+    // The object that implements the service and that is bound to other services
+    private Object m_implementationObject = null;
+
+    // The dependency managers that manage every dependency
+    private List m_dependencyManagers = new ArrayList();
+
+    // The ServiceRegistration
     private ServiceRegistration m_serviceRegistration = null;
 
     // A reference to the GenericActivator
     private GenericActivator m_activator = null;
 
-    // The context that will be passed to the implementationObject
+    // The context that will be passed to the implementationObject
     private ComponentContext m_componentContext = null;
-    
-    // In case of a delayed component, this holds a reference to the factory
-    private DelayedComponentServiceFactory m_delayedComponentServiceFactory;
-    
-    /**
-     * The constructor receives both the activator and the metadata
-     * 
-     * @param activator
-     * @param metadata
-     */
-    ComponentManagerImpl(GenericActivator activator,ComponentMetadata metadata)
-    {
-    	// Store the activator reference
-        m_activator = activator;
-
-        // Store the metadata reference
-        m_componentMetadata = metadata;
-    }
-    
-    /**
-     * Enable this component
-     * 
-     * @return true if enabling was successful
-     */
-    public boolean enable() {
-    	
-    	GenericActivator.trace("Enabling component", m_componentMetadata);
-    	
-    	try
-    	{
-	        // If this component has got dependencies, create dependency managers for each one of them.
-	        if (m_componentMetadata.getDependencies().size() != 0)
-	        {
-	            Iterator dependencyit = m_componentMetadata.getDependencies().iterator();
-	
-	            while(dependencyit.hasNext())
-	            {
-	                ReferenceMetadata currentdependency = (ReferenceMetadata)dependencyit.next();
-	
-	                DependencyManager depmanager = new DependencyManager(currentdependency);
-	
-	                m_dependencyManagers.add(depmanager);
-	
-	                // Register the dependency managers as listeners to service events so that they begin
-	                // to manage the dependency autonomously
-	                m_activator.getBundleContext().addServiceListener(depmanager,depmanager.m_dependencyMetadata.getTarget());
-	            }
-	        }
-	
-	        // TODO: create the context
-	        //m_sbcontext = new ServiceBinderContextImpl(this);
-	
-	        // Add this instance manager to the Generic activator list
-	        //m_activator.addInstanceManager(this);
-	        
-	
-	        setState(INSTANCE_CREATED);
-	        
-	        activate();
-	        
-	        return true;
-    	}
-    	catch(Exception ex)
-    	{
-    		// TODO: Log this error
-    		return false;
-    	}
-    }
-
-    /**
-    * Activate this Instance manager.
-    * 
-    * 112.5.6 Activating a component configuration consists of the following steps
-    *   1. Load the component implementation class
-    *   2. Create the component instance and component context
-    *   3. Bind the target services
-    *   4. Call the activate method, if present
-    *   [5. Register provided services]
-    */
-    synchronized private void activate()
-    {
-        // CONCURRENCY NOTE: This method is called either by the enable() method or by the dependency
-    	// managers.    	
-    	if (m_state != INSTANCE_INVALID && m_state !=INSTANCE_CREATED) {
-    		// This state can only be entered from the CREATED or INVALID states
-    		return;
-    	}
-
-        setState(INSTANCE_VALIDATING);
-
-        // Before creating the implementation object, we are going to
-        // test if all the mandatory dependencies are satisfied
-        Iterator it = m_dependencyManagers.iterator();
-
-        while (it.hasNext())
-        {
-            // It is not possible to call the isValid method yet in the DependencyManagers
-            // since they have not been initialized yet, but they can't be initialized yet
-            // because the implementationObject has not been created yet.
-            // This test is necessary, because we don't want to instantiate
-            // the implementationObject if the dependency managers aren't valid.
-            DependencyManager dm = (DependencyManager)it.next();
-            if (dm.getRequiredServiceRefs() == null && dm.m_dependencyMetadata.isOptional() == false)
-            {
-                setState(INSTANCE_INVALID);
-                return;
-            }
-        }
-        
-        // 1. Load the component implementation class
-        // 2. Create the component instance and component context
-        // If the component is not immediate, this is not done at this moment
-        if( m_componentMetadata.isImmediate() == true )
-        {
-        	//GenericActivator.trace("Loading implementation class and creating instance for component '"+m_componentMetadata.getName()+"'");
-        	try
-	        {
-	        	// 112.4.4 The class is retrieved with the loadClass method of the component's bundle
-	            Class c = m_activator.getBundleContext().getBundle().loadClass(m_componentMetadata.getImplementationClassName());
-	            
-	            // 112.4.4 The class must be public and have a public constructor without arguments so component instances
-	            // may be created by the SCR with the newInstance method on Class
-	            m_componentContext = new ComponentContextImpl(null);
-	            m_implementationObject = c.newInstance();
-	        }
-	        catch (Exception ex)
-	        {
-	            // TODO: manage this exception when implementation object cannot be created
-	            GenericActivator.exception("Error during instantiation", m_componentMetadata, ex);
-	            deactivate();
-	            //invalidate();
-	            return;
-	        }
-        } else {
-        	m_delayedComponentServiceFactory = new DelayedComponentServiceFactory();
-        }
-        
-        // 3. Bind the target services
-        it = m_dependencyManagers.iterator();
-
-        //GenericActivator.trace("Binding target services for component '"+m_componentMetadata.getName()+"'");
-        
-        while (it.hasNext())
-        {
-            DependencyManager dm = (DependencyManager)it.next();
-            
-            // if any of the dependency managers is unable to bind (it is invalid), the component is deactivated
-            if (dm.bind() == false)
-            {
-            	deactivate();
-                return;
-            }
-        }
-        
-        //GenericActivator.trace("Calling activate for component '"+m_componentMetadata.getName()+"'");
-        
-        // 4. Call the activate method, if present
-	        // We need to check if we are still validating because it is possible that when we
-	        // registered the service above our thread causes an instance to become valid which
-	        // then registered a service that then generated an event that we needed that
-	        // caused validate() to be called again, thus if we are not still VALIDATING, it
-	        // means we are already VALID.
-        if ( m_componentMetadata.isImmediate() == true && m_state == INSTANCE_VALIDATING)
-        {
-            // Search for the activate method
-        	try {
-                Method activateMethod = getMethod(m_implementationObject.getClass(), "activate", new Class[]{ComponentContext.class});
-        		activateMethod.invoke(m_implementationObject, new Object[]{m_componentContext});
-        	}
-        	catch(NoSuchMethodException ex) {        		
-        		// We can safely ignore this one
-        		GenericActivator.trace("activate() method not implemented", m_componentMetadata);
-        	}
-        	catch(IllegalAccessException ex) {
-        		// TODO: Log this exception?
-        		GenericActivator.trace("activate() method cannot be called", m_componentMetadata);
-        	}
-        	catch(InvocationTargetException ex) {
-        		// TODO: 112.5.8 If the activate method throws an exception, SCR must log an error message
-        		// containing the exception with the Log Service
-        		GenericActivator.exception("The activate method has thrown an exception", m_componentMetadata, ex.getTargetException());
-        	}
-        }
-        
-        // Validation occurs before the services are provided, otherwhise the service provider's service may be called
-        // by a service requester while it is still VALIDATING
-        setState(INSTANCE_VALID);
-        
-        // 5. Register provided services
-        if(m_componentMetadata.getServiceMetadata() != null)
-        {
-            GenericActivator.trace("registering services", m_componentMetadata);
-
-        	if( m_componentMetadata.isImmediate() == true ) {
-	        	// In the case the component is immediate, the implementation object is registered
-	        	m_serviceRegistration = m_activator.getBundleContext().registerService(m_componentMetadata.getServiceMetadata().getProvides(), m_implementationObject, m_componentMetadata.getProperties());
-	        }else {
-	        	// In the case the component is delayed, a factory is registered
-	        	m_serviceRegistration = m_activator.getBundleContext().registerService(m_componentMetadata.getServiceMetadata().getProvides(), m_delayedComponentServiceFactory, m_componentMetadata.getProperties());
-	        }
-        }
-    }
-    
-    /**
-     * This method deactivates the manager, performing the following steps
-     * 
-     * [0. Remove published services from the registry]
-     * 1. Call the deactivate() method, if present
-     * 2. Unbind any bound services
-     * 3. Release references to the component instance and component context 
-    **/
-    synchronized private void deactivate()
-    {
-    	// CONCURRENCY NOTE: This method may be called either from application code or by the dependency managers
-    	if (m_state != INSTANCE_VALID && m_state != INSTANCE_VALIDATING && m_state != INSTANCE_DESTROYING) {
-    		return;
-    	}
-
-    	// In case the instance is valid when this is called, the manager is set to an invalidating state
-        if (m_state != INSTANCE_DESTROYING)
-        {
-            setState(INSTANCE_INVALIDATING);
-        }
-    	
-        // 0.- Remove published services from the registry
-        if(m_serviceRegistration != null)
-        {
-	        m_serviceRegistration.unregister();
-	        m_serviceRegistration = null;
-
-	        GenericActivator.trace("unregistering the services", m_componentMetadata);
-	    }
-
-        // 1.- Call the deactivate method, if present	    
-        // Search the deactivate method
-		try {
-			// It is necessary to check that the implementation Object is not null. This may happen if the component
-			// is delayed and its service was never requested.
-			if(m_implementationObject != null)
-			{
-				Method activateMethod = getMethod(m_implementationObject.getClass(), "deactivate", new Class[]{ComponentContext.class});
-				activateMethod.invoke(m_implementationObject, new Object[]{m_componentContext});				
-			}
-		}
-		catch(NoSuchMethodException ex) {
-			// We can safely ignore this one
-			GenericActivator.trace("deactivate() method is not implemented", m_componentMetadata);
-		}
-		catch(IllegalAccessException ex) {
-			// Ignored, but should it be logged?
-			GenericActivator.trace("deactivate() method cannot be called", m_componentMetadata);
-		}
-		catch(InvocationTargetException ex) {
-			// TODO: 112.5.12 If the deactivate method throws an exception, SCR must log an error message
-			// containing the exception with the Log Service
-			GenericActivator.exception("The deactivate method has thrown and exception", m_componentMetadata, ex);
-		}
-
-        // 2. Unbind any bound services
-        Iterator it = m_dependencyManagers.iterator();
-
-        while (it.hasNext())
-        {
-            DependencyManager dm = (DependencyManager)it.next();
-            dm.unbind();
-        }
-
-        // 3. Release references to the component instance and component context
-        m_implementationObject = null;
-        m_componentContext = null;
-        m_delayedComponentServiceFactory = null;
-
-        //GenericActivator.trace("InstanceManager from bundle ["+ m_activator.getBundleContext().getBundle().getBundleId() + "] was invalidated.");
-
-        if (m_state != INSTANCE_DESTROYING)
-        {
-            setState(INSTANCE_INVALID);
-        }
-    }
-
-    /**
-     * 
-     */
-    public synchronized void dispose()
-    {
-        // CONCURRENCY NOTE: This method is only called from the GenericActivator or by application logic
-    	// but not by the dependency managers
-
-        // Theoretically this should never be in any state other than VALID or INVALID,
-        // because validate is called right after creation.
-        if (m_state != INSTANCE_VALID && m_state != INSTANCE_INVALID)
-        {
-            return;
-        }
-
-        boolean deactivationRequired = (m_state == INSTANCE_VALID);
-
-        setState(INSTANCE_DESTROYING);
-
-        // Stop the dependency managers to listen to events...
-        Iterator it = m_dependencyManagers.iterator();
-
-        while (it.hasNext())
-        {
-            DependencyManager dm = (DependencyManager)it.next();
-            m_activator.getBundleContext().removeServiceListener(dm);
-        }
-
-        // in case the component is disposed when it was VALID, it is necessary to deactivate it first.
-        if (deactivationRequired)
-        {
-            deactivate();
-        }
-
-        m_dependencyManagers.clear();
-
-        setState(INSTANCE_DESTROYED);
-
-        m_activator = null;
-    }
-
-    //**********************************************************************************************************
-    
-    /**
-    * Get the object that is implementing this descriptor
-    *
-    * @return the object that implements the services
-    */
-    public Object getInstance() {
-        return m_implementationObject;
-    }
-
-    /**
-     * 
-     */
-    public ComponentMetadata getComponentMetadata() {
-    	return m_componentMetadata;
-    }
-    
-    /**
-     * sets the state of the manager
-    **/
-    private synchronized void setState(int newState) {
-    	GenericActivator.trace("State transition : "+m_states[m_state]+" -> "+m_states[newState], m_componentMetadata);
-    	
-        m_state = newState;
-        
-        
-
-        if(m_state == INSTANCE_CREATED || m_state == INSTANCE_VALID || m_state == INSTANCE_INVALID || m_state == INSTANCE_DESTROYED)
-        {
-            //m_activator.fireInstanceChangeEvent(new InstanceChangeEvent(this,m_instanceMetadata,m_state));
-        }
+    
+    // In case of a delayed component, this holds a reference to the factory
+    private DelayedComponentServiceFactory m_delayedComponentServiceFactory;
+    
+    /**
+     * The constructor receives both the activator and the metadata
+     * 
+     * @param activator
+     * @param metadata
+     */
+    ComponentManagerImpl(GenericActivator activator,ComponentMetadata metadata)
+    {
+    	// Store the activator reference
+        m_activator = activator;
+
+        // Store the metadata reference
+        m_componentMetadata = metadata;
+    }
+    
+    /**
+     * Enable this component
+     * 
+     * @return true if enabling was successful
+     */
+    public boolean enable() {
+    	
+    	GenericActivator.trace("Enabling component", m_componentMetadata);
+    	
+    	try
+    	{
+	        // If this component has got dependencies, create dependency managers for each one of them.
+	        if (m_componentMetadata.getDependencies().size() != 0)
+	        {
+	            Iterator dependencyit = m_componentMetadata.getDependencies().iterator();
+	
+	            while(dependencyit.hasNext())
+	            {
+	                ReferenceMetadata currentdependency = (ReferenceMetadata)dependencyit.next();
+	
+	                DependencyManager depmanager = new DependencyManager(currentdependency);
+	
+	                m_dependencyManagers.add(depmanager);
+	
+	                // Register the dependency managers as listeners to service events so that they begin
+	                // to manage the dependency autonomously
+	                m_activator.getBundleContext().addServiceListener(depmanager,depmanager.m_dependencyMetadata.getTarget());
+	            }
+	        }
+	
+	        // TODO: create the context
+	        //m_sbcontext = new ServiceBinderContextImpl(this);
+	
+	        // Add this instance manager to the Generic activator list
+	        //m_activator.addInstanceManager(this);
+	        
+	
+	        setState(INSTANCE_CREATED);
+	        
+	        activate();
+	        
+	        return true;
+    	}
+    	catch(Exception ex)
+    	{
+    		// TODO: Log this error
+    		return false;
+    	}
+    }
+
+    /**
+    * Activate this Instance manager.
+    * 
+    * 112.5.6 Activating a component configuration consists of the following steps
+    *   1. Load the component implementation class
+    *   2. Create the component instance and component context
+    *   3. Bind the target services
+    *   4. Call the activate method, if present
+    *   [5. Register provided services]
+    */
+    synchronized private void activate()
+    {
+        // CONCURRENCY NOTE: This method is called either by the enable() method or by the dependency
+    	// managers.    	
+    	if (m_state != INSTANCE_INVALID && m_state !=INSTANCE_CREATED) {
+    		// This state can only be entered from the CREATED or INVALID states
+    		return;
+    	}
+
+        setState(INSTANCE_VALIDATING);
+
+        // Before creating the implementation object, we are going to
+        // test if all the mandatory dependencies are satisfied
+        Iterator it = m_dependencyManagers.iterator();
+
+        while (it.hasNext())
+        {
+            // It is not possible to call the isValid method yet in the DependencyManagers
+            // since they have not been initialized yet, but they can't be initialized yet
+            // because the implementationObject has not been created yet.
+            // This test is necessary, because we don't want to instantiate
+            // the implementationObject if the dependency managers aren't valid.
+            DependencyManager dm = (DependencyManager)it.next();
+            if (dm.getRequiredServiceRefs() == null && dm.m_dependencyMetadata.isOptional() == false)
+            {
+                setState(INSTANCE_INVALID);
+                return;
+            }
+        }
+        
+        // 1. Load the component implementation class
+        // 2. Create the component instance and component context
+        // If the component is not immediate, this is not done at this moment
+        if( m_componentMetadata.isImmediate() == true )
+        {
+        	//GenericActivator.trace("Loading implementation class and creating instance for component '"+m_componentMetadata.getName()+"'");
+        	try
+	        {
+	        	// 112.4.4 The class is retrieved with the loadClass method of the component's bundle
+	            Class c = m_activator.getBundleContext().getBundle().loadClass(m_componentMetadata.getImplementationClassName());
+	            
+	            // 112.4.4 The class must be public and have a public constructor without arguments so component instances
+	            // may be created by the SCR with the newInstance method on Class
+	            m_componentContext = new ComponentContextImpl(null);
+	            m_implementationObject = c.newInstance();
+	        }
+	        catch (Exception ex)
+	        {
+	            // TODO: manage this exception when implementation object cannot be created
+	            GenericActivator.exception("Error during instantiation", m_componentMetadata, ex);
+	            deactivate();
+	            //invalidate();
+	            return;
+	        }
+        } else {
+        	m_delayedComponentServiceFactory = new DelayedComponentServiceFactory();
+        }
+        
+        // 3. Bind the target services
+        it = m_dependencyManagers.iterator();
+
+        //GenericActivator.trace("Binding target services for component '"+m_componentMetadata.getName()+"'");
+        
+        while (it.hasNext())
+        {
+            DependencyManager dm = (DependencyManager)it.next();
+            
+            // if any of the dependency managers is unable to bind (it is invalid), the component is deactivated
+            if (dm.bind() == false)
+            {
+            	deactivate();
+                return;
+            }
+        }
+        
+        //GenericActivator.trace("Calling activate for component '"+m_componentMetadata.getName()+"'");
+        
+        // 4. Call the activate method, if present
+	        // We need to check if we are still validating because it is possible that when we
+	        // registered the service above our thread causes an instance to become valid which
+	        // then registered a service that then generated an event that we needed that
+	        // caused validate() to be called again, thus if we are not still VALIDATING, it
+	        // means we are already VALID.
+        if ( m_componentMetadata.isImmediate() == true && m_state == INSTANCE_VALIDATING)
+        {
+            // Search for the activate method
+        	try {
+                Method activateMethod = getMethod(m_implementationObject.getClass(), "activate", new Class[]{ComponentContext.class});
+        		activateMethod.invoke(m_implementationObject, new Object[]{m_componentContext});
+        	}
+        	catch(NoSuchMethodException ex) {        		
+        		// We can safely ignore this one
+        		GenericActivator.trace("activate() method not implemented", m_componentMetadata);
+        	}
+        	catch(IllegalAccessException ex) {
+        		// TODO: Log this exception?
+        		GenericActivator.trace("activate() method cannot be called", m_componentMetadata);
+        	}
+        	catch(InvocationTargetException ex) {
+        		// TODO: 112.5.8 If the activate method throws an exception, SCR must log an error message
+        		// containing the exception with the Log Service
+        		GenericActivator.exception("The activate method has thrown an exception", m_componentMetadata, ex.getTargetException());
+        	}
+        }
+        
+        // Validation occurs before the services are provided, otherwhise the service provider's service may be called
+        // by a service requester while it is still VALIDATING
+        setState(INSTANCE_VALID);
+        
+        // 5. Register provided services
+        if(m_componentMetadata.getServiceMetadata() != null)
+        {
+            GenericActivator.trace("registering services", m_componentMetadata);
+
+        	if( m_componentMetadata.isImmediate() == true ) {
+	        	// In the case the component is immediate, the implementation object is registered
+	        	m_serviceRegistration = m_activator.getBundleContext().registerService(m_componentMetadata.getServiceMetadata().getProvides(), m_implementationObject, m_componentMetadata.getProperties());
+	        }else {
+	        	// In the case the component is delayed, a factory is registered
+	        	m_serviceRegistration = m_activator.getBundleContext().registerService(m_componentMetadata.getServiceMetadata().getProvides(), m_delayedComponentServiceFactory, m_componentMetadata.getProperties());
+	        }
+        }
+    }
+    
+    /**
+     * This method deactivates the manager, performing the following steps
+     * 
+     * [0. Remove published services from the registry]
+     * 1. Call the deactivate() method, if present
+     * 2. Unbind any bound services
+     * 3. Release references to the component instance and component context 
+    **/
+    synchronized private void deactivate()
+    {
+    	// CONCURRENCY NOTE: This method may be called either from application code or by the dependency managers
+    	if (m_state != INSTANCE_VALID && m_state != INSTANCE_VALIDATING && m_state != INSTANCE_DESTROYING) {
+    		return;
+    	}
+
+    	// In case the instance is valid when this is called, the manager is set to an invalidating state
+        if (m_state != INSTANCE_DESTROYING)
+        {
+            setState(INSTANCE_INVALIDATING);
+        }
+    	
+        // 0.- Remove published services from the registry
+        if(m_serviceRegistration != null)
+        {
+	        m_serviceRegistration.unregister();
+	        m_serviceRegistration = null;
+
+	        GenericActivator.trace("unregistering the services", m_componentMetadata);
+	    }
+
+        // 1.- Call the deactivate method, if present	    
+        // Search the deactivate method
+		try {
+			// It is necessary to check that the implementation Object is not null. This may happen if the component
+			// is delayed and its service was never requested.
+			if(m_implementationObject != null)
+			{
+				Method activateMethod = getMethod(m_implementationObject.getClass(), "deactivate", new Class[]{ComponentContext.class});
+				activateMethod.invoke(m_implementationObject, new Object[]{m_componentContext});				
+			}
+		}
+		catch(NoSuchMethodException ex) {
+			// We can safely ignore this one
+			GenericActivator.trace("deactivate() method is not implemented", m_componentMetadata);
+		}
+		catch(IllegalAccessException ex) {
+			// Ignored, but should it be logged?
+			GenericActivator.trace("deactivate() method cannot be called", m_componentMetadata);
+		}
+		catch(InvocationTargetException ex) {
+			// TODO: 112.5.12 If the deactivate method throws an exception, SCR must log an error message
+			// containing the exception with the Log Service
+			GenericActivator.exception("The deactivate method has thrown and exception", m_componentMetadata, ex);
+		}
+
+        // 2. Unbind any bound services
+        Iterator it = m_dependencyManagers.iterator();
+
+        while (it.hasNext())
+        {
+            DependencyManager dm = (DependencyManager)it.next();
+            dm.unbind();
+        }
+
+        // 3. Release references to the component instance and component context
+        m_implementationObject = null;
+        m_componentContext = null;
+        m_delayedComponentServiceFactory = null;
+
+        //GenericActivator.trace("InstanceManager from bundle ["+ m_activator.getBundleContext().getBundle().getBundleId() + "] was invalidated.");
+
+        if (m_state != INSTANCE_DESTROYING)
+        {
+            setState(INSTANCE_INVALID);
+        }
+    }
+
+    /**
+     * 
+     */
+    public synchronized void dispose()
+    {
+        // CONCURRENCY NOTE: This method is only called from the GenericActivator or by application logic
+    	// but not by the dependency managers
+
+        // Theoretically this should never be in any state other than VALID or INVALID,
+        // because validate is called right after creation.
+        if (m_state != INSTANCE_VALID && m_state != INSTANCE_INVALID)
+        {
+            return;
+        }
+
+        boolean deactivationRequired = (m_state == INSTANCE_VALID);
+
+        setState(INSTANCE_DESTROYING);
+
+        // Stop the dependency managers to listen to events...
+        Iterator it = m_dependencyManagers.iterator();
+
+        while (it.hasNext())
+        {
+            DependencyManager dm = (DependencyManager)it.next();
+            m_activator.getBundleContext().removeServiceListener(dm);
+        }
+
+        // in case the component is disposed when it was VALID, it is necessary to deactivate it first.
+        if (deactivationRequired)
+        {
+            deactivate();
+        }
+
+        m_dependencyManagers.clear();
+
+        setState(INSTANCE_DESTROYED);
+
+        m_activator = null;
+    }
+
+    //**********************************************************************************************************
+    
+    /**
+    * Get the object that is implementing this descriptor
+    *
+    * @return the object that implements the services
+    */
+    public Object getInstance() {
+        return m_implementationObject;
+    }
+
+    /**
+     * 
+     */
+    public ComponentMetadata getComponentMetadata() {
+    	return m_componentMetadata;
+    }
+    
+    /**
+     * sets the state of the manager
+    **/
+    private synchronized void setState(int newState) {
+    	GenericActivator.trace("State transition : "+m_states[m_state]+" -> "+m_states[newState], m_componentMetadata);
+    	
+        m_state = newState;
+        
+        
+
+        if(m_state == INSTANCE_CREATED || m_state == INSTANCE_VALID || m_state == INSTANCE_INVALID || m_state == INSTANCE_DESTROYED)
+        {
+            //m_activator.fireInstanceChangeEvent(new InstanceChangeEvent(this,m_instanceMetadata,m_state));
+        }
     }
 
 /**
- * The DependencyManager task is to listen to service events and to call the
 * bind/unbind methods on a given object. It is also responsible for requesting
 * the unregistration of a service in case a dependency is broken.
- */
-    class DependencyManager implements ServiceListener
-    {
+ * The DependencyManager task is to listen to service events and to call the * bind/unbind methods on a given object. It is also responsible for requesting * the unregistration of a service in case a dependency is broken.
+ */
+    class DependencyManager implements ServiceListener
+    {
     	// Reference to the metadata
         private ReferenceMetadata m_dependencyMetadata;
-
+
         // The bound services <ServiceReference> 
-        private Set m_boundServicesRefs = new HashSet();
-        
-        // A flag that denotes if the dependency is satisfied at any given moment
-        private boolean m_isValid;
-        
-        // A flag that defines if the bind method receives a ServiceReference
-        private boolean m_bindUsesServiceReference = false;
-
-        /**
-         * Constructor that receives several parameters.
-         *
-         * @param   dependency  An object that contains data about the dependency
-        **/
-        private DependencyManager(ReferenceMetadata dependency) throws ClassNotFoundException, NoSuchMethodException
-        {
-            m_dependencyMetadata = dependency;
-            m_isValid = false;
-
-            //m_bindMethod = getTargetMethod(m_dependencyMetadata.getBind(), m_componentMetadata.getImplementationClassName(),m_dependencyMetadata.getInterface());
-            //m_unbindMethod = getTargetMethod(m_dependencyMetadata.getUnbind(), m_componentMetadata.getImplementationClassName(),m_dependencyMetadata.getInterface());
-        }
-
-        /**
-         * initializes a dependency. This method binds all of the service occurrences to the instance object
-         *
-         * @return true if the operation was successful, false otherwise
-        **/
-        private boolean bind()
-        {
-        	/* 
-            if(getInstance() == null)
-            {
-                return false;
-            }*/
-
-            // Get service references
-            ServiceReference refs[] = getRequiredServiceRefs();
-
-            // If no references were received, we have to check if the dependency
-            // is optional, if it is not then the dependency is invalid
-            if (refs == null && m_dependencyMetadata.isOptional() == false)
-            {
-                m_isValid = false;
-                return m_isValid;
-            }
-
-            m_isValid = true;
-
-            // refs can be null if the dependency is optional
-            if (refs != null)
-            {
-                int max = 1;
-                boolean retval = true;
-
-                if (m_dependencyMetadata.isMultiple() == true)
-                {
-                    max = refs.length;
-                }
-
-                for (int index = 0; index < max; index++)
-                {
-                    retval = invokeBindMethod(refs[index]);
-                    if(retval == false && (max == 1))
-                    {
-                        // There was an exception when calling the bind method
-                        GenericActivator.error("Dependency Manager: Possible exception in the bind method during initialize()");
-                        m_isValid = false;
-                        //setStateDependency(DependencyChangeEvent.DEPENDENCY_INVALID);
-                        return m_isValid;
-                    }
-                }
-            }
-
-            return m_isValid;
-        }
-
-        /**
-         * Revoke all bindings. This method cannot throw an exception since it must try
-         * to complete all that it can
-         *
-        **/
-        private void unbind()
-        {
-            Object []allrefs = m_boundServicesRefs.toArray();
-
-            if (allrefs == null)
-                return;
-
-            for (int i = 0; i < allrefs.length; i++)
-            {
-                invokeUnbindMethod((ServiceReference)allrefs[i]);
-            }
-        }
-
-        /**
-         *
-         * Returns an array containing the service references that are pertinent to the
-         * dependency managed by this object. This method filters out services that
-         * belong to bundles that are being (or are actually) shutdown. This is an issue
-         * since is not clearly specified in the OSGi specification if a getServiceReference
-         * call should return the services that belong to bundles that are stopping.
-         *
-         * @return an array of ServiceReferences valid in the context of this dependency
-        **/
-        private ServiceReference [] getRequiredServiceRefs()
-        {
-            try
-            {
-                ArrayList list=new ArrayList();
-                
-                ServiceReference temprefs[] = m_activator.getBundleContext().getServiceReferences(m_dependencyMetadata.getInterface(), m_dependencyMetadata.getTarget());
-
-                if (temprefs == null)
-                {
-                    return null;
-                }
-
-                for (int i = 0; i < temprefs.length; i++)
-                {
-                     if (temprefs[i].getBundle().getState() == Bundle.ACTIVE
-                            || temprefs[i].getBundle().getState() == Bundle.STARTING)
-                     {
-                         list.add(temprefs[i]);
-                     }
-                }
-
-                return (ServiceReference []) list.toArray(new ServiceReference [temprefs.length]);
-
-            }
-            catch (Exception e)
-            {
-                GenericActivator.error("DependencyManager: exception while getting references :"+e);
-                return null;
-            }
-        }
-
-        /**
-         * Gets a bind or unbind method according to the policies described in the specification
-         *
-         * @param methodname The name of the method
-         * @param targetClass the class to which the method belongs to
-         * @param parameterClassName the name of the class of the parameter that is passed to the method
-         * @return the method or null
-         * @throws java.lang.ClassNotFoundException if the class was not found
-        **/
-        private Method getBindingMethod(String methodname, Class targetClass, String parameterClassName)
-        {
-            Method method = null;
-            
-            Class parameterClass = null;
-            
-            // 112.3.1 The method is searched for using the following priority
-            // 1. The method's parameter type is org.osgi.framework.ServiceReference
-            // 2. The method's parameter type is the type specified by the reference's interface attribute
-            // 3. The method's parameter type is assignable from the type specified by the reference's interface attribute
-            try{
-            	// Case 1
-            	
-                method = getMethod(targetClass, methodname, new Class[]{ServiceReference.class});
-               
-                m_bindUsesServiceReference = true;                
-            }
-            catch(NoSuchMethodException ex){
-            	
-            	try {
-            		// Case2
-            		
-            		m_bindUsesServiceReference = false;
-            		
-            		parameterClass = m_activator.getBundleContext().getBundle().loadClass(parameterClassName);
-            		
-	                method = getMethod(targetClass, methodname, new Class[]{parameterClass});
-            	}
-                catch(NoSuchMethodException ex2) {
-            		
-                    // Case 3
-                    method = null;
-            		
-                    // iterate on class hierarchy
-                    for ( ; method == null && targetClass != null; targetClass = targetClass.getSuperclass())
-                    {
-                        // Get all potential bind methods
-                        Method candidateBindMethods[]  = targetClass.getDeclaredMethods();
-                       
-                        // Iterate over them
-                        for(int i = 0; method == null && i < candidateBindMethods.length; i++) {
-                            Method currentMethod = candidateBindMethods[i];
-                           
-                            // Get the parameters for the current method
-                            Class[] parameters = currentMethod.getParameterTypes();
-                           
-                            // Select only the methods that receive a single parameter
-                            // and a matching name
-                            if(parameters.length == 1 && currentMethod.getName().equals(methodname)) {
-                               
-                                // Get the parameter type
-                                Class theParameter = parameters[0];
-                               
-                                // Check if the parameter type is assignable from the type specified by the reference's interface attribute
-                                if(theParameter.isAssignableFrom(parameterClass)) {
-                                    
-                                    // Final check: it must be public or protected
-                                    if (Modifier.isPublic(method.getModifiers()) || Modifier.isProtected(method.getModifiers()))
-                                    {
-                                        if (!method.isAccessible())
-                                        {
-                                            method.setAccessible(true);
-                                        }
-                                        method = currentMethod;
-                                        
-                                    }
-                                }
-                            }                           
-                        }
-                    }
-            	} 
-            	catch(ClassNotFoundException ex2) {
-            		GenericActivator.exception("Cannot load class used as parameter "+parameterClassName,m_componentMetadata,ex2);
-            	}
-
-            }
-                        
-            return method;
-        }
-
-        /**
-         * Call the bind method. In case there is an exception while calling the bind method, the service
-         * is not considered to be bound to the instance object
-         *
-         * @param ref A ServiceReference with the service that will be bound to the instance object
-         * @param storeRef A boolean that indicates if the reference must be stored (this is used for the delayed components)
-         * @return true if the call was successful, false otherwise
-        **/
-        private boolean invokeBindMethod(ServiceReference ref) {
-        	// The bind method is only invoked if the implementation object is not null. This is valid
-        	// for both immediate and delayed components
-        	if(m_implementationObject != null) {
-        		
-		        try {
-		        	// Get the bind method
-		            Method bindMethod = getBindingMethod(m_dependencyMetadata.getBind(),  getInstance().getClass(), m_dependencyMetadata.getInterface());
-		            
-		            if(bindMethod == null){
-		            	// 112.3.1 If the method is not found , SCR must log an error
-		            	// message with the log service, if present, and ignore the method
-		            	// TODO: log error message
-		            	GenericActivator.trace("bind() method not found", m_componentMetadata);
-		            	return false;
-		            }
-		            
-		            // Get the parameter
-		            Object parameter;
-		            
-		            if(m_bindUsesServiceReference == false) {		            	 
-		            	parameter = m_activator.getBundleContext().getService(ref);
-		            }
-		            else {
-		            	parameter = ref;
-		            }
-		            	
-		            // Invoke the method
-		            bindMethod.invoke(getInstance(),new Object[] {parameter});
-		            
-		            // Store the reference
-		        	m_boundServicesRefs.add(ref);                
-		            
-		            return true;
-		        }
-		        catch(IllegalAccessException ex)
-		        {
-		        	// 112.3.1 If the method is not is not declared protected or public, SCR must log an error
-		        	// message with the log service, if present, and ignore the method
-		        	// TODO: log error message
-		        	return false;
-		        }
-		        catch(InvocationTargetException ex)
-		        {
-		        	GenericActivator.exception("DependencyManager : exception while invoking "+m_dependencyMetadata.getBind()+"()", m_componentMetadata, ex);
-		            return false;
-		        }
-        	} else if( m_implementationObject == null && m_componentMetadata.isImmediate() == false) {
-        		// In the case the implementation object is null and the component is delayed
-        		// then we still have to store the object that is passed to the bind methods
-        		// so that it can be used once the implementation object is created.
-        		m_boundServicesRefs.add(ref);
-        		return true;
-        	} else {
-        		// TODO: assert false : this theoretically never happens...
-        		return false;
-        	}        	
-        }
-
-        /**
-         * Call the unbind method
-         *
-         * @param ref A service reference corresponding to the service that will be unbound
-         * @return true if the call was successful, false otherwise
-        **/
-        private boolean invokeUnbindMethod(ServiceReference ref) {
-        	// TODO: assert m_boundServices.contains(ref) == true : "DependencyManager : callUnbindMethod UNBINDING UNKNOWN SERVICE !!!!";	
-        	
-        	// The unbind method is only invoked if the implementation object is not null. This is valid
-        	// for both immediate and delayed components
-        	if ( m_implementationObject != null ) {
-	            try
-	            {
-	            	// TODO: me quede aqui por que el unbind method no funciona
-	            	GenericActivator.trace("getting unbind: "+m_dependencyMetadata.getUnbind(), m_componentMetadata);
-	            	Method unbindMethod = getBindingMethod(m_dependencyMetadata.getUnbind(), getInstance().getClass(), m_dependencyMetadata.getInterface());
-	            	
-		        	// Recover the object that is bound from the map.
-		            //Object parameter = m_boundServices.get(ref);
-	        		Object parameter = null;
-	        		
-	        		if(m_bindUsesServiceReference == true) {
-	        			parameter = ref;
-	        		} else {
-	        			parameter = m_activator.getBundleContext().getService(ref);
-	        		}
-		            
-	            	if(unbindMethod == null){
-	                	// 112.3.1 If the method is not found , SCR must log an error
-	                	// message with the log service, if present, and ignore the method
-	                	// TODO: log error message
-	                	GenericActivator.trace("unbind() method not found", m_componentMetadata);
-	                	return false;
-	                }
-	
-	            	unbindMethod.invoke(getInstance(),new Object [] {parameter});
-	            	                
-	                m_boundServicesRefs.remove(ref);
-	                
-	                m_activator.getBundleContext().ungetService(ref);
-	                
-	                return true;
-	            }
-	            catch (IllegalAccessException ex) {
-	            	// 112.3.1 If the method is not is not declared protected or public, SCR must log an error
-	            	// message with the log service, if present, and ignore the method
-	            	// TODO: log error message
-	            	return false;
-	            }
-	            catch (InvocationTargetException ex) {
-	            	GenericActivator.exception("DependencyManager : exception while invoking "+m_dependencyMetadata.getUnbind()+"()", m_componentMetadata, ex);
-	            	return false;
-	            }
-	            
-        	} else if( m_implementationObject == null && m_componentMetadata.isImmediate() == false) {
-        		// In the case the implementation object is null and the component is delayed
-        		// then we still have to store the object that is passed to the bind methods
-        		// so that it can be used once the implementation object is created.
-        		m_boundServicesRefs.remove(ref);
-        		return true;
-        	} else {
-        		// TODO: assert false : this theoretically never happens...
-        		return false;
-        	}
-        }
-        
-        /**
-         * Called upon a service event. This method is responsible for calling the
-         * binding and unbinding methods and also to request the eventual unregistering
-         * of a service when a dependency breaks
-         *
-         * @param evt  The ServiceEvent
-        **/
-        public void serviceChanged(ServiceEvent evt)
-        {
-            synchronized (ComponentManagerImpl.this)
-            {
-                // If the object is being created or destroyed, we can safely ignore events.
-                if (m_state == INSTANCE_DESTROYING || m_state == INSTANCE_DESTROYED || m_state == INSTANCE_CREATING || m_state == INSTANCE_CREATED)
-                {
-                    return;
-                }
-
-                // If we are in the process of invalidating, it is not necessary to pass
-                // unregistration events, since we are unbinding everything anyway.
-                else if (m_state == INSTANCE_INVALIDATING && evt.getType() == ServiceEvent.UNREGISTERING)
-                {
-                    return;
-                }
-
-                // We do not have an entry for VALIDATING because it is reentrant.
-
-                // A service is unregistering
-                if (evt.getType() == ServiceEvent.UNREGISTERING)
-                {
-                    if (m_boundServicesRefs.contains(evt.getServiceReference()) == true)
-                    {
-                        // A static dependency is broken the instance manager will be invalidated
-                        if (m_dependencyMetadata.isStatic())
-                        {
-                            m_isValid = false;
-                            //setStateDependency(DependencyChangeEvent.DEPENDENCY_INVALID);
-                            try
-                            {
-                                GenericActivator.trace("Dependency Manager: Static dependency is broken", m_componentMetadata);
-                                deactivate();
-                                GenericActivator.trace("Dependency Manager: RECREATING", m_componentMetadata);
-                                activate();
-                            }
-                            catch(Exception ex)
-                            {
-                            	GenericActivator.exception("Exception while recreating dependency ",m_componentMetadata, ex);
-                            }
-                        }
-                        // dynamic dependency
-                        else
-                        {
-                            // Release references to the service, call unbinder method
-                            // and eventually request service unregistration
-
-                            invokeUnbindMethod(evt.getServiceReference());
-
-                            // The only thing we need to do here is check if we can reinitialize
-                            // once the bound services becomes zero. This tries to repair dynamic
-                            // 1..1 or rebind 0..1, since replacement services may be available.
-                            // In the case of aggregates, this will only invalidate them since they
-                            // can't be repaired.
-                            if (m_boundServicesRefs.size() == 0)
-                            {
-                                // try to reinitialize
-                                if (!bind())
-                                {
-                                    if (!m_dependencyMetadata.isOptional())
-                                    {
-                                        GenericActivator.trace("Dependency Manager: Mandatory dependency not fullfilled and no replacements available... unregistering service...", m_componentMetadata);
-                                        deactivate();
-                                        GenericActivator.trace("Dependency Manager: Recreating", m_componentMetadata);
-                                        activate();
-                                    }
-                                }
-                            }
-                        }
-                    }
-                }
-                // A service is registering.
-                else if (evt.getType() == ServiceEvent.REGISTERED)
-                {
-                    if (m_boundServicesRefs.contains(evt.getServiceReference()) == true)
-                    {
-                        // This is a duplicate
-                        GenericActivator.trace("DependencyManager : ignoring REGISTERED ServiceEvent (already bound)", m_componentMetadata);
-                    }
-                    else
-                    {
-                        m_isValid = true;
-                        //setStateDependency(DependencyChangeEvent.DEPENDENCY_VALID);
-
-                        // If the InstanceManager is invalid, a call to validate is made
-                        // which will fix everything.
-                        if (ComponentManagerImpl.this.m_state != INSTANCE_VALID)
-                        {
-                            activate();
-                        }
-                        // Otherwise, this checks for dynamic 0..1, 0..N, and 1..N it never
-                        // checks for 1..1 dynamic which is done above by the validate()
-                        else if (!m_dependencyMetadata.isStatic())
-                        {
-                            // For dependency that are aggregates, always bind the service
-                            // Otherwise only bind if bind services is zero, which captures the 0..1 case
-                            if (m_dependencyMetadata.isMultiple() || m_boundServicesRefs.size() == 0)
-                            {
-                                invokeBindMethod(evt.getServiceReference());
-                            }
-                        }
-                    }
-                }
-            }
-        }
-    }
-
-    /**
-     * Implementation for the ComponentContext interface
-     *
+        private Set m_boundServicesRefs = new HashSet();
+        
+        // A flag that denotes if the dependency is satisfied at any given moment
+        private boolean m_isValid;
+        
+        // A flag that defines if the bind method receives a ServiceReference
+        private boolean m_bindUsesServiceReference = false;
+
+        /**
+         * Constructor that receives several parameters.
+         *
+         * @param   dependency  An object that contains data about the dependency
+        **/
+        private DependencyManager(ReferenceMetadata dependency) throws ClassNotFoundException, NoSuchMethodException
+        {
+            m_dependencyMetadata = dependency;
+            m_isValid = false;
+
+            //m_bindMethod = getTargetMethod(m_dependencyMetadata.getBind(), m_componentMetadata.getImplementationClassName(),m_dependencyMetadata.getInterface());
+            //m_unbindMethod = getTargetMethod(m_dependencyMetadata.getUnbind(), m_componentMetadata.getImplementationClassName(),m_dependencyMetadata.getInterface());
+        }
+
+        /**
+         * initializes a dependency. This method binds all of the service occurrences to the instance object
+         *
+         * @return true if the operation was successful, false otherwise
+        **/
+        private boolean bind()
+        {
+        	/* 
+            if(getInstance() == null)
+            {
+                return false;
+            }*/
+
+            // Get service references
+            ServiceReference refs[] = getRequiredServiceRefs();
+
+            // If no references were received, we have to check if the dependency
+            // is optional, if it is not then the dependency is invalid
+            if (refs == null && m_dependencyMetadata.isOptional() == false)
+            {
+                m_isValid = false;
+                return m_isValid;
+            }
+
+            m_isValid = true;
+
+            // refs can be null if the dependency is optional
+            if (refs != null)
+            {
+                int max = 1;
+                boolean retval = true;
+
+                if (m_dependencyMetadata.isMultiple() == true)
+                {
+                    max = refs.length;
+                }
+
+                for (int index = 0; index < max; index++)
+                {
+                    retval = invokeBindMethod(refs[index]);
+                    if(retval == false && (max == 1))
+                    {
+                        // There was an exception when calling the bind method
+                        GenericActivator.error("Dependency Manager: Possible exception in the bind method during initialize()");
+                        m_isValid = false;
+                        //setStateDependency(DependencyChangeEvent.DEPENDENCY_INVALID);
+                        return m_isValid;
+                    }
+                }
+            }
+
+            return m_isValid;
+        }
+
+        /**
+         * Revoke all bindings. This method cannot throw an exception since it must try
+         * to complete all that it can
+         *
+        **/
+        private void unbind()
+        {
+            Object []allrefs = m_boundServicesRefs.toArray();
+
+            if (allrefs == null)
+                return;
+
+            for (int i = 0; i < allrefs.length; i++)
+            {
+                invokeUnbindMethod((ServiceReference)allrefs[i]);
+            }
+        }
+
+        /**
+         *
+         * Returns an array containing the service references that are pertinent to the
+         * dependency managed by this object. This method filters out services that
+         * belong to bundles that are being (or are actually) shutdown. This is an issue
+         * since is not clearly specified in the OSGi specification if a getServiceReference
+         * call should return the services that belong to bundles that are stopping.
+         *
+         * @return an array of ServiceReferences valid in the context of this dependency
+        **/
+        private ServiceReference [] getRequiredServiceRefs()
+        {
+            try
+            {
+                ArrayList list=new ArrayList();
+                
+                ServiceReference temprefs[] = m_activator.getBundleContext().getServiceReferences(m_dependencyMetadata.getInterface(), m_dependencyMetadata.getTarget());
+
+                if (temprefs == null)
+                {
+                    return null;
+                }
+
+                for (int i = 0; i < temprefs.length; i++)
+                {
+                     if (temprefs[i].getBundle().getState() == Bundle.ACTIVE
+                            || temprefs[i].getBundle().getState() == Bundle.STARTING)
+                     {
+                         list.add(temprefs[i]);
+                     }
+                }
+
+                return (ServiceReference []) list.toArray(new ServiceReference [temprefs.length]);
+
+            }
+            catch (Exception e)
+            {
+                GenericActivator.error("DependencyManager: exception while getting references :"+e);
+                return null;
+            }
+        }
+
+        /**
+         * Gets a bind or unbind method according to the policies described in the specification
+         *
+         * @param methodname The name of the method
+         * @param targetClass the class to which the method belongs to
+         * @param parameterClassName the name of the class of the parameter that is passed to the method
+         * @return the method or null
+         * @throws java.lang.ClassNotFoundException if the class was not found
+        **/
+        private Method getBindingMethod(String methodname, Class targetClass, String parameterClassName)
+        {
+            Method method = null;
+            
+            Class parameterClass = null;
+            
+            // 112.3.1 The method is searched for using the following priority
+            // 1. The method's parameter type is org.osgi.framework.ServiceReference
+            // 2. The method's parameter type is the type specified by the reference's interface attribute
+            // 3. The method's parameter type is assignable from the type specified by the reference's interface attribute
+            try{
+            	// Case 1
+            	
+                method = getMethod(targetClass, methodname, new Class[]{ServiceReference.class});
+               
+                m_bindUsesServiceReference = true;                
+            }
+            catch(NoSuchMethodException ex){
+            	
+            	try {
+            		// Case2
+            		
+            		m_bindUsesServiceReference = false;
+            		
+            		parameterClass = m_activator.getBundleContext().getBundle().loadClass(parameterClassName);
+            		
+	                method = getMethod(targetClass, methodname, new Class[]{parameterClass});
+            	}
+                catch(NoSuchMethodException ex2) {
+            		
+                    // Case 3
+                    method = null;
+            		
+                    // iterate on class hierarchy
+                    for ( ; method == null && targetClass != null; targetClass = targetClass.getSuperclass())
+                    {
+                        // Get all potential bind methods
+                        Method candidateBindMethods[]  = targetClass.getDeclaredMethods();
+                       
+                        // Iterate over them
+                        for(int i = 0; method == null && i < candidateBindMethods.length; i++) {
+                            Method currentMethod = candidateBindMethods[i];
+                           
+                            // Get the parameters for the current method
+                            Class[] parameters = currentMethod.getParameterTypes();
+                           
+                            // Select only the methods that receive a single parameter
+                            // and a matching name
+                            if(parameters.length == 1 && currentMethod.getName().equals(methodname)) {
+                               
+                                // Get the parameter type
+                                Class theParameter = parameters[0];
+                               
+                                // Check if the parameter type is assignable from the type specified by the reference's interface attribute
+                                if(theParameter.isAssignableFrom(parameterClass)) {
+                                    
+                                    // Final check: it must be public or protected
+                                    if (Modifier.isPublic(method.getModifiers()) || Modifier.isProtected(method.getModifiers()))
+                                    {
+                                        if (!method.isAccessible())
+                                        {
+                                            method.setAccessible(true);
+                                        }
+                                        method = currentMethod;
+                                        
+                                    }
+                                }
+                            }                           
+                        }
+                    }
+            	} 
+            	catch(ClassNotFoundException ex2) {
+            		GenericActivator.exception("Cannot load class used as parameter "+parameterClassName,m_componentMetadata,ex2);
+            	}
+
+            }
+                        
+            return method;
+        }
+
+        /**
+         * Call the bind method. In case there is an exception while calling the bind method, the service
+         * is not considered to be bound to the instance object
+         *
+         * @param ref A ServiceReference with the service that will be bound to the instance object
+         * @param storeRef A boolean that indicates if the reference must be stored (this is used for the delayed components)
+         * @return true if the call was successful, false otherwise
+        **/
+        private boolean invokeBindMethod(ServiceReference ref) {
+        	// The bind method is only invoked if the implementation object is not null. This is valid
+        	// for both immediate and delayed components
+        	if(m_implementationObject != null) {
+        		
+		        try {
+		        	// Get the bind method
+		            Method bindMethod = getBindingMethod(m_dependencyMetadata.getBind(),  getInstance().getClass(), m_dependencyMetadata.getInterface());
+		            
+		            if(bindMethod == null){
+		            	// 112.3.1 If the method is not found , SCR must log an error
+		            	// message with the log service, if present, and ignore the method
+		            	// TODO: log error message
+		            	GenericActivator.trace("bind() method not found", m_componentMetadata);
+		            	return false;
+		            }
+		            
+		            // Get the parameter
+		            Object parameter;
+		            
+		            if(m_bindUsesServiceReference == false) {		            	 
+		            	parameter = m_activator.getBundleContext().getService(ref);
+		            }
+		            else {
+		            	parameter = ref;
+		            }
+		            	
+		            // Invoke the method
+		            bindMethod.invoke(getInstance(),new Object[] {parameter});
+		            
+		            // Store the reference
+		        	m_boundServicesRefs.add(ref);                
+		            
+		            return true;
+		        }
+		        catch(IllegalAccessException ex)
+		        {
+		        	// 112.3.1 If the method is not is not declared protected or public, SCR must log an error
+		        	// message with the log service, if present, and ignore the method
+		        	// TODO: log error message
+		        	return false;
+		        }
+		        catch(InvocationTargetException ex)
+		        {
+		        	GenericActivator.exception("DependencyManager : exception while invoking "+m_dependencyMetadata.getBind()+"()", m_componentMetadata, ex);
+		            return false;
+		        }
+        	} else if( m_implementationObject == null && m_componentMetadata.isImmediate() == false) {
+        		// In the case the implementation object is null and the component is delayed
+        		// then we still have to store the object that is passed to the bind methods
+        		// so that it can be used once the implementation object is created.
+        		m_boundServicesRefs.add(ref);
+        		return true;
+        	} else {
+        		// TODO: assert false : this theoretically never happens...
+        		return false;
+        	}        	
+        }
+
+        /**
+         * Call the unbind method
+         *
+         * @param ref A service reference corresponding to the service that will be unbound
+         * @return true if the call was successful, false otherwise
+        **/
+        private boolean invokeUnbindMethod(ServiceReference ref) {
+        	// TODO: assert m_boundServices.contains(ref) == true : "DependencyManager : callUnbindMethod UNBINDING UNKNOWN SERVICE !!!!";	
+        	
+        	// The unbind method is only invoked if the implementation object is not null. This is valid
+        	// for both immediate and delayed components
+        	if ( m_implementationObject != null ) {
+	            try
+	            {
+	            	// TODO: me quede aqui por que el unbind method no funciona
+	            	GenericActivator.trace("getting unbind: "+m_dependencyMetadata.getUnbind(), m_componentMetadata);
+	            	Method unbindMethod = getBindingMethod(m_dependencyMetadata.getUnbind(), getInstance().getClass(), m_dependencyMetadata.getInterface());
+	            	
+		        	// Recover the object that is bound from the map.
+		            //Object parameter = m_boundServices.get(ref);
+	        		Object parameter = null;
+	        		
+	        		if(m_bindUsesServiceReference == true) {
+	        			parameter = ref;
+	        		} else {
+	        			parameter = m_activator.getBundleContext().getService(ref);
+	        		}
+		            
+	            	if(unbindMethod == null){
+	                	// 112.3.1 If the method is not found , SCR must log an error
+	                	// message with the log service, if present, and ignore the method
+	                	// TODO: log error message
+	                	GenericActivator.trace("unbind() method not found", m_componentMetadata);
+	                	return false;
+	                }
+	
+	            	unbindMethod.invoke(getInstance(),new Object [] {parameter});
+	            	                
+	                m_boundServicesRefs.remove(ref);
+	                
+	                m_activator.getBundleContext().ungetService(ref);
+	                
+	                return true;
+	            }
+	            catch (IllegalAccessException ex) {
+	            	// 112.3.1 If the method is not is not declared protected or public, SCR must log an error
+	            	// message with the log service, if present, and ignore the method
+	            	// TODO: log error message
+	            	return false;
+	            }
+	            catch (InvocationTargetException ex) {
+	            	GenericActivator.exception("DependencyManager : exception while invoking "+m_dependencyMetadata.getUnbind()+"()", m_componentMetadata, ex);
+	            	return false;
+	            }
+	            
+        	} else if( m_implementationObject == null && m_componentMetadata.isImmediate() == false) {
+        		// In the case the implementation object is null and the component is delayed
+        		// then we still have to store the object that is passed to the bind methods
+        		// so that it can be used once the implementation object is created.
+        		m_boundServicesRefs.remove(ref);
+        		return true;
+        	} else {
+        		// TODO: assert false : this theoretically never happens...
+        		return false;
+        	}
+        }
+        
+        /**
+         * Called upon a service event. This method is responsible for calling the
+         * binding and unbinding methods and also to request the eventual unregistering
+         * of a service when a dependency breaks
+         *
+         * @param evt  The ServiceEvent
+        **/
+        public void serviceChanged(ServiceEvent evt)
+        {
+            synchronized (ComponentManagerImpl.this)
+            {
+                // If the object is being created or destroyed, we can safely ignore events.
+                if (m_state == INSTANCE_DESTROYING || m_state == INSTANCE_DESTROYED || m_state == INSTANCE_CREATING || m_state == INSTANCE_CREATED)
+                {
+                    return;
+                }
+
+                // If we are in the process of invalidating, it is not necessary to pass
+                // unregistration events, since we are unbinding everything anyway.
+                else if (m_state == INSTANCE_INVALIDATING && evt.getType() == ServiceEvent.UNREGISTERING)
+                {
+                    return;
+                }
+
+                // We do not have an entry for VALIDATING because it is reentrant.
+
+                // A service is unregistering
+                if (evt.getType() == ServiceEvent.UNREGISTERING)
+                {
+                    if (m_boundServicesRefs.contains(evt.getServiceReference()) == true)
+                    {
+                        // A static dependency is broken the instance manager will be invalidated
+                        if (m_dependencyMetadata.isStatic())
+                        {
+                            m_isValid = false;
+                            //setStateDependency(DependencyChangeEvent.DEPENDENCY_INVALID);
+                            try
+                            {
+                                GenericActivator.trace("Dependency Manager: Static dependency is broken", m_componentMetadata);
+                                deactivate();
+                                GenericActivator.trace("Dependency Manager: RECREATING", m_componentMetadata);
+                                activate();
+                            }
+                            catch(Exception ex)
+                            {
+                            	GenericActivator.exception("Exception while recreating dependency ",m_componentMetadata, ex);
+                            }
+                        }
+                        // dynamic dependency
+                        else
+                        {
+                            // Release references to the service, call unbinder method
+                            // and eventually request service unregistration
+
+                            invokeUnbindMethod(evt.getServiceReference());
+
+                            // The only thing we need to do here is check if we can reinitialize
+                            // once the bound services becomes zero. This tries to repair dynamic
+                            // 1..1 or rebind 0..1, since replacement services may be available.
+                            // In the case of aggregates, this will only invalidate them since they
+                            // can't be repaired.
+                            if (m_boundServicesRefs.size() == 0)
+                            {
+                                // try to reinitialize
+                                if (!bind())
+                                {
+                                    if (!m_dependencyMetadata.isOptional())
+                                    {
+                                        GenericActivator.trace("Dependency Manager: Mandatory dependency not fullfilled and no replacements available... unregistering service...", m_componentMetadata);
+                                        deactivate();
+                                        GenericActivator.trace("Dependency Manager: Recreating", m_componentMetadata);
+                                        activate();
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+                // A service is registering.
+                else if (evt.getType() == ServiceEvent.REGISTERED)
+                {
+                    if (m_boundServicesRefs.contains(evt.getServiceReference()) == true)
+                    {
+                        // This is a duplicate
+                        GenericActivator.trace("DependencyManager : ignoring REGISTERED ServiceEvent (already bound)", m_componentMetadata);
+                    }
+                    else
+                    {
+                        m_isValid = true;
+                        //setStateDependency(DependencyChangeEvent.DEPENDENCY_VALID);
+
+                        // If the InstanceManager is invalid, a call to validate is made
+                        // which will fix everything.
+                        if (ComponentManagerImpl.this.m_state != INSTANCE_VALID)
+                        {
+                            activate();
+                        }
+                        // Otherwise, this checks for dynamic 0..1, 0..N, and 1..N it never
+                        // checks for 1..1 dynamic which is done above by the validate()
+                        else if (!m_dependencyMetadata.isStatic())
+                        {
+                            // For dependency that are aggregates, always bind the service
+                            // Otherwise only bind if bind services is zero, which captures the 0..1 case
+                            if (m_dependencyMetadata.isMultiple() || m_boundServicesRefs.size() == 0)
+                            {
+                                invokeBindMethod(evt.getServiceReference());
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * Implementation for the ComponentContext interface
+     *
+     */
+    class ComponentContextImpl implements ComponentContext {
+
+        private Bundle m_usingBundle;
+
+        ComponentContextImpl(Bundle usingBundle)
+        {
+            m_usingBundle = usingBundle;
+        }
+
+    	public Dictionary getProperties() {
+    		//TODO: 112.11.3.5 The Dictionary is read-only and cannot be modified
+    		return m_componentMetadata.getProperties();
+    	}
+
+        public Object locateService(String name) {
+            DependencyManager dm = getDependencyManager(name);
+            if (dm == null || dm.m_boundServicesRefs.isEmpty())
+            {
+                return null;
+            }
+            
+            ServiceReference selectedRef;
+            if (dm.m_boundServicesRefs.size() == 1)
+            {
+                // short cut for single bound service
+                selectedRef = (ServiceReference) dm.m_boundServicesRefs.iterator().next();
+            }
+            else
+            {
+                // is it correct to assume an ordered bound services set ? 
+                int maxRanking = Integer.MIN_VALUE;
+                long minId = Long.MAX_VALUE;
+                selectedRef = null;
+                
+                Iterator it = dm.m_boundServicesRefs.iterator();
+                while (it.hasNext())
+                {
+                    ServiceReference ref = (ServiceReference) it.next();
+                    Integer rank = (Integer) ref.getProperty(Constants.SERVICE_RANKING);
+                    int ranking = (rank == null) ? Integer.MIN_VALUE : rank.intValue();
+                    long id = ((Long) ref.getProperty(Constants.SERVICE_ID)).longValue();
+                    if (maxRanking < ranking || (maxRanking == ranking && id < minId))
+                    {
+                        maxRanking = ranking;
+                        minId = id;
+                        selectedRef = ref;
+                    }
+                }
+            }
+    
+            // this is not realistic, as at least one service is available
+            // whose service id is smaller than Long.MAX_VALUE, still be sure
+            if (selectedRef == null)
+            {
+                return null;
+            }
+            
+            // return the service for the selected reference
+            return getBundleContext().getService(selectedRef);
+   	    }
+
+        public Object locateService(String name, ServiceReference ref) {
+            DependencyManager dm = getDependencyManager(name);
+            if (dm == null || dm.m_boundServicesRefs.isEmpty())
+            {
+                return null;
+            }
+            
+            // is it correct to assume an ordered bound services set ? 
+            Iterator it = dm.m_boundServicesRefs.iterator();
+            while (it.hasNext())
+            {
+                if (it.next().equals(ref))
+                {
+                    return getBundleContext().getService(ref);
+                }
+            }
+            
+            // no matching name and service reference found
+            return null;
+    	}
+
+        public Object[] locateServices(String name) {
+            DependencyManager dm = getDependencyManager(name);
+            if (dm == null || dm.m_boundServicesRefs.isEmpty())
+            {
+                return null;
+            }
+            
+            Object[] services = new Object[dm.m_boundServicesRefs.size()];
+            Iterator it = dm.m_boundServicesRefs.iterator();
+            for (int i=0; i < services.length && it.hasNext(); i++)
+            {
+                ServiceReference ref = (ServiceReference) it.next();
+                services[i] = getBundleContext().getService(ref);
+            }
+            return services;
+    	}
+
+        private DependencyManager getDependencyManager(String name) {
+            Iterator it = m_dependencyManagers.iterator();
+            while (it.hasNext())
+            {
+                DependencyManager dm = (DependencyManager)it.next();
+                
+                // if any of the dependency managers is unable to bind (it is invalid), the component is deactivated
+                if (name.equals(dm.m_dependencyMetadata.getName()))
+                {
+                    return dm;
+                }
+            }
+            
+            // not found
+            return null;
+        }
+        
+    	public BundleContext getBundleContext() {
+    		return m_activator.getBundleContext();
+    	}
+
+    	public Bundle getUsingBundle() {
+            return m_usingBundle;
+    	}
+
+    	public ComponentInstance getComponentInstance() {
+    		return ComponentManagerImpl.this;
+    	}
+
+    	public void enableComponent(String arg0) {
+    		// TODO implement this method
+    		
+    	}
+
+    	public void disableComponent(String arg0) {
+    		// TODO implement this method
+    		
+    	}
+
+    	public ServiceReference getServiceReference() {
+    		if(m_serviceRegistration != null) {
+    			return m_serviceRegistration.getReference();
+    		}
+    		else {
+    			return null;
+    		}
+    	}
+    }
+    
+    /**
+     * This class is a ServiceFactory that is used when a delayed component is created
+     *
+     */
+    class DelayedComponentServiceFactory implements ServiceFactory {
+    	
+    	public Object getService(Bundle arg0, ServiceRegistration arg1) {
+    		
+    		GenericActivator.trace("DelayedComponentServiceFactory.getService()", m_componentMetadata);
+    		// When the getServiceMethod is called, the implementation object must be created
+    		
+            // 1. Load the component implementation class
+            // 2. Create the component instance and component context
+            // If the component is not immediate, this is not done at this moment
+        	try
+	        {
+	        	// 112.4.4 The class is retrieved with the loadClass method of the component's bundle
+	            Class c = m_activator.getBundleContext().getBundle().loadClass(m_componentMetadata.getImplementationClassName());
+	            
+	            // 112.4.4 The class must be public and have a public constructor without arguments so component instances
+	            // may be created by the SCR with the newInstance method on Class
+	            m_componentContext = new ComponentContextImpl(arg0);
+	            m_implementationObject = c.newInstance();
+	        }
+	        catch (Exception ex)
+	        {
+	            // TODO: manage this exception when implementation object cannot be created
+	            GenericActivator.exception("Error during instantiation of the implementation object",m_componentMetadata,ex);
+	            deactivate();
+	            //invalidate();
+	            return null;
+	        }
+	        
+	        
+	        // 3. Bind the target services
+	        Iterator it = m_dependencyManagers.iterator();
+
+	        while ( it.hasNext() )
+	        {
+	            DependencyManager dm = (DependencyManager)it.next();
+	            Iterator bound = dm.m_boundServicesRefs.iterator();
+	            while ( bound.hasNext() ) {
+	            	ServiceReference nextRef = (ServiceReference) bound.next();	            	
+	            	dm.invokeBindMethod(nextRef);
+	            }
+	        }
+	        
+	        // 4. Call the activate method, if present
+            // Search for the activate method
+        	try {
+        		Method activateMethod = getMethod(m_implementationObject.getClass(), "activate", new Class[]{ComponentContext.class});
+        		activateMethod.invoke(m_implementationObject, new Object[]{m_componentContext});
+        	}
+        	catch(NoSuchMethodException ex) {
+                // We can safely ignore this one
+                GenericActivator.trace("activate() method is not implemented", m_componentMetadata);
+            }
+            catch(IllegalAccessException ex) {
+                // Ignored, but should it be logged?
+                GenericActivator.trace("activate() method cannot be called", m_componentMetadata);
+            }
+            catch(InvocationTargetException ex) {
+                // TODO: 112.5.8 If the activate method throws an exception, SCR must log an error message
+                // containing the exception with the Log Service
+                GenericActivator.exception("The activate method has thrown and exception", m_componentMetadata, ex);
+            }
+    		
+    		return m_implementationObject;
+    	}
+
+    	public void ungetService(Bundle arg0, ServiceRegistration arg1, Object arg2) {
+    		// TODO Auto-generated method stub
+
+    	}
+    }
+
+    /**
+     * Finds the named public or protected method in the given class or any
+     * super class. If such a method is found, its accessibility is enfored by
+     * calling the <code>Method.setAccessible</code> method if required and
+     * the method is returned. Enforcing accessibility is required to support
+     * invocation of protected methods.
+     * 
+     * @param clazz The <code>Class</code> which provides the method.
+     * @param name The name of the method.
+     * @param parameterTypes The parameters to the method. Passing
+     *      <code>null</code> is equivalent to using an empty array.
+     *      
+     * @return The named method with enforced accessibility
+     * 
+     * @throws NoSuchMethodException If no public or protected method with
+     *      the given name can be found in the class or any of its super classes.
      */
-    class ComponentContextImpl implements ComponentContext {
-
-        private Bundle m_usingBundle;
-
-        ComponentContextImpl(Bundle usingBundle)
-        {
-            m_usingBundle = usingBundle;
-        }
-
-    	public Dictionary getProperties() {
-    		//TODO: 112.11.3.5 The Dictionary is read-only and cannot be modified
-    		return m_componentMetadata.getProperties();
-    	}
-
-        public Object locateService(String name) {
-            DependencyManager dm = getDependencyManager(name);
-            if (dm == null || dm.m_boundServicesRefs.isEmpty())
-            {
-                return null;
-            }
-            
-            ServiceReference selectedRef;
-            if (dm.m_boundServicesRefs.size() == 1)
-            {
-                // short cut for single bound service
-                selectedRef = (ServiceReference) dm.m_boundServicesRefs.iterator().next();
-            }
-            else
-            {

[... 296 lines stripped ...]


Mime
View raw message