ignite-6944 Fixed lookup of writeReplace and readResolve methods during serialization/deserialization
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/1a1c2d37 Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/1a1c2d37 Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/1a1c2d37 Branch: refs/heads/ignite-zk Commit: 1a1c2d37b1ad5cbd91d9ec2a3c8eeef376ac70f2 Parents: 1d906b3 Author: Andrey Gura <[email protected]> Authored: Thu Nov 23 18:23:23 2017 +0300 Committer: agura <[email protected]> Committed: Sun Nov 26 22:12:00 2017 +0300 ---------------------------------------------------------------------- .../internal/binary/BinaryClassDescriptor.java | 4 +- .../ignite/internal/util/IgniteUtils.java | 58 ++++++++++++++++++++ .../binary/BinaryMarshallerSelfTest.java | 20 ++++++- 3 files changed, 79 insertions(+), 3 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ignite/blob/1a1c2d37/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryClassDescriptor.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryClassDescriptor.java b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryClassDescriptor.java index 935211e..f9be1db 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryClassDescriptor.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryClassDescriptor.java @@ -344,9 +344,9 @@ public class BinaryClassDescriptor { Method writeReplaceMthd; if (mode == BinaryWriteMode.BINARY || mode == BinaryWriteMode.OBJECT) { - readResolveMtd = U.getNonPublicMethod(cls, "readResolve"); + readResolveMtd = U.findInheritableMethod(cls, "readResolve"); - writeReplaceMthd = U.getNonPublicMethod(cls, "writeReplace"); + writeReplaceMthd = U.findInheritableMethod(cls, "writeReplace"); } else { readResolveMtd = null; http://git-wip-us.apache.org/repos/asf/ignite/blob/1a1c2d37/modules/core/src/main/java/org/apache/ignite/internal/util/IgniteUtils.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/util/IgniteUtils.java b/modules/core/src/main/java/org/apache/ignite/internal/util/IgniteUtils.java index d426468..b493545 100755 --- a/modules/core/src/main/java/org/apache/ignite/internal/util/IgniteUtils.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/util/IgniteUtils.java @@ -9458,6 +9458,64 @@ public abstract class IgniteUtils { } /** + * Finds a non-static and non-abstract method from the class it parents. + * + * Method.getMethod() does not return non-public method. + * + * @param cls Target class. + * @param name Name of the method. + * @param paramTypes Method parameters. + * @return Method or {@code null}. + */ + @Nullable public static Method findInheritableMethod(Class<?> cls, String name, Class<?>... paramTypes) { + Method mtd = null; + + Class<?> cls0 = cls; + + while (cls0 != null) { + try { + mtd = cls0.getDeclaredMethod(name, paramTypes); + + break; + } + catch (NoSuchMethodException e) { + cls0 = cls0.getSuperclass(); + } + } + + if (mtd == null) + return null; + + mtd.setAccessible(true); + + int mods = mtd.getModifiers(); + + if ((mods & (Modifier.STATIC | Modifier.ABSTRACT)) != 0) + return null; + else if ((mods & (Modifier.PUBLIC | Modifier.PROTECTED)) != 0) + return mtd; + else if ((mods & Modifier.PRIVATE) != 0) + return cls == cls0 ? mtd : null; + else { + ClassLoader clsLdr = cls.getClassLoader(); + + ClassLoader clsLdr0 = cls0.getClassLoader(); + + return clsLdr == clsLdr0 && packageName(cls).equals(packageName(cls0)) ? mtd : null; + } + } + + /** + * @param cls Class. + * @return Package name. + */ + private static String packageName(Class<?> cls) { + Package pkg = cls.getPackage(); + + return pkg == null ? "" : pkg.getName(); + } + + /** * @param cls The class to search. * @param name Name of a field to get. * @return Field or {@code null}. http://git-wip-us.apache.org/repos/asf/ignite/blob/1a1c2d37/modules/core/src/test/java/org/apache/ignite/internal/binary/BinaryMarshallerSelfTest.java ---------------------------------------------------------------------- diff --git a/modules/core/src/test/java/org/apache/ignite/internal/binary/BinaryMarshallerSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/binary/BinaryMarshallerSelfTest.java index ef68cd1..bcd2bde 100644 --- a/modules/core/src/test/java/org/apache/ignite/internal/binary/BinaryMarshallerSelfTest.java +++ b/modules/core/src/test/java/org/apache/ignite/internal/binary/BinaryMarshallerSelfTest.java @@ -17,6 +17,7 @@ package org.apache.ignite.internal.binary; +import com.google.common.collect.ImmutableList; import java.io.Externalizable; import java.io.IOException; import java.io.ObjectInput; @@ -940,7 +941,7 @@ public class BinaryMarshallerSelfTest extends GridCommonAbstractTest { /** * @throws Exception If failed. */ - public void testWriteReplace() throws Exception { + public void testWriteReplacePrivate() throws Exception { BinaryMarshaller marsh = binaryMarshaller(Collections.singleton( new BinaryTypeConfiguration(TestObject.class.getName()) )); @@ -955,6 +956,23 @@ public class BinaryMarshallerSelfTest extends GridCommonAbstractTest { } /** + * @throws Exception If failed. + */ + public void testWriteReplaceInheritable() throws Exception { + ImmutableList<String> obj = ImmutableList.of("This is a test"); + + BinaryMarshaller marsh = binaryMarshaller(Collections.singleton( + new BinaryTypeConfiguration(obj.getClass().getName()) + )); + + BinaryObject po = marshal(obj, marsh); + + Object des = po.deserialize(); + + assertEquals(obj, des); + } + + /** * */ private static class EnclosingObj implements Serializable {
