From c6c683e8acfc4b188fa4af2f0293a43a33e39a4c Mon Sep 17 00:00:00 2001 From: Marc Prud'hommeaux Date: Thu, 14 Sep 2006 23:06:11 +0000 Subject: [PATCH] Allow callback methods to accept the Entity subclass of the type they are listening on, rather than forcing them to all take an argument of type java.lang.Object (section 3.5.1) git-svn-id: https://svn.apache.org/repos/asf/incubator/openjpa/trunk@443509 13f79535-47bb-0310-9956-ffa450edef68 --- .../openjpa/event/BeanLifecycleCallbacks.java | 5 +-- .../event/MethodLifecycleCallbacks.java | 36 +++++++++++++++++-- .../openjpa/meta/InterfaceImplGenerator.java | 2 +- .../apache/openjpa/event/localizer.properties | 3 +- .../XMLPersistenceMetaDataParser.java | 7 +++- 5 files changed, 46 insertions(+), 7 deletions(-) diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/event/BeanLifecycleCallbacks.java b/openjpa-kernel/src/main/java/org/apache/openjpa/event/BeanLifecycleCallbacks.java index 183dc53cf..89fe2eac1 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/event/BeanLifecycleCallbacks.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/event/BeanLifecycleCallbacks.java @@ -38,9 +38,10 @@ public class BeanLifecycleCallbacks * * @arg whether another argunent is expected such as AfterDetach */ - public BeanLifecycleCallbacks(Class cls, String method, boolean arg) { + public BeanLifecycleCallbacks(Class cls, String method, boolean arg, + Class type) { this(cls, getMethod(cls, method, arg ? new Class[]{ Object.class, - Object.class } : new Class[]{ Object.class }), arg); + type } : new Class[]{ type }), arg); } /** diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/event/MethodLifecycleCallbacks.java b/openjpa-kernel/src/main/java/org/apache/openjpa/event/MethodLifecycleCallbacks.java index 6b9a52cc1..e6ed34b48 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/event/MethodLifecycleCallbacks.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/event/MethodLifecycleCallbacks.java @@ -16,6 +16,7 @@ package org.apache.openjpa.event; import java.lang.reflect.Method; +import java.util.Arrays; import org.apache.openjpa.lib.util.Localizer; import org.apache.openjpa.util.UserException; @@ -92,7 +93,14 @@ public class MethodLifecycleCallbacks */ protected static Method getMethod(Class cls, String method, Class[] args) { try { - return cls.getMethod(method, args); + Method[] methods = cls.getMethods(); + for (int i = 0; i < methods.length; i++) { + if (!method.equals(methods[i].getName())) + continue; + + if (isAssignable(methods[i].getParameterTypes(), args)) + return methods[i]; + } } catch (Throwable t) { try { // try again with the declared methods, which will @@ -103,8 +111,32 @@ public class MethodLifecycleCallbacks return m; } catch (Throwable t2) { throw new UserException(_loc.get("method-notfound", - cls.getName(), method), t); + cls.getName(), method, + args == null ? null : Arrays.asList(args)), t); } } + + throw new UserException(_loc.get("method-notfound", + cls.getName(), method, + args == null ? null : Arrays.asList(args))); } + + /** + * Returns true if all parameters in the from array are assignable + * from the corresponding parameters of the to array. + */ + private static boolean isAssignable(Class[] from, Class[] to) { + if (from == null) + return to == null; + + if (from.length != to.length) + return false; + + for (int i = 0; i < from.length; i++) { + if (from[i] == null || !from[i].isAssignableFrom(to[i])) + return false; + } + + return true; + } } diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/meta/InterfaceImplGenerator.java b/openjpa-kernel/src/main/java/org/apache/openjpa/meta/InterfaceImplGenerator.java index c39df669e..0487c4056 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/meta/InterfaceImplGenerator.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/meta/InterfaceImplGenerator.java @@ -205,7 +205,7 @@ class InterfaceImplGenerator { return true; try { Method meth = iface.getDeclaredMethod("is" + StringUtils.capitalize - (fmd.getName()), null); + (fmd.getName()), (Class[]) null); return meth == null; } catch (NoSuchMethodException e) {} return true; diff --git a/openjpa-kernel/src/main/resources/org/apache/openjpa/event/localizer.properties b/openjpa-kernel/src/main/resources/org/apache/openjpa/event/localizer.properties index 5f1679100..ef0994dc4 100644 --- a/openjpa-kernel/src/main/resources/org/apache/openjpa/event/localizer.properties +++ b/openjpa-kernel/src/main/resources/org/apache/openjpa/event/localizer.properties @@ -75,4 +75,5 @@ tcp-close-pool-error: Exception thrown while closing connection pool. tcp-wrong-version-error: Received packet from "{0}" with invalid version \ number. Check if a prior release of OpenJPA is being used on this host. bean-constructor: Could not instantiate class {0}. -method-notfound: Method "{1}" not found in class "{0}". +method-notfound: Method "{1}" with arguments of type: {2} \ + not found in class "{0}". diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/XMLPersistenceMetaDataParser.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/XMLPersistenceMetaDataParser.java index 5e4e0c472..fd5899980 100644 --- a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/XMLPersistenceMetaDataParser.java +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/XMLPersistenceMetaDataParser.java @@ -1528,6 +1528,11 @@ public class XMLPersistenceMetaDataParser return false; boolean system = currentElement() == null; + Class type = currentElement() == null ? null : + ((ClassMetaData) currentElement()).getDescribedType(); + if (type == null) + type = Object.class; + if (_callbacks == null) { _callbacks = (Collection[]) new Collection[LifecycleEvent.ALL_EVENTS.length]; @@ -1538,7 +1543,7 @@ public class XMLPersistenceMetaDataParser LifecycleCallbacks adapter; if (_listener != null) adapter = new BeanLifecycleCallbacks(_listener, - attrs.getValue("method-name"), false); + attrs.getValue("method-name"), false, type); else adapter = new MethodLifecycleCallbacks(_cls, attrs.getValue("method-name"), false);