Fixed https://issues.apache.org/jira/browse/FELIX-3144
The MethodInterceptors receive a Member instead of a Method. The received object can be either a Method or a Constructor.
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1179231 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/ipojo/core/pom.xml b/ipojo/core/pom.xml
index 9ded33b..4bd0792 100644
--- a/ipojo/core/pom.xml
+++ b/ipojo/core/pom.xml
@@ -30,7 +30,10 @@
<version>1.9.0-SNAPSHOT</version>
<properties>
- <ipojo.package.version>1.8.0</ipojo.package.version>
+ <!--
+ * 1.8.1 : change in the MethodInterceptor interface (FELIX-3144)
+ -->
+ <ipojo.package.version>1.8.1</ipojo.package.version>
</properties>
<description>
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/InstanceManager.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/InstanceManager.java
index 836614a..1d9c6b9 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/InstanceManager.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/InstanceManager.java
@@ -21,6 +21,7 @@
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Dictionary;
@@ -1090,7 +1091,7 @@
return;
}
MethodInterceptor[] list = (MethodInterceptor[]) m_methodRegistration.get(methodId);
- Method method = getMethodById(methodId);
+ Member method = getMethodById(methodId);
// In case of a constructor, the method is null, and the list is null too.
for (int i = 0; list != null && i < list.length; i++) {
list[i].onEntry(pojo, method, args); // Outside a synchronized block.
@@ -1113,7 +1114,7 @@
return;
}
MethodInterceptor[] list = (MethodInterceptor[]) m_methodRegistration.get(methodId);
- Method method = getMethodById(methodId);
+ Member method = getMethodById(methodId);
for (int i = 0; list != null && i < list.length; i++) {
list[i].onExit(pojo, method, result);
}
@@ -1137,7 +1138,7 @@
return;
}
MethodInterceptor[] list = (MethodInterceptor[]) m_methodRegistration.get(methodId);
- Method method = getMethodById(methodId);
+ Member method = getMethodById(methodId);
for (int i = 0; list != null && i < list.length; i++) {
list[i].onError(pojo, method, error);
}
@@ -1153,10 +1154,12 @@
* @param methodId the method id
* @return the method object or <code>null</code> if the method cannot be found.
*/
- private Method getMethodById(String methodId) {
+ private Member getMethodById(String methodId) {
// Not necessary synchronized as recomputing the methodID will give the same Method twice.
- Method method = (Method) m_methods.get(methodId);
- if (method == null && m_clazz != null) {
+ Member member = (Member) m_methods.get(methodId);
+ if (member == null && m_clazz != null) {
+
+ // First try on methods.
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.
@@ -1166,16 +1169,25 @@
return mets[i];
}
}
- // If not found, it is a constructor, return null in this case.
+
+ // If not found, it is a constructor, return the constructor object in this case.
if (methodId.startsWith(MethodMetadata.CONSTRUCTOR_PREFIX)) {
- // Constructor.
- return null;
+ Constructor[] constructors = m_clazz.getDeclaredConstructors();
+ for (int i = 0; i < constructors.length; i++) {
+ // Check if the constructor was not already computed. If not, compute the Id and check.
+ if (!m_methods.containsValue(constructors[i]) && (MethodMetadata.computeMethodId(constructors[i]).equals(methodId))) {
+ // Store the new methodId
+ m_methods.put(methodId, constructors[i]);
+ return constructors[i];
+ }
+ }
}
+
// Cannot happen
- m_logger.log(Logger.ERROR, "A methodID cannot be associated with a method from the POJO class: " + methodId);
+ m_logger.log(Logger.INFO, "A methodID cannot be associated with a method from the POJO class: " + methodId);
return null;
} else {
- return method;
+ return member;
}
}
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/MethodInterceptor.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/MethodInterceptor.java
index c74a11c..15560fe 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/MethodInterceptor.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/MethodInterceptor.java
@@ -1,4 +1,4 @@
-/*
+/*
* 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
@@ -18,21 +18,26 @@
*/
package org.apache.felix.ipojo;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Member;
import java.lang.reflect.Method;
/**
* Method interceptor.
* A class implementing this interface is able to be notified of method invocations (
* i.e. entries, exits, and errors).
-* The listener needs to be register on the instance manager with the
+* The listener needs to be register on the instance manager with the
* {@link InstanceManager#register(org.apache.felix.ipojo.parser.MethodMetadata, MethodInterceptor)}
-* method.
-* Events are sent before the method entry (onEntry), after the method returns (onExit),
-* when an error is thrown by the method (onError), and before the after either a returns or an error (onFinally)
+* method.
+* Events are sent before the method entry (onEntry), after the method returns (onExit),
+* when an error is thrown by the method (onError), and before the after either a returns or an error (onFinally).
+*
+* Instead of a {@link Method} object, the callbacks received a {@link Member} object which can be either a {@link Method}
+* or a {@link Constructor}.
* @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
*/
public interface MethodInterceptor {
-
+
/**
* This method is called when a thread enters in a method.
* The given argument array is created from the method argument.
@@ -40,36 +45,36 @@
* @param method the invoked method.
* @param args the arguments array.
*/
- void onEntry(Object pojo, Method method, Object[] args);
+ void onEntry(Object pojo, Member method, Object[] args);
/**
* This method is called when the execution exits a method :
* before a <code>return</code>.
- * If the given returned object is <code>null</code>, either the method is
+ * If the given returned object is <code>null</code>, either the method is
* <code>void</code>, or it returns <code>null</code>.
* This method must not modify the returned object.
* @param pojo the pojo on which the method exits.
* @param method the exiting method.
* @param returnedObj the the returned object (boxed for primitive type)
*/
- void onExit(Object pojo, Method method, Object returnedObj);
-
+ void onExit(Object pojo, Member method, Object returnedObj);
+
/**
- * This method is called when the execution throws an exception in the given
+ * This method is called when the execution throws an exception in the given
* method.
* @param pojo the pojo on which the method was accessed.
* @param method the invoked method.
* @param throwable the thrown exception
*/
- void onError(Object pojo, Method method, Throwable throwable);
-
+ void onError(Object pojo, Member method, Throwable throwable);
+
/**
- * This method is called when the execution of a method is going to terminate :
+ * This method is called when the execution of a method is going to 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 the invoked method.
*/
- void onFinally(Object pojo, Method method);
+ void onFinally(Object pojo, Member method);
}
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/PrimitiveHandler.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/PrimitiveHandler.java
index 1e5069c..2d70f25 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/PrimitiveHandler.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/PrimitiveHandler.java
@@ -18,6 +18,7 @@
*/
package org.apache.felix.ipojo;
+import java.lang.reflect.Member;
import java.lang.reflect.Method;
import org.apache.felix.ipojo.parser.PojoMetadata;
@@ -34,7 +35,7 @@
* @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
*/
public abstract class PrimitiveHandler extends Handler implements FieldInterceptor, MethodInterceptor,
- ConstructorInjector {
+ ConstructorInjector {
/**
* The "Primitive" Handler type (value).
@@ -52,10 +53,10 @@
*/
private ComponentFactory m_factory;
- /**
- * Instance Logger used by the handler.
- */
- private Logger m_instanceLogger;
+ /**
+ * Instance Logger used by the handler.
+ */
+ private Logger m_instanceLogger;
/**
* Attaches the current handler to the given instance.
@@ -83,9 +84,9 @@
* @see org.apache.felix.ipojo.Handler#getLogger()
*/
public Logger getLogger() {
- if (m_instanceLogger == null) {
- return m_factory.getLogger();
- }
+ if (m_instanceLogger == null) {
+ return m_factory.getLogger();
+ }
return m_instanceLogger;
}
@@ -167,7 +168,7 @@
* @see org.apache.felix.ipojo.ConstructorInjector#getConstructorParameter(int)
*/
public Object getConstructorParameter(int index) {
- return null;
+ return null;
}
/**
@@ -182,7 +183,7 @@
* @see org.apache.felix.ipojo.ConstructorInjector#getConstructorParameterType(int)
*/
public Class getConstructorParameterType(int index) {
- return null;
+ return null;
}
/**
@@ -193,7 +194,7 @@
* @param args the arguments array.
* @see MethodInterceptor#onEntry(Object, Method, Object[])
*/
- public void onEntry(Object pojo, Method method, Object[] args) {
+ public void onEntry(Object pojo, Member method, Object[] args) {
// Nothing to do in the default implementation
}
@@ -209,7 +210,7 @@
* @param returnedObj the returned object (boxed for primitive type)
* @see MethodInterceptor#onExit(Object, Method, Object)
*/
- public void onExit(Object pojo, Method method, Object returnedObj) {
+ public void onExit(Object pojo, Member method, Object returnedObj) {
// Nothing to do in the default implementation
}
@@ -223,7 +224,7 @@
* @param throwable the thrown exception
* @see org.apache.felix.ipojo.MethodInterceptor#onError(java.lang.Object, java.lang.reflect.Method, java.lang.Throwable)
*/
- public void onError(Object pojo, Method method, Throwable throwable) {
+ public void onError(Object pojo, Member method, Throwable throwable) {
// Nothing to do in the default implementation
}
@@ -237,7 +238,7 @@
* @param pojo the pojo on which the method was accessed.
* @param method the invoked method.
*/
- public void onFinally(Object pojo, Method method) {
+ public void onFinally(Object pojo, Member method) {
// Nothing to do in the default implementation
}
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/Dependency.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/Dependency.java
index c6419ba..eb45ae7 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/Dependency.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/Dependency.java
@@ -22,6 +22,7 @@
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
@@ -50,7 +51,7 @@
* @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
*/
public class Dependency extends DependencyModel implements FieldInterceptor, MethodInterceptor,
- ConstructorInjector {
+ ConstructorInjector {
/**
* Reference on the Dependency Handler.
@@ -213,9 +214,9 @@
protected void addConstructorInjection(int index) throws ConfigurationException {
- m_index = index;
- m_usage = new ServiceUsage();
- m_handler.getInstanceManager().register(index, this);
+ m_index = index;
+ m_usage = new ServiceUsage();
+ m_handler.getInstanceManager().register(index, this);
}
/**
@@ -268,7 +269,7 @@
// This may happen during refresh.
// So we just return.
if (refs == null) {
- return;
+ return;
}
// Call bind callback.
@@ -358,9 +359,9 @@
}
private Object createNullableObject() {
- // To load the proxy we use the POJO class loader. Indeed, this classloader imports iPOJO (so can access to Nullable) and has
+ // To load the proxy we use the POJO class loader. Indeed, this classloader imports iPOJO (so can access to Nullable) and has
// access to the service specification.
- try {
+ try {
ClassLoader cl = new NullableClassLoader(
getHandler().getInstanceManager().getClazz().getClassLoader(),
getSpecification().getClassLoader());
@@ -391,7 +392,7 @@
if (m_di == null) {
// If nullable are supported, create the nullable object.
if (m_supportNullable) {
- createNullableObject();
+ createNullableObject();
}
} else {
// Create the default-implementation object.
@@ -414,20 +415,20 @@
if (isAggregate()) {
m_proxyObject = new ServiceCollection(this);
} else {
- // Can we really proxy ? We can proxy only interfaces.
- if (getSpecification().isInterface()) {
- String type = getHandler().getInstanceManager().getContext().getProperty(DependencyHandler.PROXY_TYPE_PROPERTY);
- if (type == null || type.equals(DependencyHandler.SMART_PROXY)) {
- SmartProxyFactory proxyFactory = new SmartProxyFactory(this.getClass().getClassLoader());
- m_proxyObject = proxyFactory.getProxy(getSpecification(), this);
- } else {
- DynamicProxyFactory proxyFactory = new DynamicProxyFactory();
- m_proxyObject = proxyFactory.getProxy(getSpecification());
- }
- } else {
- m_handler.warn("Cannot create a proxy for a service dependency which is not an interface " +
- "- disabling proxy for " + getId());
- }
+ // Can we really proxy ? We can proxy only interfaces.
+ if (getSpecification().isInterface()) {
+ String type = getHandler().getInstanceManager().getContext().getProperty(DependencyHandler.PROXY_TYPE_PROPERTY);
+ if (type == null || type.equals(DependencyHandler.SMART_PROXY)) {
+ SmartProxyFactory proxyFactory = new SmartProxyFactory(this.getClass().getClassLoader());
+ m_proxyObject = proxyFactory.getProxy(getSpecification(), this);
+ } else {
+ DynamicProxyFactory proxyFactory = new DynamicProxyFactory();
+ m_proxyObject = proxyFactory.getProxy(getSpecification());
+ }
+ } else {
+ m_handler.warn("Cannot create a proxy for a service dependency which is not an interface " +
+ "- disabling proxy for " + getId());
+ }
}
}
@@ -737,7 +738,7 @@
* @param args : arguments
* @see org.apache.felix.ipojo.MethodInterceptor#onEntry(java.lang.Object, java.lang.reflect.Method, java.lang.Object[])
*/
- public void onEntry(Object pojo, Method method, Object[] args) {
+ public void onEntry(Object pojo, Member method, Object[] args) {
if (m_usage != null) {
Usage usage = (Usage) m_usage.get();
usage.incComponentStack(); // Increment the number of component access.
@@ -756,7 +757,7 @@
* @param throwable : thrown error
* @see org.apache.felix.ipojo.MethodInterceptor#onError(java.lang.Object, java.lang.reflect.Method, java.lang.Throwable)
*/
- public void onError(Object pojo, Method method, Throwable throwable) {
+ public void onError(Object pojo, Member method, Throwable throwable) {
// Nothing to do : wait onFinally
}
@@ -767,7 +768,7 @@
* @param returnedObj : returned object (null for void method)
* @see org.apache.felix.ipojo.MethodInterceptor#onExit(java.lang.Object, java.lang.reflect.Method, java.lang.Object)
*/
- public void onExit(Object pojo, Method method, Object returnedObj) {
+ public void onExit(Object pojo, Member method, Object returnedObj) {
// Nothing to do : wait onFinally
}
@@ -777,7 +778,7 @@
* @param method : Method object.
* @see org.apache.felix.ipojo.MethodInterceptor#onFinally(java.lang.Object, java.lang.reflect.Method)
*/
- public void onFinally(Object pojo, Method method) {
+ public void onFinally(Object pojo, Member method) {
if (m_usage != null) {
Usage usage = (Usage) m_usage.get();
usage.decComponentStack();
@@ -891,10 +892,10 @@
*/
protected Class getProxyClass(Class clazz) {
byte[] clz = ProxyGenerator.dumpProxy(clazz); // Generate the proxy.
- // Turn around the VM changes (FELIX-2716) about java.* classes.
+ // Turn around the VM changes (FELIX-2716) about java.* classes.
String cn = clazz.getName();
if (cn.startsWith("java.")) {
- cn = "$" + cn;
+ cn = "$" + cn;
}
return defineClass(cn + "$$Proxy", clz, 0, clz.length);
}
@@ -1015,52 +1016,52 @@
}
- /**
- * Gets the constructor parameter.
- * @return the index of the constructor parameter,
- * or <code>-1</code> if not set.
- */
- public int getConstructorParameterIndex() {
- return m_index;
- }
+ /**
+ * Gets the constructor parameter.
+ * @return the index of the constructor parameter,
+ * or <code>-1</code> if not set.
+ */
+ public int getConstructorParameterIndex() {
+ return m_index;
+ }
- /**
- * Gets the object to inject in the constructor parameter.
- * @param index the index of the parameter
- * @return the created proxy object
- * @see org.apache.felix.ipojo.ConstructorInjector#getConstructorParameter(int)
- */
- public Object getConstructorParameter(int index) {
- if (m_index == index && m_proxyObject != null) {
- return m_proxyObject;
- }
- return null;
- }
+ /**
+ * Gets the object to inject in the constructor parameter.
+ * @param index the index of the parameter
+ * @return the created proxy object
+ * @see org.apache.felix.ipojo.ConstructorInjector#getConstructorParameter(int)
+ */
+ public Object getConstructorParameter(int index) {
+ if (m_index == index && m_proxyObject != null) {
+ return m_proxyObject;
+ }
+ return null;
+ }
- /**
- * Gets the type of the constructor parameter.
- * @param index the parameter index
- * @return the class of the object. For scalar dependency, it's the
- * specification, for aggregate it depends of the container object:
- * {@link List} or {@link Set}.
- * @see org.apache.felix.ipojo.ConstructorInjector#getConstructorParameterType(int)
- */
- public Class getConstructorParameterType(int index) {
- if (m_index == index && m_proxyObject != null) {
- if (isAggregate()) {
- switch (m_type) {
- case DependencyHandler.LIST: return List.class;
- case DependencyHandler.SET : return Set.class;
- //TODO We should also manage the Collection type.
- default: return null; // Should never happen, it was checked before.
- }
- } else {
- return getSpecification();
- }
- } else {
- return null;
- }
- }
+ /**
+ * Gets the type of the constructor parameter.
+ * @param index the parameter index
+ * @return the class of the object. For scalar dependency, it's the
+ * specification, for aggregate it depends of the container object:
+ * {@link List} or {@link Set}.
+ * @see org.apache.felix.ipojo.ConstructorInjector#getConstructorParameterType(int)
+ */
+ public Class getConstructorParameterType(int index) {
+ if (m_index == index && m_proxyObject != null) {
+ if (isAggregate()) {
+ switch (m_type) {
+ case DependencyHandler.LIST: return List.class;
+ case DependencyHandler.SET : return Set.class;
+ //TODO We should also manage the Collection type.
+ default: return null; // Should never happen, it was checked before.
+ }
+ } else {
+ return getSpecification();
+ }
+ } else {
+ return null;
+ }
+ }