CAMEL-10396: Corrected a bug where BeanInfo was missing a method overload
Project: http://git-wip-us.apache.org/repos/asf/camel/repo Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/8889b827 Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/8889b827 Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/8889b827 Branch: refs/heads/master Commit: 8889b827193d6c5b08c801a4dbb457a43af2f958 Parents: ec7ffa1 Author: aldettinger <aldettin...@gmail.com> Authored: Sat Feb 18 16:28:55 2017 +0100 Committer: Claus Ibsen <davscl...@apache.org> Committed: Sun Feb 19 10:03:36 2017 +0100 ---------------------------------------------------------------------- .../apache/camel/component/bean/BeanInfo.java | 34 +++++++++++--------- .../org/apache/camel/util/ObjectHelper.java | 9 ++++++ .../camel/component/bean/MyOtherFooBean.java | 11 +++++-- .../org/apache/camel/util/ObjectHelperTest.java | 24 ++++++++++++++ 4 files changed, 59 insertions(+), 19 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/camel/blob/8889b827/camel-core/src/main/java/org/apache/camel/component/bean/BeanInfo.java ---------------------------------------------------------------------- diff --git a/camel-core/src/main/java/org/apache/camel/component/bean/BeanInfo.java b/camel-core/src/main/java/org/apache/camel/component/bean/BeanInfo.java index ffeea3e..1efe61c 100644 --- a/camel-core/src/main/java/org/apache/camel/component/bean/BeanInfo.java +++ b/camel-core/src/main/java/org/apache/camel/component/bean/BeanInfo.java @@ -405,10 +405,8 @@ public class BeanInfo { MethodInfo methodInfo = createMethodInfo(clazz, method); - // methods already registered should be preferred to use instead of super classes of existing methods - // we want to us the method from the sub class over super classes, so if we have already registered - // the method then use it (we are traversing upwards: sub (child) -> super (farther) ) - MethodInfo existingMethodInfo = overridesExistingMethod(methodInfo); + // Foster the use of a potentially already registered most specific override + MethodInfo existingMethodInfo = findMostSpecificOverride(methodInfo); if (existingMethodInfo != null) { LOG.trace("This method is already overridden in a subclass, so the method from the sub class is preferred: {}", existingMethodInfo); return existingMethodInfo; @@ -905,20 +903,24 @@ public class BeanInfo { } /** - * Does the given method info override an existing method registered before (from a subclass) + * Gets the most specific override of a given method, if any. Indeed, + * overrides may have already been found while inspecting sub classes. Or + * the given method could override an interface extra method. * - * @param methodInfo the method to test - * @return the already registered method to use, null if not overriding any + * @param proposedMethodInfo the method for which a more specific override is + * searched + * @return The already registered most specific override if any, otherwise + * <code>null</code> */ - private MethodInfo overridesExistingMethod(MethodInfo methodInfo) { - for (MethodInfo info : methodMap.values()) { - Method source = info.getMethod(); - Method target = methodInfo.getMethod(); - - boolean override = ObjectHelper.isOverridingMethod(source, target); - if (override) { - // same name, same parameters, then its overrides an existing class - return info; + private MethodInfo findMostSpecificOverride(MethodInfo proposedMethodInfo) { + for (MethodInfo alreadyRegisteredMethodInfo : methodMap.values()) { + Method alreadyRegisteredMethod = alreadyRegisteredMethodInfo.getMethod(); + Method proposedMethod = proposedMethodInfo.getMethod(); + + if (ObjectHelper.isOverridingMethod(proposedMethod, alreadyRegisteredMethod, false)) { + return alreadyRegisteredMethodInfo; + } else if (ObjectHelper.isOverridingMethod(alreadyRegisteredMethod, proposedMethod, false)) { + return proposedMethodInfo; } } http://git-wip-us.apache.org/repos/asf/camel/blob/8889b827/camel-core/src/main/java/org/apache/camel/util/ObjectHelper.java ---------------------------------------------------------------------- diff --git a/camel-core/src/main/java/org/apache/camel/util/ObjectHelper.java b/camel-core/src/main/java/org/apache/camel/util/ObjectHelper.java index 7331437..b87cbc6 100644 --- a/camel-core/src/main/java/org/apache/camel/util/ObjectHelper.java +++ b/camel-core/src/main/java/org/apache/camel/util/ObjectHelper.java @@ -1327,6 +1327,15 @@ public final class ObjectHelper { * @return <tt>true</tt> if it override, <tt>false</tt> otherwise */ public static boolean isOverridingMethod(Method source, Method target, boolean exact) { + + if (source.equals(target)) { + return true; + } else if (source.getDeclaringClass() == target.getDeclaringClass()) { + return false; + } else if (!source.getDeclaringClass().isAssignableFrom(target.getDeclaringClass())) { + return false; + } + if (!source.getName().equals(target.getName())) { return false; } http://git-wip-us.apache.org/repos/asf/camel/blob/8889b827/camel-core/src/test/java/org/apache/camel/component/bean/MyOtherFooBean.java ---------------------------------------------------------------------- diff --git a/camel-core/src/test/java/org/apache/camel/component/bean/MyOtherFooBean.java b/camel-core/src/test/java/org/apache/camel/component/bean/MyOtherFooBean.java index 0333478..fa2a519 100644 --- a/camel-core/src/test/java/org/apache/camel/component/bean/MyOtherFooBean.java +++ b/camel-core/src/test/java/org/apache/camel/component/bean/MyOtherFooBean.java @@ -16,9 +16,6 @@ */ package org.apache.camel.component.bean; -/** - * @version - */ public class MyOtherFooBean { public String echo(String s) { @@ -28,4 +25,12 @@ public class MyOtherFooBean { public Integer echo(Integer i) { return i.intValue() * i.intValue(); } + + public String toString(Object input) { + return "toString(Object) was called"; + } + + public String toString(String input) { + return "toString(String) was called"; + } } http://git-wip-us.apache.org/repos/asf/camel/blob/8889b827/camel-core/src/test/java/org/apache/camel/util/ObjectHelperTest.java ---------------------------------------------------------------------- diff --git a/camel-core/src/test/java/org/apache/camel/util/ObjectHelperTest.java b/camel-core/src/test/java/org/apache/camel/util/ObjectHelperTest.java index 0253eca..7997664 100644 --- a/camel-core/src/test/java/org/apache/camel/util/ObjectHelperTest.java +++ b/camel-core/src/test/java/org/apache/camel/util/ObjectHelperTest.java @@ -37,6 +37,7 @@ import junit.framework.TestCase; import org.apache.camel.CamelContext; import org.apache.camel.Exchange; import org.apache.camel.Message; +import org.apache.camel.component.bean.MyOtherFooBean; import org.apache.camel.component.bean.MyStaticClass; import org.apache.camel.impl.DefaultCamelContext; import org.apache.camel.impl.DefaultMessage; @@ -866,4 +867,27 @@ public class ObjectHelperTest extends TestCase { assertEquals("expected2 must be specified on: holder", iae.getMessage()); } } + + public void testSameMethodIsOverride() throws Exception { + Method m = MyOtherFooBean.class.getMethod("toString", Object.class); + assertTrue(ObjectHelper.isOverridingMethod(m, m, false)); + } + + public void testOverloadIsNotOverride() throws Exception { + Method m1 = MyOtherFooBean.class.getMethod("toString", Object.class); + Method m2 = MyOtherFooBean.class.getMethod("toString", String.class); + assertFalse(ObjectHelper.isOverridingMethod(m2, m1, false)); + } + + public void testOverrideEquivalentSignatureFromSiblingClassIsNotOverride() throws Exception { + Method m1 = Double.class.getMethod("intValue"); + Method m2 = Float.class.getMethod("intValue"); + assertFalse(ObjectHelper.isOverridingMethod(m2, m1, false)); + } + + public void testOverrideEquivalentSignatureFromUpperClassIsOverride() throws Exception { + Method m1 = Double.class.getMethod("intValue"); + Method m2 = Number.class.getMethod("intValue"); + assertTrue(ObjectHelper.isOverridingMethod(m2, m1, false)); + } }