You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by cl...@apache.org on 2007/08/17 09:53:41 UTC

svn commit: r566960 - in /felix/trunk/ipojo/core: ./ src/main/java/org/apache/felix/ipojo/ src/main/java/org/apache/felix/ipojo/handlers/configuration/ src/main/java/org/apache/felix/ipojo/handlers/lifecycle/controller/ src/main/java/org/apache/felix/i...

Author: clement
Date: Fri Aug 17 00:53:40 2007
New Revision: 566960

URL: http://svn.apache.org/viewvc?view=rev&rev=566960
Log:
Add the lifecycle controller handler.
Solve a bug when InstanceManager.setState is reentrant (in the same thread).
Some comestic bug fixes in provided service.

Added:
    felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/lifecycle/controller/
    felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/lifecycle/controller/ControllerHandler.java
Modified:
    felix/trunk/ipojo/core/pom.xml
    felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/IPojoConfiguration.java
    felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/InstanceManager.java
    felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/configuration/ConfigurableProperty.java
    felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/providedservice/ProvidedService.java
    felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/providedservice/ProvidedServiceHandler.java

Modified: felix/trunk/ipojo/core/pom.xml
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/core/pom.xml?view=diff&rev=566960&r1=566959&r2=566960
==============================================================================
--- felix/trunk/ipojo/core/pom.xml (original)
+++ felix/trunk/ipojo/core/pom.xml Fri Aug 17 00:53:40 2007
@@ -59,6 +59,7 @@
     			org.apache.felix.ipojo.handlers.configuration,
     			org.apache.felix.ipojo.handlers.dependency.nullable,
               	org.apache.felix.ipojo.handlers.lifecycle.callback,
+              	org.apache.felix.ipojo.handlers.lifecycle.controller,
               	org.objectweb.asm,
               	org.objectweb.asm.commons,
               	org.objectweb.asm.tree  <!-- to remove -->

Modified: felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/IPojoConfiguration.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/IPojoConfiguration.java?view=diff&rev=566960&r1=566959&r2=566960
==============================================================================
--- felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/IPojoConfiguration.java (original)
+++ felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/IPojoConfiguration.java Fri Aug 17 00:53:40 2007
@@ -25,12 +25,12 @@
 import org.apache.felix.ipojo.handlers.configuration.ConfigurationHandler;
 import org.apache.felix.ipojo.handlers.dependency.DependencyHandler;
 import org.apache.felix.ipojo.handlers.lifecycle.callback.LifecycleCallbackHandler;
+import org.apache.felix.ipojo.handlers.lifecycle.controller.ControllerHandler;
 import org.apache.felix.ipojo.handlers.providedservice.ProvidedServiceHandler;
 import org.apache.felix.ipojo.util.Logger;
 
 /**
- * Activator Basic Configuration. - Log Level - Available handlers
- * 
+ * iPOJO Configuration : Default Log Level - Available (core) handlers.
  * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
  */
 public class IPojoConfiguration {
@@ -47,8 +47,9 @@
         DependencyHandler.class, 
         ProvidedServiceHandler.class, 
         ConfigurationHandler.class,
-        LifecycleCallbackHandler.class, 
-        ArchitectureHandler.class 
+        LifecycleCallbackHandler.class,
+        ControllerHandler.class,
+        ArchitectureHandler.class
     };
 
     /**

Modified: felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/InstanceManager.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/InstanceManager.java?view=diff&rev=566960&r1=566959&r2=566960
==============================================================================
--- felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/InstanceManager.java (original)
+++ felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/InstanceManager.java Fri Aug 17 00:53:40 2007
@@ -20,8 +20,10 @@
 
 import java.lang.reflect.Constructor;
 import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
 import java.util.Dictionary;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
@@ -94,15 +96,23 @@
     /**
      * Instance State Listener List.
      */
-    private InstanceStateListener[] m_instanceListeners = new InstanceStateListener[0];
+    private List m_instanceListeners = new ArrayList();
 
     /**
      * Component type information.
      */
     private ComponentDescription m_componentDesc;
     
+   /**
+    * Is the component instance state changing?
+    */
+    private boolean m_inTransition = false;
+    
+    /**
+     * Queue of stored state changed. 
+     */
+    private List m_stateQueue = new ArrayList();
 
-    // Constructor
     /**
      * Construct a new Component Manager.
      * 
@@ -275,8 +285,8 @@
         m_pojoObjects = new Object[0];
 
         m_state = STOPPED;
-        for (int i = 0; i < m_instanceListeners.length; i++) {
-            m_instanceListeners[i].stateChanged(this, STOPPED);
+        for (int i = 0; i < m_instanceListeners.size(); i++) {
+            ((InstanceStateListener) m_instanceListeners.get(i)).stateChanged(this, STOPPED);
         }
     }
     
@@ -289,8 +299,8 @@
             stop();
         }
         
-        for (int i = 0; i < m_instanceListeners.length; i++) {
-            m_instanceListeners[i].stateChanged(this, DISPOSED);
+        for (int i = 0; i < m_instanceListeners.size(); i++) {
+            ((InstanceStateListener) m_instanceListeners.get(i)).stateChanged(this, DISPOSED);
         }
         
         m_factory.disposed(this);
@@ -300,7 +310,7 @@
         m_fieldRegistration = new HashMap();
         m_clazz = null;
         m_pojoObjects = new Object[0];
-        m_instanceListeners = new InstanceStateListener[0];
+        m_instanceListeners.clear();
     }
     
     /**
@@ -312,8 +322,8 @@
             stop();
         }
         
-        for (int i = 0; i < m_instanceListeners.length; i++) {
-            m_instanceListeners[i].stateChanged(this, DISPOSED);
+        for (int i = 0; i < m_instanceListeners.size(); i++) {
+            ((InstanceStateListener) m_instanceListeners.get(i)).stateChanged(this, DISPOSED);
         }
 
         // Cleaning
@@ -322,16 +332,24 @@
         m_fieldRegistration = new HashMap();
         m_clazz = null;
         m_pojoObjects = new Object[0];
-        m_instanceListeners = new InstanceStateListener[0];
+        m_instanceListeners.clear();
     }
-
+    
     /**
      * Set the state of the component instance.
-     * Ff the state changed call the stateChanged(int) method on the handlers.
+     * if the state changed call the stateChanged(int) method on the handlers.
+     * This method has a reentrant mechanism. If in the flow of the first call the method is called another times, 
+     * the second call is stored and executed after the first one is finished.
      * @param state : the new state
      */
-    public void setState(int state) {
+    private synchronized void setState(int state) {
+        if (m_inTransition) {
+            m_stateQueue.add(new Integer(state)); 
+            return;
+        }
+        
         if (m_state != state) {
+            m_inTransition = true;
 
             // Log the state change
             if (state == INVALID) {
@@ -347,10 +365,16 @@
                 m_handlers[i].stateChanged(state);
             }
             
-            for (int i = 0; i < m_instanceListeners.length; i++) {
-                m_instanceListeners[i].stateChanged(this, state);
+            for (int i = 0; i < m_instanceListeners.size(); i++) {
+                ((InstanceStateListener) m_instanceListeners.get(i)).stateChanged(this, state);
             }
         }
+        
+        m_inTransition = false;
+        if (! m_stateQueue.isEmpty()) {
+            int newState = ((Integer) (m_stateQueue.remove(0))).intValue();
+            setState(newState);
+        }
     }
 
     /**
@@ -372,53 +396,21 @@
     }
     
     /**
-     * Add an instance to the created instance list.
-     * @param listener : the instance state listener to add.
+     * Register an instance state listener.
+     * @param listener : listener to register.
      * @see org.apache.felix.ipojo.ComponentInstance#addInstanceStateListener(org.apache.felix.ipojo.InstanceStateListener)
      */
     public void addInstanceStateListener(InstanceStateListener listener) {
-        for (int i = 0; (m_instanceListeners != null) && (i < m_instanceListeners.length); i++) {
-            if (m_instanceListeners[i] == listener) {
-                return;
-            }
-        }
-
-        if (m_instanceListeners.length > 0) {
-            InstanceStateListener[] newInstances = new InstanceStateListener[m_instanceListeners.length + 1];
-            System.arraycopy(m_instanceListeners, 0, newInstances, 0, m_instanceListeners.length);
-            newInstances[m_instanceListeners.length] = listener;
-            m_instanceListeners = newInstances;
-        } else {
-            m_instanceListeners = new InstanceStateListener[] { listener };
-        }
+        m_instanceListeners.add(listener);
     }
-    
+
     /**
-     * Remove an instance state listener.
-     * @param listener : the listener to remove
+     * Unregister an instance state listener.
+     * @param listener : listener to unregister.
      * @see org.apache.felix.ipojo.ComponentInstance#removeInstanceStateListener(org.apache.felix.ipojo.InstanceStateListener)
      */
     public void removeInstanceStateListener(InstanceStateListener listener) {
-        int idx = -1;
-        for (int i = 0; i < m_instanceListeners.length; i++) {
-            if (m_instanceListeners[i] == listener) {
-                idx = i;
-                break;
-            }
-        }
-        
-        if (idx >= 0) {
-            if ((m_instanceListeners.length - 1) == 0) {
-                m_instanceListeners = new InstanceStateListener[0];
-            } else {
-                InstanceStateListener[] newInstances = new InstanceStateListener[m_instanceListeners.length - 1];
-                System.arraycopy(m_instanceListeners, 0, newInstances, 0, idx);
-                if (idx < newInstances.length) {
-                    System.arraycopy(m_instanceListeners, idx + 1, newInstances, idx, newInstances.length - idx);
-                }
-                m_instanceListeners = newInstances;
-            }
-        }
+        m_instanceListeners.remove(listener);
     }
 
     // ===================== end Lifecycle management =====================

Modified: felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/configuration/ConfigurableProperty.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/configuration/ConfigurableProperty.java?view=diff&rev=566960&r1=566959&r2=566960
==============================================================================
--- felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/configuration/ConfigurableProperty.java (original)
+++ felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/configuration/ConfigurableProperty.java Fri Aug 17 00:53:40 2007
@@ -67,18 +67,12 @@
      * Configurable Property Constructor. At least the method or the field need
      * to be referenced.
      * 
-     * @param name :
-     *            name of the property (optional)
-     * @param field :
-     *            name of the field
-     * @param method :
-     *            method name
-     * @param value :
-     *            initial value of the property (optional)
-     * @param type :
-     *            the type of the property
-     * @param ch :
-     *            configuration handler managing this configurable property
+     * @param name : name of the property (optional)
+     * @param field : name of the field
+     * @param method : method name
+     * @param value : initial value of the property (optional)
+     * @param type : the type of the property
+     * @param ch : configuration handler managing this configurable property
      */
     public ConfigurableProperty(String name, String field, String method, String value, String type,
             ConfigurationHandler ch) {
@@ -107,14 +101,13 @@
     /**
      * Set the value of the property.
      * 
-     * @param strValue :
-     *            value of the property (String)
-     * @param type :
-     *            type of the property
+     * @param strValue : value of the property (String)
+     * @param type : type of the property
      */
     private void setValue(String strValue, String type) {
         Object value = null;
-
+        
+        // Syntactic sugar to avoid writing java.lang.String
         if (type.equals("string") || type.equals("String")) {
             value = new String(strValue);
             m_type = java.lang.String.class;
@@ -202,10 +195,8 @@
     /**
      * Set array value to the current property.
      * 
-     * @param internalType :
-     *            type of the property
-     * @param values :
-     *            new property value
+     * @param internalType : type of the property
+     * @param values : new property value
      */
     private void setArrayValue(String internalType, String[] values) {
         if (internalType.equals("string") || internalType.equals("String")) {
@@ -345,8 +336,7 @@
     /**
      * Fix the value of the property.
      * 
-     * @param value :
-     *            the new value.
+     * @param value : the new value.
      */
     public void setValue(Object value) {
         m_value = value;
@@ -406,7 +396,7 @@
             m_handler.getInstanceManager().getFactory().getLogger().log(
                     Logger.ERROR,
                     "The method " + m_method + " in the class " + m_handler.getInstanceManager().getClassName()
-                            + "thorws an exception : " + e.getMessage());
+                            + "throws an exception : " + e.getMessage());
             return;
         }
     }

Added: felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/lifecycle/controller/ControllerHandler.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/lifecycle/controller/ControllerHandler.java?view=auto&rev=566960
==============================================================================
--- felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/lifecycle/controller/ControllerHandler.java (added)
+++ felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/lifecycle/controller/ControllerHandler.java Fri Aug 17 00:53:40 2007
@@ -0,0 +1,140 @@
+/* 
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.ipojo.handlers.lifecycle.controller;
+
+import java.util.Dictionary;
+
+import org.apache.felix.ipojo.Handler;
+import org.apache.felix.ipojo.InstanceManager;
+import org.apache.felix.ipojo.metadata.Element;
+import org.apache.felix.ipojo.parser.FieldMetadata;
+import org.apache.felix.ipojo.parser.ManipulationMetadata;
+import org.apache.felix.ipojo.util.Logger;
+
+/**
+ * Lifecycle Controller handler.
+ * This handler allow a POJO  to vote for the instance state. By setting a boolean field to true or false, the handler state changed.
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class ControllerHandler extends Handler {
+    
+    /**
+     * Instance Manager.
+     */
+    private InstanceManager m_manager;
+    
+    /**
+     * Actual handler (i.e. field value) state
+     */
+    private boolean m_state;
+
+    /**
+     * Configure method.
+     * Look for the first 'controller' element.
+     * @param im : instance manager
+     * @param metadata : metadata
+     * @param configuration : configuration
+     * @see org.apache.felix.ipojo.Handler#configure(org.apache.felix.ipojo.InstanceManager, org.apache.felix.ipojo.metadata.Element, java.util.Dictionary)
+     */
+    public void configure(InstanceManager im, Element metadata, Dictionary configuration) {
+        m_manager = im;
+        String field = null;
+        Element[] lc = metadata.getElements("controller");
+        if (lc.length > 0) {
+            // Use only the first controller
+            if (lc[0].containsAttribute("field")) {
+                field = lc[0].getAttribute("field");
+            } else {
+                m_manager.getFactory().getLogger().log(Logger.ERROR, "A lifecycle controler needs to contain a field attribute");
+                return;
+            }
+        } else {
+            return;
+        }
+        
+        ManipulationMetadata mm = new ManipulationMetadata(metadata);
+        FieldMetadata fm = mm.getField(field);
+        if (fm == null) {
+            m_manager.getFactory().getLogger().log(Logger.ERROR, "The field " + field + " does not exist in the class");
+            return;
+        }
+        
+        if (!fm.getFieldType().equalsIgnoreCase("boolean")) {
+            m_manager.getFactory().getLogger().log(Logger.ERROR, "The field " + field + " must be a boolean (" + fm.getFieldType() + " found)");
+            return;
+        }
+        
+        im.register(this, new FieldMetadata[] {fm}, null);
+    }
+
+    /**
+     * Start method.
+     * Nothing to do.
+     * @see org.apache.felix.ipojo.Handler#start()
+     */
+    public void start() { 
+        m_state = true;
+    }
+
+    /**
+     * Stop method.
+     * Nothing to do. 
+     * @see org.apache.felix.ipojo.Handler#stop()
+     */
+    public void stop() { }
+    
+    /**
+     * Return the field value.
+     * @return the field value (i.e. the handler state)
+     * @see org.apache.felix.ipojo.Handler#isValid()
+     */
+    public boolean isValid() {
+        return m_state;
+    }
+    
+    /**
+     * GetterCallback.
+     * Return the stored value.
+     * @param field : field name.
+     * @param o : value given by the previous handler.
+     * @return : the handler state.
+     */
+    public Object getterCallback(String field, Object o) {
+        return new Boolean(m_state);
+    }
+    
+    /**
+     * SetterCallback.
+     * Store the new field value & invalidate / validate the handler is required.
+     * @param field : field name.
+     * @param o : new value.
+     */
+    public void setterCallback(String field, Object o) {
+        if (o instanceof Boolean) {
+            boolean nv = ((Boolean) o).booleanValue();
+            if (nv != m_state) {
+                m_state = nv;
+                m_manager.checkInstanceState();
+            }
+        } else {
+            m_manager.getFactory().getLogger().log(Logger.ERROR, "Boolean expected");
+        }
+    }
+
+}

Modified: felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/providedservice/ProvidedService.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/providedservice/ProvidedService.java?view=diff&rev=566960&r1=566959&r2=566960
==============================================================================
--- felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/providedservice/ProvidedService.java (original)
+++ felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/providedservice/ProvidedService.java Fri Aug 17 00:53:40 2007
@@ -228,7 +228,7 @@
             for (int i = 0; i < m_serviceSpecification.length; i++) {
                 spec = spec + m_serviceSpecification[i] + ", ";
             }
-            // Contruct the service properties list
+            // Build the service properties list
             Properties serviceProperties = getServiceProperties();
 
             m_serviceRegistration = m_handler.getInstanceManager().getContext().registerService(m_serviceSpecification, this, serviceProperties);

Modified: felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/providedservice/ProvidedServiceHandler.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/providedservice/ProvidedServiceHandler.java?view=diff&rev=566960&r1=566959&r2=566960
==============================================================================
--- felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/providedservice/ProvidedServiceHandler.java (original)
+++ felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/providedservice/ProvidedServiceHandler.java Fri Aug 17 00:53:40 2007
@@ -382,7 +382,7 @@
      * java.lang.Object)
      */
     public void setterCallback(String fieldName, Object value) {
-        // Verify that the field name coreespond to a dependency
+        // Verify that the field name correspond to a dependency
         for (int i = 0; i < m_providedServices.length; i++) {
             ProvidedService ps = m_providedServices[i];
             boolean update = false;
@@ -433,7 +433,7 @@
      * @see org.apache.felix.ipojo.CompositeHandler#stateChanged(int)
      */
     public void stateChanged(int state) {
-        // If the new state is UNRESOLVED => unregister all the services
+        // If the new state is INVALID => unregister all the services
         if (state == InstanceManager.INVALID) {
             for (int i = 0; i < m_providedServices.length; i++) {
                 m_providedServices[i].unregisterService();
@@ -441,14 +441,13 @@
             return;
         }
 
-        // If the new state is VALID => regiter all the services
+        // If the new state is VALID => register all the services
         if (state == InstanceManager.VALID) {
             for (int i = 0; i < m_providedServices.length; i++) {
                 m_providedServices[i].registerService();
             }
             return;
         }
-
     }
 
     /**