Author: clement
Date: Thu Mar  6 08:35:31 2008
New Revision: 634335

URL: http://svn.apache.org/viewvc?rev=634335&view=rev
Log:
Add an onFinally callback in method interceptions.
Add a way for handler to get field value without listening an storing every 
changes.

Modified:
    
felix/sandbox/clement/ipojo/core/src/main/java/org/apache/felix/ipojo/InstanceManager.java
    
felix/sandbox/clement/ipojo/core/src/main/java/org/apache/felix/ipojo/PrimitiveHandler.java
    
felix/sandbox/clement/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/DependencyHandler.java

Modified: 
felix/sandbox/clement/ipojo/core/src/main/java/org/apache/felix/ipojo/InstanceManager.java
URL: 
http://svn.apache.org/viewvc/felix/sandbox/clement/ipojo/core/src/main/java/org/apache/felix/ipojo/InstanceManager.java?rev=634335&r1=634334&r2=634335&view=diff
==============================================================================
--- 
felix/sandbox/clement/ipojo/core/src/main/java/org/apache/felix/ipojo/InstanceManager.java
 (original)
+++ 
felix/sandbox/clement/ipojo/core/src/main/java/org/apache/felix/ipojo/InstanceManager.java
 Thu Mar  6 08:35:31 2008
@@ -18,7 +18,9 @@
  */
 package org.apache.felix.ipojo;
 
+import java.lang.reflect.AccessibleObject;
 import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.util.ArrayList;
@@ -160,8 +162,8 @@
      */
     public InstanceDescription getInstanceDescription() {
         int componentState = getState();
-        InstanceDescription desc = new InstanceDescription(m_name, 
componentState, getContext().getBundle().getBundleId(), m_factory
-                .getComponentDescription());
+        InstanceDescription desc =
+                new InstanceDescription(m_name, componentState, 
getContext().getBundle().getBundleId(), m_factory.getComponentDescription());
 
         if (m_pojoObjects != null) {
             String[] objects = new String[m_pojoObjects.size()];
@@ -198,12 +200,67 @@
     public Handler getHandler(String name) {
         for (int i = 0; i < m_handlers.length; i++) {
             HandlerFactory fact = (HandlerFactory) 
m_handlers[i].getHandler().getHandlerManager().getFactory();
-            if (fact.getHandlerName().equals(name)) { return 
m_handlers[i].getHandler(); }
+            if (fact.getHandlerName().equals(name)) {
+                return m_handlers[i].getHandler();
+            }
         }
         return null;
     }
 
     /**
+     * Give access to a field value to the first created pojo.
+     * This method process by analyzing both managed fields and pojo fields 
(by reflection).
+     * If no pojo were already created try only on managed fields.
+     * @param fieldName : field name.
+     * @return the field value, null is returned if the value is managed and 
not already set.
+     */
+    public synchronized Object getFieldValue(String fieldName) {
+        if (m_pojoObjects == null) {
+            return getFieldValue(fieldName, null);
+        } else {
+            return getFieldValue(fieldName, m_pojoObjects.get(0)); // Use the 
first pojo.
+        }
+    }
+
+    /**
+     * Give access to a field value to the given created pojo.
+     * This method process by analyzing both managed fields and pojo fields 
(by reflection).
+     * If the given pojo is null, try only on managed fields.
+     * @param fieldName : field name.
+     * @param pojo : the pojo on which computing field value.
+     * @return the field value, null is returned if the value is managed and 
not already set.
+     */
+    public synchronized Object getFieldValue(String fieldName, Object pojo) {
+        Object setByContainer = null;
+        
+        if (m_fields != null) {
+            setByContainer = m_fields.get(fieldName);
+        }
+        
+        if (setByContainer == null && pojo != null) { // In the case of no 
given pojo, return null.
+            // If null either the value was not already set or has the null 
value.
+            try {
+                Field field = pojo.getClass().getDeclaredField(fieldName);
+                if (!field.isAccessible()) {
+                    field.setAccessible(true);
+                }
+                return field.get(pojo);
+            } catch (SecurityException e) {
+                m_factory.getLogger().log(Logger.ERROR, "Cannot reflect on 
field " + fieldName + " to obtain the value : " + e.getMessage());
+            } catch (NoSuchFieldException e) {
+                m_factory.getLogger().log(Logger.ERROR, "Cannot reflect on 
field " + fieldName + " to obtain the value : " + e.getMessage());
+            } catch (IllegalArgumentException e) {
+                m_factory.getLogger().log(Logger.ERROR, "Cannot reflect on 
field " + fieldName + " to obtain the value : " + e.getMessage());
+            } catch (IllegalAccessException e) {
+                m_factory.getLogger().log(Logger.ERROR, "Cannot reflect on 
field " + fieldName + " to obtain the value : " + e.getMessage());
+            }
+            return null;
+        } else {
+            return setByContainer;
+        }
+    }
+
+    /**
      * Start the instance manager.
      */
     public synchronized void start() {
@@ -236,7 +293,9 @@
      * Stop the instance manager.
      */
     public synchronized void stop() {
-        if (m_state == STOPPED) { return; } // Instance already stopped
+        if (m_state == STOPPED) {
+            return;
+        } // Instance already stopped
 
         setState(INVALID);
 
@@ -289,8 +348,9 @@
     }
 
     /**
-     * Set the state of the component instance. 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.
+     * Set the state of the component instance. 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 synchronized void setState(int state) {
@@ -419,7 +479,9 @@
      * @return the created instance of the component instance.
      */
     public Object[] getPojoObjects() {
-        if (m_pojoObjects == null) { return null; }
+        if (m_pojoObjects == null) {
+            return null;
+        }
         return m_pojoObjects.toArray(new Object[m_pojoObjects.size()]);
     }
 
@@ -461,13 +523,17 @@
             } catch (SecurityException e) {
                 m_factory.getLogger().log(
                                           Logger.ERROR,
-                                          "[" + m_name + "] createInstance -> 
The Component Instance is not accessible (security reason) : "
+                                          "["
+                                                  + m_name
+                                                  + "] createInstance -> The 
Component Instance is not accessible (security reason) : "
                                                   + e.getMessage());
                 stop();
             } catch (InvocationTargetException e) {
                 m_factory.getLogger().log(
                                           Logger.ERROR,
-                                          "[" + m_name + "] createInstance -> 
Cannot invoke the constructor method (illegal target) : "
+                                          "["
+                                                  + m_name
+                                                  + "] createInstance -> 
Cannot invoke the constructor method (illegal target) : "
                                                   + 
e.getTargetException().getMessage());
                 onError(null, m_className, e.getTargetException());
                 stop();
@@ -505,7 +571,9 @@
                         // Error : factory-method not found
                         m_factory.getLogger().log(
                                                   Logger.ERROR,
-                                                  "[" + m_name + "] 
createInstance -> Cannot invoke the factory-method (method not found) : "
+                                                  "["
+                                                          + m_name
+                                                          + "] createInstance 
-> Cannot invoke the factory-method (method not found) : "
                                                           + e2.getMessage());
                         stop();
                     }
@@ -540,7 +608,9 @@
                 m_factory.getLogger()
                         .log(
                              Logger.ERROR,
-                             "[" + m_name + "] createInstance -> Cannot invoke 
the factory-method (the _setInstanceManager method does not exist) : "
+                             "["
+                                     + m_name
+                                     + "] createInstance -> Cannot invoke the 
factory-method (the _setInstanceManager method does not exist) : "
                                      + e.getMessage());
                 stop();
             }
@@ -567,7 +637,9 @@
      * @return the instance of the component instance to use for singleton 
component
      */
     public synchronized Object getPojoObject() {
-        if (m_pojoObjects == null) { return createPojoObject(); }
+        if (m_pojoObjects == null) {
+            return createPojoObject();
+        }
         return m_pojoObjects.get(0);
     }
 
@@ -620,7 +692,9 @@
                     m_methodRegistration.put(methods[i].getMethodIdentifier(), 
new PrimitiveHandler[] { handler });
                 } else {
                     for (int j = 0; j < list.length; j++) {
-                        if (list[j] == handler) { return; }
+                        if (list[j] == handler) {
+                            return;
+                        }
                     }
                     PrimitiveHandler[] newList = new 
PrimitiveHandler[list.length + 1];
                     System.arraycopy(list, 0, newList, 0, list.length);
@@ -633,7 +707,8 @@
     }
 
     /**
-     * This method is called by the manipulated class each time that a 
GETFIELD instruction is found. The method ask to each handler which value need 
to be returned.
+     * This method is called by the manipulated class each time that a 
GETFIELD instruction is found. The method ask to each handler which value need
+     * to be returned.
      * @param pojo : the pojo object on which the field was get
      * @param fieldName : the field name on which the GETFIELD instruction is 
called
      * @return the value decided by the last asked handler (throw a warning if 
two fields decide two different values)
@@ -642,8 +717,7 @@
         Object initialValue = m_fields.get(fieldName);
         Object result = initialValue;
         // Get the list of registered handlers
-        
-        
+
         PrimitiveHandler[] list = (PrimitiveHandler[]) 
m_fieldRegistration.get(fieldName);
         for (int i = 0; list != null && i < list.length; i++) {
             Object handlerResult = list[i].onGet(null, fieldName, 
initialValue);
@@ -654,7 +728,9 @@
                     if ((handlerResult != null && 
!handlerResult.equals(result)) || (result != null && handlerResult == null)) {
                         m_factory.getLogger().log(
                                                   Logger.WARNING,
-                                                  "A conflict was detected on 
the injection of " + fieldName + " - return the last value from "
+                                                  "A conflict was detected on 
the injection of "
+                                                          + fieldName
+                                                          + " - return the 
last value from "
                                                           + 
list[i].getHandlerManager().getInstanceName());
                     }
                 }
@@ -679,38 +755,55 @@
      * @param methodId : method id
      */
     public void onEntry(Object pojo, String methodId) {
-        if (m_methodRegistration == null) { return; }
+        if (m_methodRegistration == null) {
+            return;
+        }
         PrimitiveHandler[] list = (PrimitiveHandler[]) 
m_methodRegistration.get(methodId);
+        Method method = getMethodById(methodId);
         for (int i = 0; list != null && i < list.length; i++) {
-            list[i].onEntry(pojo, getMethodById(methodId));
+            list[i].onEntry(pojo, method);
         }
     }
 
     /**
-     * Dispatch exit method event on registered handler. The given returned 
object is an instance of Exception if the method has launched an exception. If 
the given object is null, either the method returns void, either the method has 
returned null.
+     * Dispatch exit method event on registered handler. The given returned 
object is an instance of Exception if the method has launched an
+     * exception. If the given object is null, either the method returns void, 
either the method has returned null.
      * @param pojo : the pojo object on which the method was invoked
      * @param methodId : method id
      * @param result : returned object.
      */
     public void onExit(Object pojo, String methodId, Object result) {
-        if (m_methodRegistration == null) { return; }
+        if (m_methodRegistration == null) {
+            return;
+        }
         PrimitiveHandler[] list = (PrimitiveHandler[]) 
m_methodRegistration.get(methodId);
+        Method method = getMethodById(methodId);
+        for (int i = 0; list != null && i < list.length; i++) {
+            list[i].onExit(pojo, method, result);
+        }
         for (int i = 0; list != null && i < list.length; i++) {
-            list[i].onExit(pojo, getMethodById(methodId), result);
+            list[i].onFinally(pojo, method);
         }
     }
 
     /**
-     * Dispatch error method event on registered handler. The given returned 
object is an instance of Exception if the method has thrown an exception. If 
the given object is null, either the method returns void, either the method has 
returned null.
+     * Dispatch error method event on registered handler. The given returned 
object is an instance of Exception if the method has thrown an exception.
+     * If the given object is null, either the method returns void, either the 
method has returned null.
      * @param pojo : the pojo object on which the method was invoked
      * @param methodId : method id
-     * @param error : returned throwable object.
+     * @param error : throwable object.
      */
     public void onError(Object pojo, String methodId, Throwable error) {
-        if (m_methodRegistration == null) { return; }
+        if (m_methodRegistration == null) {
+            return;
+        }
         PrimitiveHandler[] list = (PrimitiveHandler[]) 
m_methodRegistration.get(methodId);
+        Method method = getMethodById(methodId);
+        for (int i = 0; list != null && i < list.length; i++) {
+            list[i].onError(pojo, method, error);
+        }
         for (int i = 0; list != null && i < list.length; i++) {
-            list[i].onError(pojo, getMethodById(methodId), error);
+            list[i].onFinally(pojo, method);
         }
     }
 
@@ -725,13 +818,18 @@
             Method[] mets = m_clazz.getDeclaredMethods();
             for (int i = 0; i < mets.length; i++) {
                 // Check if the method was not already computed. If not, 
compute the Id and check.
-                if (! m_methods.containsValue(mets[i]) && 
(MethodMetadata.computeMethodId(mets[i]).equals(methodId))) {
+                if (!m_methods.containsValue(mets[i]) && 
(MethodMetadata.computeMethodId(mets[i]).equals(methodId))) {
                     // Store the new methodId
                     m_methods.put(methodId, mets[i]);
                     return mets[i];
                 }
             }
-            // Method not found : cannot happen.  
+            // If not found, it is a constructor, return null in this case.
+            if (methodId.equals(m_clazz.getName())) {
+                // Constructor.
+                return null;
+            }
+            // Cannot happen
             m_factory.getLogger().log(Logger.ERROR, "A methodID cannot be 
associate with a POJO method : " + methodId);
             return null;
         } else {
@@ -794,7 +892,9 @@
         if (m_state == INVALID) {
             // Try to revalidate the instance ofter reconfiguration
             for (int i = 0; i < m_handlers.length; i++) {
-                if (m_handlers[i].getState() != VALID) { return; }
+                if (m_handlers[i].getState() != VALID) {
+                    return;
+                }
             }
             setState(VALID);
         }
@@ -815,7 +915,9 @@
      * @see 
org.apache.felix.ipojo.InstanceStateListener#stateChanged(org.apache.felix.ipojo.ComponentInstance,
 int)
      */
     public synchronized void stateChanged(ComponentInstance instance, int 
newState) {
-        if (m_state <= STOPPED) { return; }
+        if (m_state <= STOPPED) {
+            return;
+        }
 
         // Update the component state if necessary
         if (newState == INVALID && m_state == VALID) {
@@ -826,7 +928,9 @@
         if (newState == VALID && m_state == INVALID) {
             // An handler becomes valid => check if all handlers are valid
             for (int i = 0; i < m_handlers.length; i++) {
-                if (m_handlers[i].getState() != VALID) { return; }
+                if (m_handlers[i].getState() != VALID) {
+                    return;
+                }
             }
             setState(VALID);
             return;
@@ -838,7 +942,9 @@
      * @return the set of registered fields.
      */
     public Set getRegistredFields() {
-        if (m_fieldRegistration == null) { return null; }
+        if (m_fieldRegistration == null) {
+            return null;
+        }
         return m_fieldRegistration.keySet();
     }
 

Modified: 
felix/sandbox/clement/ipojo/core/src/main/java/org/apache/felix/ipojo/PrimitiveHandler.java
URL: 
http://svn.apache.org/viewvc/felix/sandbox/clement/ipojo/core/src/main/java/org/apache/felix/ipojo/PrimitiveHandler.java?rev=634335&r1=634334&r2=634335&view=diff
==============================================================================
--- 
felix/sandbox/clement/ipojo/core/src/main/java/org/apache/felix/ipojo/PrimitiveHandler.java
 (original)
+++ 
felix/sandbox/clement/ipojo/core/src/main/java/org/apache/felix/ipojo/PrimitiveHandler.java
 Thu Mar  6 08:35:31 2008
@@ -147,6 +147,17 @@
     }
     
     /**
+     * This method is called when the execution of a method will terminate : 
+     * just before to throw an exception or before to return.
+     * OnError or OnExit was already called.
+     * @param pojo : the pojo on which the method was accessed.
+     * @param method : invoked method.
+     */
+    public void onFinally(Object pojo, Method method) {
+        // Nothing do do in the default implementation
+    }
+    
+    /**
      * This method is called when an instance of the component is created, but
      * before someone can use it.
      * @param instance : the created instance

Modified: 
felix/sandbox/clement/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/DependencyHandler.java
URL: 
http://svn.apache.org/viewvc/felix/sandbox/clement/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/DependencyHandler.java?rev=634335&r1=634334&r2=634335&view=diff
==============================================================================
--- 
felix/sandbox/clement/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/DependencyHandler.java
 (original)
+++ 
felix/sandbox/clement/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/DependencyHandler.java
 Thu Mar  6 08:35:31 2008
@@ -398,30 +398,18 @@
     }
 
     /**
-     * Method Exit callback.
+     * Method onFinally implementation.
      * @param pojo : pojo object on which the method was invoked.
      * @param method : method object representing the invoked method.
-     * @param returnedObj : returned object by the method.
-     * @see org.apache.felix.ipojo.Handler#onExit(Object, Method, 
java.lang.Object)
+     * @see 
org.apache.felix.ipojo.PrimitiveHandler#onFinally(java.lang.Object, 
java.lang.reflect.Method)
      */
-    public void onExit(Object pojo, Method method, Object returnedObj) {
+    public void onFinally(Object pojo, Method method) {
         for (int i = 0; i < m_dependencies.length; i++) {
             Dependency dep = m_dependencies[i];
-            if (dep.getField() != null) {
+            if (dep.getField() != null) { // Only field injection require to 
be notified. 
                 dep.exit();
             }
         }
-    }
-
-    /**
-     * Method Error callback.
-     * @param pojo : the pojo object on which the field is accessed
-     * @param method : method id.
-     * @param returnedObj : returned object.
-     * @see org.apache.felix.ipojo.Handler#onExit(Object, Method, 
java.lang.Object)
-     */
-    public void onError(Object pojo, Method method, Object returnedObj) {
-        onExit(pojo, method, returnedObj);
     }
 
     /**


Reply via email to