CAMEL-11235: Resolved an issue where a method inherited from a superclass overrides a superinterface method
Project: http://git-wip-us.apache.org/repos/asf/camel/repo Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/04c4de84 Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/04c4de84 Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/04c4de84 Branch: refs/heads/camel-2.19.x Commit: 04c4de84687579b1f26fb536c21b0ad90d1fbeb1 Parents: 6d820de Author: aldettinger <aldettin...@gmail.com> Authored: Sat May 20 12:18:57 2017 +0200 Committer: Claus Ibsen <davscl...@apache.org> Committed: Sat May 20 15:53:49 2017 +0200 ---------------------------------------------------------------------- .../apache/camel/component/bean/BeanInfo.java | 46 ++++++-------------- .../org/apache/camel/util/ObjectHelper.java | 20 ++++++++- .../camel/component/bean/MyOtherFooBean.java | 17 ++++++++ .../org/apache/camel/util/ObjectHelperTest.java | 15 +++++++ 4 files changed, 65 insertions(+), 33 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/camel/blob/04c4de84/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 1efe61c..f87e4a4 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 @@ -328,7 +328,7 @@ public class BeanInfo { methods.addAll(extraMethods); } - Set<Method> overrides = new HashSet<Method>(); + Set<Method> overriddenMethods = new HashSet<Method>(); // do not remove duplicates form class from the Java itself as they have some "duplicates" we need boolean javaClass = clazz.getName().startsWith("java.") || clazz.getName().startsWith("javax."); @@ -343,38 +343,17 @@ public class BeanInfo { for (Method target : methods) { // skip ourselves - if (ObjectHelper.isOverridingMethod(source, target, true)) { + if (ObjectHelper.isOverridingMethod(getType(), source, target, true)) { continue; } // skip duplicates which may be assign compatible (favor keep first added method when duplicate) - if (ObjectHelper.isOverridingMethod(source, target, false)) { - overrides.add(target); + if (ObjectHelper.isOverridingMethod(getType(), source, target, false)) { + overriddenMethods.add(target); } } } - methods.removeAll(overrides); - overrides.clear(); - } - - // if we are a public class, then add non duplicate interface classes also - if (Modifier.isPublic(clazz.getModifiers())) { - // add additional interface methods - List<Method> extraMethods = getInterfaceMethods(clazz); - for (Method source : extraMethods) { - for (Method target : methods) { - if (ObjectHelper.isOverridingMethod(source, target, false)) { - overrides.add(source); - } - } - for (Method target : methodMap.keySet()) { - if (ObjectHelper.isOverridingMethod(source, target, false)) { - overrides.add(source); - } - } - } - // remove all the overrides methods - extraMethods.removeAll(overrides); - methods.addAll(extraMethods); + methods.removeAll(overriddenMethods); + overriddenMethods.clear(); } // now introspect the methods and filter non valid methods @@ -386,9 +365,12 @@ public class BeanInfo { } } - Class<?> superclass = clazz.getSuperclass(); - if (superclass != null && !superclass.equals(Object.class)) { - introspect(superclass); + Class<?> superClass = clazz.getSuperclass(); + if (superClass != null && !superClass.equals(Object.class)) { + introspect(superClass); + } + for (Class<?> superInterface : clazz.getInterfaces()) { + introspect(superInterface); } } @@ -917,9 +899,9 @@ public class BeanInfo { Method alreadyRegisteredMethod = alreadyRegisteredMethodInfo.getMethod(); Method proposedMethod = proposedMethodInfo.getMethod(); - if (ObjectHelper.isOverridingMethod(proposedMethod, alreadyRegisteredMethod, false)) { + if (ObjectHelper.isOverridingMethod(getType(), proposedMethod, alreadyRegisteredMethod, false)) { return alreadyRegisteredMethodInfo; - } else if (ObjectHelper.isOverridingMethod(alreadyRegisteredMethod, proposedMethod, false)) { + } else if (ObjectHelper.isOverridingMethod(getType(), alreadyRegisteredMethod, proposedMethod, false)) { return proposedMethodInfo; } } http://git-wip-us.apache.org/repos/asf/camel/blob/04c4de84/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 07bb308..ebc3df8 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 @@ -1380,12 +1380,30 @@ 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) { + return isOverridingMethod(target.getDeclaringClass(), source, target, exact); + } + + /** + * Tests whether the target method overrides the source method from the + * inheriting class. + * <p/> + * Tests whether they have the same name, return type, and parameter list. + * + * @param inheritingClass the class inheriting the target method overriding + * the source method + * @param source the source method + * @param target the target method + * @param exact <tt>true</tt> if the override must be exact same types, + * <tt>false</tt> if the types should be assignable + * @return <tt>true</tt> if it override, <tt>false</tt> otherwise + */ + public static boolean isOverridingMethod(Class<?> inheritingClass, 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())) { + } else if (!source.getDeclaringClass().isAssignableFrom(inheritingClass) || !target.getDeclaringClass().isAssignableFrom(inheritingClass)) { return false; } http://git-wip-us.apache.org/repos/asf/camel/blob/04c4de84/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 fa2a519..4343812 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 @@ -33,4 +33,21 @@ public class MyOtherFooBean { public String toString(String input) { return "toString(String) was called"; } + + public interface InterfaceSize { + int size(); + } + + public abstract static class AbstractClassSize { + public abstract int size(); + } + + public static class SuperClazz extends AbstractClassSize implements InterfaceSize { + public int size() { + return 1; + } + } + + public static class Clazz extends SuperClazz { + } } http://git-wip-us.apache.org/repos/asf/camel/blob/04c4de84/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 7997664..f0d60a5 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 @@ -38,6 +38,9 @@ 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.MyOtherFooBean.AbstractClassSize; +import org.apache.camel.component.bean.MyOtherFooBean.Clazz; +import org.apache.camel.component.bean.MyOtherFooBean.InterfaceSize; import org.apache.camel.component.bean.MyStaticClass; import org.apache.camel.impl.DefaultCamelContext; import org.apache.camel.impl.DefaultMessage; @@ -890,4 +893,16 @@ public class ObjectHelperTest extends TestCase { Method m2 = Number.class.getMethod("intValue"); assertTrue(ObjectHelper.isOverridingMethod(m2, m1, false)); } + + public void testInheritedMethodCanOverrideInterfaceMethod() throws Exception { + Method m1 = AbstractClassSize.class.getMethod("size"); + Method m2 = InterfaceSize.class.getMethod("size"); + assertTrue(ObjectHelper.isOverridingMethod(Clazz.class, m2, m1, false)); + } + + public void testNonInheritedMethodCantOverrideInterfaceMethod() throws Exception { + Method m1 = AbstractClassSize.class.getMethod("size"); + Method m2 = InterfaceSize.class.getMethod("size"); + assertFalse(ObjectHelper.isOverridingMethod(InterfaceSize.class, m2, m1, false)); + } }