You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@empire-db.apache.org by do...@apache.org on 2012/04/11 14:23:34 UTC

svn commit: r1324735 - in /empire-db/trunk/empire-db/src/main/java/org/apache/empire/db: DBColumn.java DBDatabase.java DBRowSet.java

Author: doebele
Date: Wed Apr 11 12:23:34 2012
New Revision: 1324735

URL: http://svn.apache.org/viewvc?rev=1324735&view=rev
Log:
EMPIREDB-138
Custom serialization and deserialization for DBRowSet and DBColumn objects

Modified:
    empire-db/trunk/empire-db/src/main/java/org/apache/empire/db/DBColumn.java
    empire-db/trunk/empire-db/src/main/java/org/apache/empire/db/DBDatabase.java
    empire-db/trunk/empire-db/src/main/java/org/apache/empire/db/DBRowSet.java

Modified: empire-db/trunk/empire-db/src/main/java/org/apache/empire/db/DBColumn.java
URL: http://svn.apache.org/viewvc/empire-db/trunk/empire-db/src/main/java/org/apache/empire/db/DBColumn.java?rev=1324735&r1=1324734&r2=1324735&view=diff
==============================================================================
--- empire-db/trunk/empire-db/src/main/java/org/apache/empire/db/DBColumn.java (original)
+++ empire-db/trunk/empire-db/src/main/java/org/apache/empire/db/DBColumn.java Wed Apr 11 12:23:34 2012
@@ -19,13 +19,22 @@
 package org.apache.empire.db;
 
 // Java
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.lang.reflect.Field;
 import java.util.Set;
 
 import org.apache.empire.commons.Options;
+import org.apache.empire.commons.StringUtils;
 import org.apache.empire.data.Column;
 import org.apache.empire.data.DataType;
 import org.apache.empire.db.exceptions.DatabaseNotOpenException;
 import org.apache.empire.db.expr.set.DBSetExpr;
+import org.apache.empire.exceptions.InvalidArgumentException;
+import org.apache.empire.exceptions.ItemNotFoundException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.w3c.dom.Element;
 
 
@@ -46,6 +55,8 @@ public abstract class DBColumn extends D
 {
     private final static long serialVersionUID = 1L;
   
+    private static final Logger log = LoggerFactory.getLogger(DBColumn.class);
+    
     // Predefined column attributes 
 
     /**
@@ -74,7 +85,7 @@ public abstract class DBColumn extends D
     public static final String DBCOLATTR_SINGLEBYTECHARS  = "singleByteChars";
 
     // basic data
-    protected final DBRowSet   rowset;
+    protected final transient DBRowSet rowset;
     protected final String     name;
     protected String           comment;
 
@@ -94,6 +105,105 @@ public abstract class DBColumn extends D
     }
 
     /**
+     * Gets an identifier for this RowSet Object
+     * @return the rowset identifier
+     */
+    public String getId()
+    {
+        return rowset.getId()+"."+name;
+    }
+
+    /**
+     * returns a rowset by its identifier
+     * @param rowsetId the id of the rowset
+     * @return the rowset object
+     */
+    public static DBColumn findById(String columnId)
+    {
+        int i = columnId.lastIndexOf('.');
+        if (i<0)
+            throw new InvalidArgumentException("columnId", columnId);
+        // rowset suchen
+        String rsid = columnId.substring(0, i);
+        DBRowSet rset = DBRowSet.findById(rsid);
+        // column suchen
+        String colname = columnId.substring(i+1);
+        DBColumn col = rset.getColumn(colname);
+        if (col==null)
+            throw new ItemNotFoundException(columnId);
+        return col;
+    }
+    
+    /**
+     * Custom serialization for transient rowset.
+     */
+    private void writeObject(ObjectOutputStream strm) throws IOException 
+    {
+        if (rowset==null)
+        {   // No rowset
+            strm.writeObject("");
+            strm.defaultWriteObject();
+            return;
+        }
+        // write dbid and rowset-name
+        String dbid   = rowset.getDatabase().getId(); 
+        String rsname = rowset.getName(); 
+        strm.writeObject(dbid);
+        strm.writeObject(rsname);
+        if (log.isInfoEnabled())
+            log.info("Serialization: reading DBColumn "+dbid+"."+rsname);
+        strm.defaultWriteObject();
+    }
+
+    /**
+     * Custom serialization for transient rowset.
+     */
+    private void readObject(ObjectInputStream strm) throws IOException, ClassNotFoundException, 
+        SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException
+    {
+        String dbid = String.valueOf(strm.readObject());
+        if (StringUtils.isNotEmpty(dbid))
+        {   // Find Rowset
+            String rsname = String.valueOf(strm.readObject());
+            if (log.isInfoEnabled())
+                log.info("Serialization: reading DBColumn "+dbid+"."+rsname);
+            // find database
+            DBDatabase db = DBDatabase.findById(dbid);
+            if (db==null)
+                throw new ClassNotFoundException(dbid);
+            // find database
+            DBRowSet srs = db.getRowSet(rsname);
+            if (srs==null)
+                throw new ClassNotFoundException(dbid+"."+rsname);
+            // set final field
+            Field f = DBColumn.class.getDeclaredField("rowset");
+            f.setAccessible(true);
+            f.set(this, srs);
+            f.setAccessible(false);
+        }
+        // read the rest
+        strm.defaultReadObject();
+    }
+
+    @Override
+    public boolean equals(Object other)
+    {
+        if (other==this)
+            return true;
+        if (rowset==null)
+            return super.equals(other);
+        if (other instanceof DBColumn)
+        {   // Rowset and name must match
+            DBColumn c = (DBColumn) other;
+            if (rowset.equals(c.getRowSet())==false)
+                return false;
+            // check for equal names
+            return name.equalsIgnoreCase(c.getName());
+        }
+        return false;
+    }
+     
+    /**
      * Returns the size of the column.
      *
      * @return Returns the size of the column

Modified: empire-db/trunk/empire-db/src/main/java/org/apache/empire/db/DBDatabase.java
URL: http://svn.apache.org/viewvc/empire-db/trunk/empire-db/src/main/java/org/apache/empire/db/DBDatabase.java?rev=1324735&r1=1324734&r2=1324735&view=diff
==============================================================================
--- empire-db/trunk/empire-db/src/main/java/org/apache/empire/db/DBDatabase.java (original)
+++ empire-db/trunk/empire-db/src/main/java/org/apache/empire/db/DBDatabase.java Wed Apr 11 12:23:34 2012
@@ -19,12 +19,14 @@
 package org.apache.empire.db;
 
 import java.io.Serializable;
+import java.lang.ref.WeakReference;
 import java.sql.Connection;
 import java.sql.ResultSet;
 import java.sql.SQLException;
 import java.sql.Statement;
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.HashMap;
 import java.util.List;
 
 import org.apache.empire.commons.ObjectUtils;
@@ -40,6 +42,7 @@ import org.apache.empire.db.expr.column.
 import org.apache.empire.exceptions.InternalException;
 import org.apache.empire.exceptions.InvalidArgumentException;
 import org.apache.empire.exceptions.ItemExistsException;
+import org.apache.empire.exceptions.ItemNotFoundException;
 import org.apache.empire.exceptions.MiscellaneousErrorException;
 import org.apache.empire.exceptions.PropertyReadOnlyException;
 import org.apache.empire.exceptions.UnexpectedReturnValueException;
@@ -87,6 +90,37 @@ public abstract class DBDatabase extends
 
     // Logger
     private static final Logger log = LoggerFactory.getLogger(DBDatabase.class);
+    
+    /** 
+     * global map of all database instances that have been allocated
+     */
+    private static HashMap<String, WeakReference<DBDatabase>> databaseMap = new HashMap<String, WeakReference<DBDatabase>>();
+    
+    /** 
+     * find a database by id
+     */
+    public static DBDatabase findById(String dbIdent)
+    {
+        if (databaseMap.containsKey(dbIdent)==false)
+            log.warn("Database {} not found!", dbIdent);
+        // get reference
+        WeakReference<DBDatabase> ref = databaseMap.get(dbIdent); 
+        return ref.get();
+    }
+    
+    /** 
+     * find a database by id
+     */
+    public static DBDatabase findByClass(Class<? extends DBDatabase> cls)
+    {
+        for (WeakReference<DBDatabase> ref : databaseMap.values())
+        {   // find database by class
+            DBDatabase db = ref.get();
+            if (db!=null && cls.isInstance(db))
+                return db;
+        }
+        throw new ItemNotFoundException(cls.getName());
+    }
 
     /** the database schema * */
     protected String           schema    = null; // database schema name
@@ -95,6 +129,7 @@ public abstract class DBDatabase extends
     protected List<DBRelation> relations = new ArrayList<DBRelation>();
     protected List<DBView>     views     = new ArrayList<DBView>();
     protected DBDatabaseDriver driver    = null;
+    protected String           instanceId;
     
     /**   
      * Property that indicates whether to always use usePreparedStatements (Default is false!)
@@ -104,11 +139,18 @@ public abstract class DBDatabase extends
     private boolean preparedStatementsEnabled = false;
 
     /**
-     * Constructs a new DBDatabase object set the variable 'schema' = null.
+     * Constructs a new DBDatabase object and sets the specified schema object.
+     * 
+     * @param schema the database schema
+     * @param linkName the database link name
      */
-    public DBDatabase()
+    public DBDatabase(String schema, String linkName)
     {
-        this.schema = null;
+        this.schema = schema;
+        this.linkName = linkName;
+
+        // register database in global map
+        register(getClass().getSimpleName());
     }
 
     /**
@@ -118,19 +160,48 @@ public abstract class DBDatabase extends
      */
     public DBDatabase(String schema)
     {
-        this.schema = schema;
+        this(schema, null);
     }
 
     /**
-     * Constructs a new DBDatabase object and sets the specified schema object.
-     * 
-     * @param schema the database schema
-     * @param linkName the database link name
+     * Constructs a new DBDatabase object set the variable 'schema' = null.
      */
-    public DBDatabase(String schema, String linkName)
+    public DBDatabase()
     {
-        this.schema = schema;
-        this.linkName = linkName;
+        this(null, null);
+    }
+    
+    /**
+     * registers the database in the global list of databases
+     * @param dbid
+     */
+    protected void register(String dbid)
+    {
+        // Check if it exists
+        if (databaseMap.containsValue(this))
+            databaseMap.remove(instanceId);
+        // find a unique key
+        int inst=0;
+        for (String key : databaseMap.keySet())
+        {
+            if (key.startsWith(dbid) && databaseMap.get(key).get()!=null)
+                inst++;
+        }
+        if (inst>0)
+            this.instanceId = dbid+":"+String.valueOf(inst+1);
+        else
+            this.instanceId = dbid;
+        // register database in global map
+        databaseMap.put(this.instanceId, new WeakReference<DBDatabase>(this));
+    }
+
+    /**
+     * Returns the database instance id
+     * @return the identifier of the database
+     */
+    public String getId()
+    {
+        return instanceId;
     }
 
     // ------------------------------
@@ -457,6 +528,20 @@ public abstract class DBDatabase extends
     }
 
     /**
+     * Finds a DBRowSet object (DBTable or DBView) by name.
+     * <P>
+     * @param name the name of the table
+     * @return the located DBTable object
+     */
+    public DBRowSet getRowSet(String name)
+    { // find table by name
+        DBRowSet rset = getTable(name);
+        if (rset==null)
+            rset = getView(name);
+        return rset;
+    }
+
+    /**
      * Finds a DBTable object by name.
      * <P>
      * @param name the name of the table

Modified: empire-db/trunk/empire-db/src/main/java/org/apache/empire/db/DBRowSet.java
URL: http://svn.apache.org/viewvc/empire-db/trunk/empire-db/src/main/java/org/apache/empire/db/DBRowSet.java?rev=1324735&r1=1324734&r2=1324735&view=diff
==============================================================================
--- empire-db/trunk/empire-db/src/main/java/org/apache/empire/db/DBRowSet.java (original)
+++ empire-db/trunk/empire-db/src/main/java/org/apache/empire/db/DBRowSet.java Wed Apr 11 12:23:34 2012
@@ -18,6 +18,10 @@
  */
 package org.apache.empire.db;
 
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.lang.reflect.Field;
 import java.sql.Connection;
 import java.sql.Timestamp;
 import java.util.ArrayList;
@@ -83,7 +87,7 @@ public abstract class DBRowSet extends D
     // Logger
     protected static final Logger log = LoggerFactory.getLogger(DBRowSet.class);
     // Members
-    protected final DBDatabase db;
+    protected final transient DBDatabase db;
     protected String        comment           = null;
     protected DBIndex       primaryKey        = null;
     protected DBColumn      timestampColumn   = null; // Use SetUpdateTimestamp!
@@ -100,6 +104,100 @@ public abstract class DBRowSet extends D
         this.db = db;
     }
 
+    /**
+     * Gets an identifier for this RowSet Object
+     * @return the rowset identifier
+     */
+    public String getId()
+    {
+        return db.getId()+"."+getName();
+    }
+
+    /**
+     * returns a rowset by its identifier
+     * @param rowsetId the id of the rowset
+     * @return the rowset object
+     */
+    public static DBRowSet findById(String rowsetId)
+    {
+        int i = rowsetId.lastIndexOf('.');
+        if (i<0)
+            throw new InvalidArgumentException("rowsetId", rowsetId);
+        // database suchen
+        String dbid = rowsetId.substring(0, i);
+        DBDatabase db = DBDatabase.findById(dbid);
+        if (db==null)
+            throw new ItemNotFoundException(dbid);
+        // rowset suchen
+        String rsname = rowsetId.substring(i+1);
+        DBRowSet rset = db.getRowSet(rsname);
+        if (rset==null)
+            throw new ItemNotFoundException(rowsetId);
+        return rset;
+    }
+    
+    /**
+    * Custom serialization for transient database.
+    */
+    private void writeObject(ObjectOutputStream strm) throws IOException 
+    {
+        if (db==null)
+        {   // No database
+            strm.writeObject("");
+            strm.defaultWriteObject();
+            return;
+        }
+        String dbid = db.getId(); 
+        strm.writeObject(dbid);
+        if (log.isInfoEnabled())
+            log.info("Serialization: reading DBRowSet "+dbid);
+        // write the rest
+        strm.defaultWriteObject();
+    }
+
+    /**
+    * Custom deserialization for transient database.
+    */
+    private void readObject(ObjectInputStream strm) throws IOException, ClassNotFoundException,
+        SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException
+    {
+        String dbid = String.valueOf(strm.readObject());
+        if (StringUtils.isNotEmpty(dbid))
+        {   // Find database
+            if (log.isInfoEnabled())
+                log.info("Serialization: reading DBRowSet "+dbid);
+            // find database
+            DBDatabase sdb = DBDatabase.findById(dbid);
+            if (sdb==null)
+                throw new ClassNotFoundException(dbid);
+            // set final field
+            Field f = DBRowSet.class.getDeclaredField("db");
+            f.setAccessible(true);
+            f.set(this, sdb);
+            f.setAccessible(false);
+        }    
+        // read the rest
+        strm.defaultReadObject();
+    }
+
+    @Override
+    public boolean equals(Object other)
+    {
+        if (other==this)
+            return true;
+        if (db==null)
+            return super.equals(other);
+        if (other instanceof DBRowSet)
+        {   // Database and name must match
+            DBRowSet r = (DBRowSet) other; 
+            if (db.equals(r.getDatabase())==false)
+                return false;
+            // check for equal names
+            return getName().equalsIgnoreCase(r.getName());
+        }
+        return false;
+    }
+
     // ------- Abstract Methods -------
     
     public abstract String getName();