This is an automated email from the ASF dual-hosted git repository.

doebele pushed a commit to branch version3
in repository https://gitbox.apache.org/repos/asf/empire-db.git


The following commit(s) were added to refs/heads/version3 by this push:
     new 6f734e5  EMPIREDB-362 ClassUtils.copy fix
6f734e5 is described below

commit 6f734e5b8f2037e5912310a68405162c90e03644
Author: Rainer Döbele <[email protected]>
AuthorDate: Wed Feb 9 20:32:13 2022 +0100

    EMPIREDB-362 ClassUtils.copy fix
---
 .../java/org/apache/empire/commons/ClassUtils.java | 41 ++++++++++++----------
 .../java/org/apache/empire/db/DBRecordBase.java    |  2 +-
 2 files changed, 24 insertions(+), 19 deletions(-)

diff --git a/empire-db/src/main/java/org/apache/empire/commons/ClassUtils.java 
b/empire-db/src/main/java/org/apache/empire/commons/ClassUtils.java
index cdcc330..0ccc30a 100644
--- a/empire-db/src/main/java/org/apache/empire/commons/ClassUtils.java
+++ b/empire-db/src/main/java/org/apache/empire/commons/ClassUtils.java
@@ -86,12 +86,13 @@ public final class ClassUtils
      * @param obj the object to copy
      * @return either a copy of the object or null if copy is not supported
      */
-    public static Object copy(Object obj)
+    @SuppressWarnings("unchecked")
+    public static <T> T copy(T obj)
     {
         if (obj==null)
             return null;
         // the class
-        Class<?> clazz = obj.getClass();
+        Class<T> clazz = (Class<T>)obj.getClass();
         // class check
         if (clazz.isInterface() || clazz.isAnnotation()) {
             log.warn("Unable to copy Interface or Annotation {}", 
clazz.getName());
@@ -104,7 +105,7 @@ public final class ClassUtils
         // try clonable
         if (obj instanceof Cloneable)
         {   try {
-                return invokeSimpleMethod(java.lang.Object.class, obj, 
"clone", true);
+                return (T)invokeSimpleMethod(java.lang.Object.class, obj, 
"clone", true);
             } catch (Exception e) {
                 log.error("Copy through Cloning failed for : 
"+clazz.getName(), e);
             }
@@ -120,13 +121,13 @@ public final class ClassUtils
                 ObjectInputStream oin = new ObjectInputStream(new 
ByteArrayInputStream(baos.toByteArray()));
                 Object copy = oin.readObject();
                 // return result
-                return copy;
+                return (T)copy;
             } catch (IOException | ClassNotFoundException e) {
                 log.error("Copy through Serialization failed for : 
"+clazz.getName(), e);
             }
         }
         // try copy through Instantiation
-        Constructor<?> ctor = findMatchingConstructor(clazz, 0, clazz);
+        Constructor<T> ctor = findMatchingConstructor(clazz, 0, clazz);
         if (ctor!=null)
         {   try
             {   if (ctor.getParameterCount()==1)
@@ -135,19 +136,23 @@ public final class ClassUtils
                 }
                 else
                 {   // Try default constructor and copy fields
-                    Object copy = ctor.newInstance();
-                    Field[] fields = copy.getClass().getDeclaredFields();
-                    for (Field field : fields) {
-                        // make accessible
-                        boolean accessible = field.isAccessible();
-                        if (!accessible)
-                            field.setAccessible(true);
-                        // copy
-                        Object value = field.get(obj); // recurse ?
-                        field.set(copy, value);
-                        // restore
-                        if (!accessible)
-                            field.setAccessible(false);
+                    T copy = ctor.newInstance();
+                    // copy fields of this class and all superclasses
+                    for (Class<?> cl = clazz; (cl!=null && cl!=Object.class); 
cl=cl.getSuperclass())  
+                    {
+                        Field[] fields = cl.getDeclaredFields();
+                        for (Field field : fields) {
+                            // make accessible
+                            boolean accessible = field.isAccessible();
+                            if (!accessible)
+                                field.setAccessible(true);
+                            // copy
+                            Object value = field.get(obj); // recurse ?
+                            field.set(copy, copy(value));
+                            // restore
+                            if (!accessible)
+                                field.setAccessible(false);
+                        }
                     }
                     return copy;
                 }
diff --git a/empire-db/src/main/java/org/apache/empire/db/DBRecordBase.java 
b/empire-db/src/main/java/org/apache/empire/db/DBRecordBase.java
index 3213752..3ec6dcc 100644
--- a/empire-db/src/main/java/org/apache/empire/db/DBRecordBase.java
+++ b/empire-db/src/main/java/org/apache/empire/db/DBRecordBase.java
@@ -262,7 +262,7 @@ public abstract class DBRecordBase extends DBRecordData 
implements Record, Clone
                 rec.fields = fields.clone();
             if (rec.modified == modified && modified!=null)
                 rec.modified = modified.clone();
-            rec.rowsetData = this.rowsetData;
+            rec.rowsetData = ClassUtils.copy(this.rowsetData);
             return rec;
             
         } catch (CloneNotSupportedException e)

Reply via email to