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 68648bc  EMPIREDB-362 small fix
68648bc is described below

commit 68648bc334cacb392d522558b1d0633595283f36
Author: Rainer Döbele <[email protected]>
AuthorDate: Wed Feb 9 10:29:16 2022 +0100

    EMPIREDB-362 small fix
---
 .../java/org/apache/empire/commons/ClassUtils.java | 73 ++++++++++++++++++++++
 .../main/java/org/apache/empire/db/DBRecord.java   |  7 ++-
 .../java/org/apache/empire/db/DBRecordBase.java    | 24 ++++---
 .../java/org/apache/empire/db/DBRecordBean.java    | 11 ++--
 4 files changed, 100 insertions(+), 15 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 4e7d2e3..7b8b618 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
@@ -23,6 +23,7 @@ import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.ObjectInputStream;
 import java.io.ObjectOutputStream;
+import java.io.Serializable;
 import java.lang.reflect.Constructor;
 import java.lang.reflect.Field;
 import java.lang.reflect.InvocationTargetException;
@@ -81,6 +82,78 @@ public final class ClassUtils
     }
     
     /**
+     * Makes a copy of an object if possible or returns null 
+     * @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)
+    {
+        if (obj==null)
+            return null;
+        // the class
+        Class<?> clazz = obj.getClass();
+        // simple check
+        if (clazz.isInterface() || clazz.isAnnotation())
+            return null; // not supported
+        if (clazz.isPrimitive() || clazz.isEnum())
+            return obj; // no need to copy
+        // try clonable
+        if (obj instanceof Cloneable)
+        {   try {
+                return invokeSimpleMethod(java.lang.Object.class, obj, 
"clone", true);
+            } catch (Exception e) {
+                log.error("Copy through Cloning failed for : 
"+clazz.getName(), e);
+            }
+        }
+        // try serializable
+        if (obj instanceof Serializable)
+        {   try
+            {   ByteArrayOutputStream baos = new ByteArrayOutputStream();
+                // Write the object
+                ObjectOutputStream oos = new ObjectOutputStream(baos);
+                oos.writeObject(obj);
+                // Read the object
+                ObjectInputStream oin = new ObjectInputStream(new 
ByteArrayInputStream(baos.toByteArray()));
+                Object copy = oin.readObject();
+                // return result
+                return copy;
+            } catch (IOException | ClassNotFoundException e) {
+                log.error("Copy through Serialization failed for : 
"+clazz.getName(), e);
+            }
+        }
+        // find standard constructor
+        int i=0;
+        final Constructor<?>[] ctors = clazz.getConstructors();
+        for (; i<ctors.length; i++)
+            if (ctors[i].getParameterCount()==0)
+                break;
+        if (i<ctors.length)
+        {   try
+            {   // Try standard constructor
+                Object copy = clazz.newInstance();
+                Field[] fields = copy.getClass().getDeclaredFields();
+                for (Field field : fields) {
+                    // make acessible
+                    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);
+                }
+                return copy;
+            } catch (InstantiationException | IllegalAccessException e) {
+                log.error("Copy through Instantiation failed for : 
"+clazz.getName(), e);
+            }
+        }
+        // not supported
+        return null;
+    }
+    
+    /**
      * Retrieve a field value using reflection
      * @param clazz the class from which to obtain the field
      * @param object the object instance from which to obtain the field
diff --git a/empire-db/src/main/java/org/apache/empire/db/DBRecord.java 
b/empire-db/src/main/java/org/apache/empire/db/DBRecord.java
index 71749fc..3cd3c7c 100644
--- a/empire-db/src/main/java/org/apache/empire/db/DBRecord.java
+++ b/empire-db/src/main/java/org/apache/empire/db/DBRecord.java
@@ -21,6 +21,7 @@ package org.apache.empire.db;
 import java.io.IOException;
 import java.io.ObjectInputStream;
 import java.io.ObjectOutputStream;
+import java.io.Serializable;
 import java.sql.Connection;
 
 import org.apache.empire.commons.ClassUtils;
@@ -49,7 +50,7 @@ import org.slf4j.LoggerFactory;
  * 
  * The record is Serializable either if the provided DBContext is 
serializable, or if the Context is provided on deserialization in a derived 
class.
  */
-public class DBRecord extends DBRecordBase
+public class DBRecord extends DBRecordBase implements Serializable // really 
Serializable?
 {
     private static final long serialVersionUID = 1L;
     
@@ -212,8 +213,8 @@ public class DBRecord extends DBRecordBase
     
     /**
      * Returns the record id for tables which have a single numeric primary key
-     * This method is provided for convenience in additon to the the getKey() 
method
-     * @return the record id
+     * This method is provided for convenience in addition to the the getKey() 
method
+     * @return the record id or 0 if the key is null
      * @throws NoPrimaryKeyException if the table has no primary key
      * @throws NotSupportedException if the primary key is not a single column 
of if the column is not numeric
      */
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 a453b37..7a68e1e 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
@@ -18,13 +18,13 @@
  */
 package org.apache.empire.db;
 
-import java.io.Serializable;
 import java.lang.reflect.InvocationTargetException;
 import java.util.Collection;
 import java.util.List;
 
 import org.apache.commons.beanutils.BeanUtilsBean;
 import org.apache.commons.beanutils.PropertyUtilsBean;
+import org.apache.empire.commons.ClassUtils;
 import org.apache.empire.commons.ObjectUtils;
 import org.apache.empire.commons.Options;
 import org.apache.empire.commons.StringUtils;
@@ -60,10 +60,8 @@ import org.w3c.dom.Element;
  * 
  * Also, field value changes, can be handled using the onFieldChanged event.
  */
-public abstract class DBRecordBase extends DBRecordData implements Record, 
Cloneable, Serializable
+public abstract class DBRecordBase extends DBRecordData implements Record, 
Cloneable
 {
-    private static final long serialVersionUID = 1L;
-    
     private static final Logger log  = 
LoggerFactory.getLogger(DBRecordBase.class);
     
     /**
@@ -90,9 +88,9 @@ public abstract class DBRecordBase extends DBRecordData 
implements Record, Clone
                 throw new ObjectNotValidException(record);
             // save state
             this.state = record.state;            
-            this.modified = copy(record.modified);
-            this.fields   = copy(record.fields);
-            this.rowsetData = record.rowsetData;
+            this.modified   = copy(record.modified);
+            this.fields     = copy(record.fields);
+            this.rowsetData = copy(record.rowsetData);
         }
 
         @Override
@@ -177,6 +175,18 @@ public abstract class DBRecordBase extends DBRecordData 
implements Record, Clone
             }
             return copy;
         }
+        
+        protected Object copy(Object other)
+        {   
+            if (other==null)
+                return null;
+            if (other instanceof Object[])
+                return copy((Object[])other);
+            Object copy = ClassUtils.copy(other);
+            if (copy!=null)
+                return copy;
+            return other;
+        }
     }
   
     /* Record state enum */
diff --git a/empire-db/src/main/java/org/apache/empire/db/DBRecordBean.java 
b/empire-db/src/main/java/org/apache/empire/db/DBRecordBean.java
index 3992654..03a8ad2 100644
--- a/empire-db/src/main/java/org/apache/empire/db/DBRecordBean.java
+++ b/empire-db/src/main/java/org/apache/empire/db/DBRecordBean.java
@@ -18,6 +18,7 @@
  */
 package org.apache.empire.db;
 
+import java.io.Serializable;
 import java.sql.Connection;
 
 import org.apache.empire.commons.StringUtils;
@@ -39,7 +40,7 @@ import org.slf4j.LoggerFactory;
  * Thus it has a Default constructor and is essentially a dynamic bean
  * 
  */
-public class DBRecordBean extends DBRecordBase
+public class DBRecordBean extends DBRecordBase implements Serializable
 {
     private static final long serialVersionUID = 1L;
     
@@ -132,8 +133,8 @@ public class DBRecordBean extends DBRecordBase
     
     /**
      * Returns the record id for tables which have a single numeric primary key
-     * This method is provided for convenience in additon to the the getKey() 
method
-     * @return the record id
+     * This method is provided for convenience in addition to the the getKey() 
method
+     * @return the record id or 0 if the key is null
      * @throws NoPrimaryKeyException if the table has no primary key
      * @throws NotSupportedException if the primary key is not a single column 
of if the column is not numeric
      */
@@ -257,7 +258,7 @@ public class DBRecordBean extends DBRecordBase
             // check updatable
             checkUpdateable();
             // allow rollback
-            if (isRollbackHandlingEnabled())
+            if (this.enableRollbackHandling && 
context.isRollbackHandlingEnabled())
                 context.appendRollbackHandler(createRollbackHandler());
             // update
             getRowSet().updateRecord(this);
@@ -283,7 +284,7 @@ public class DBRecordBean extends DBRecordBase
         // check updatable
         checkUpdateable();
         // allow rollback
-        if (isRollbackHandlingEnabled())
+        if (this.enableRollbackHandling && context.isRollbackHandlingEnabled())
             context.appendRollbackHandler(createRollbackHandler());
         // Delete only if record is not new
         if (!isNew())

Reply via email to