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);
}
/**