You are viewing a plain text version of this content. The canonical link for it is here.
Posted to ojb-dev@db.apache.org by ar...@apache.org on 2006/05/31 20:01:49 UTC

svn commit: r410616 - in /db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker: lob/BlobHandle.java lob/ClobHandle.java lob/LobHandle.java lob/LobHelperImpl.java metadata/ClassDescriptor.java metadata/FieldType.java metadata/FieldTypes.java

Author: arminw
Date: Wed May 31 11:01:48 2006
New Revision: 410616

URL: http://svn.apache.org/viewvc?rev=410616&view=rev
Log:
improve LOB object handling

Modified:
    db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/lob/BlobHandle.java
    db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/lob/ClobHandle.java
    db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/lob/LobHandle.java
    db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/lob/LobHelperImpl.java
    db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/metadata/ClassDescriptor.java
    db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/metadata/FieldType.java
    db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/metadata/FieldTypes.java

Modified: db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/lob/BlobHandle.java
URL: http://svn.apache.org/viewvc/db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/lob/BlobHandle.java?rev=410616&r1=410615&r2=410616&view=diff
==============================================================================
--- db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/lob/BlobHandle.java (original)
+++ db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/lob/BlobHandle.java Wed May 31 11:01:48 2006
@@ -34,6 +34,16 @@
         super(broker, blob);
     }
 
+    private BlobHandle()
+    {
+        super();
+    }
+
+    public LobHandle decoupledCopy()
+    {
+        return new BlobHandle();
+    }
+
     /**
      * Returns the innermost {@link java.sql.Blob} instance.
      *
@@ -78,27 +88,33 @@
     {
         return getLocalBlob().position(pattern, start);
     }
+
 //#ifdef JDBC30
 
     public OutputStream setBinaryStream(long pos) throws SQLException
     {
+        markDirty();
         return getLocalBlob().setBinaryStream(pos);
     }
 
     public int setBytes(long pos, byte[] bytes, int offset, int len) throws SQLException
     {
+        markDirty();
         return getLocalBlob().setBytes(pos, bytes, offset, len);
     }
 
     public int setBytes(long pos, byte[] bytes) throws SQLException
     {
+        markDirty();
         return getLocalBlob().setBytes(pos, bytes);
     }
 
     public void truncate(long len) throws SQLException
     {
+        markDirty();
         getLocalBlob().truncate(len);
     }
 
 //#endif
+
 }

Modified: db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/lob/ClobHandle.java
URL: http://svn.apache.org/viewvc/db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/lob/ClobHandle.java?rev=410616&r1=410615&r2=410616&view=diff
==============================================================================
--- db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/lob/ClobHandle.java (original)
+++ db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/lob/ClobHandle.java Wed May 31 11:01:48 2006
@@ -36,6 +36,16 @@
         super(broker, clob);
     }
 
+    private ClobHandle()
+    {
+        super();
+    }
+
+    public LobHandle decoupledCopy()
+    {
+        return new ClobHandle();
+    }
+
     /**
      * Returns the innermost {@link java.sql.Clob} instance.
      *
@@ -90,28 +100,34 @@
 
     public int setString(long pos, String str) throws SQLException
     {
+        markDirty();
         return getLocalClob().setString(pos, str);
     }
 
     public int setString(long pos, String str, int offset, int len) throws SQLException
     {
+        markDirty();
         return getLocalClob().setString(pos, str, offset, len);
     }
 
     public Writer setCharacterStream(long pos) throws SQLException
     {
+        markDirty();
         return getLocalClob().setCharacterStream(pos);
     }
 
     public OutputStream setAsciiStream(long pos) throws SQLException
     {
+        markDirty();
         return getLocalClob().setAsciiStream(pos);
     }
 
     public void truncate(long len) throws SQLException
     {
+        markDirty();
         getLocalClob().truncate(len);
     }
 
 //#endif
+    
 }

Modified: db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/lob/LobHandle.java
URL: http://svn.apache.org/viewvc/db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/lob/LobHandle.java?rev=410616&r1=410615&r2=410616&view=diff
==============================================================================
--- db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/lob/LobHandle.java (original)
+++ db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/lob/LobHandle.java Wed May 31 11:01:48 2006
@@ -15,29 +15,43 @@
  * limitations under the License.
  */
 
+import java.io.Serializable;
+
 import org.apache.ojb.broker.PBStateEvent;
 import org.apache.ojb.broker.PBStateListener;
 import org.apache.ojb.broker.PersistenceBrokerInternal;
 
 /**
- * Base class for OJB LOB-objects.
+ * Base class for OJB LOB-object wrapper classes like Blob, Clob
+ * but also all other locator based advanced jdbc data types.
  *
  * @version $Id: $
  */
-abstract class LobHandle implements PBStateListener
+abstract public class LobHandle implements PBStateListener, Serializable
 {
     private boolean active;
     private boolean isTransient;
-    private Object locator;
+    private transient Object locator;
+    private boolean dirty;
+
+    protected LobHandle()
+    {
+
+    }
 
     LobHandle(PersistenceBrokerInternal broker, Object locator)
     {
+        if(locator == null)
+        {
+            throw new NullPointerException("The locator object may not be 'null'");
+        }
         this.locator = locator;
         isTransient = false;
         active = broker.isInTransaction();
         if(locator instanceof Lob)
         {
-            setTransient(true);
+            isTransient = true;
+            markDirty();
         }
         if(active)
         {
@@ -46,6 +60,42 @@
     }
 
     /**
+     * Returns a <em>deactivated, decoupled</em> locator copy
+     * of this instance.
+     *
+     * @return A decoupled locator wrapper instance copy of this locator.
+     */
+    abstract public LobHandle decoupledCopy();
+
+    /**
+     * Returns <em>true</em> if the locator object was manipulated.
+     *
+     * @return If the locator object was modified <em>true</em> is returned, else <em>false</em>.
+     */
+    public boolean isDirty()
+    {
+        return dirty && this.locator != null;
+    }
+
+    /**
+     * Set the state of this locator.
+     *
+     * @param dirty The state flag of this locator.
+     */
+    public void setDirty(boolean dirty)
+    {
+        this.dirty = dirty;
+    }
+
+    /**
+     * Mark this locator as dirty.
+     */
+    protected void markDirty()
+    {
+        setDirty(true);
+    }
+
+    /**
      * Return the locator object.
      *
      * @param check If <em>true</em> a validation check is done, else simply the locator is returned.
@@ -57,15 +107,20 @@
         return locator;
     }
 
+    /**
+     * Returns <em>true</em> if the wrapped locator object is
+     * a ojb specific {@link Lob} implementation (and not a database specific
+     * locator object of a column entry). Else <em>false</em> is returned.
+     */
     public boolean isTransient()
     {
         return isTransient;
     }
 
-    protected void setTransient(boolean aTransient)
-    {
-        isTransient = aTransient;
-    }
+//    protected void setTransient(boolean aTransient)
+//    {
+//        isTransient = aTransient;
+//    }
 
     protected void txFail()
     {
@@ -77,24 +132,36 @@
     {
         this.active = false;
         this.isTransient = false;
+        this.dirty = false;
         this.locator = null;
     }
 
-    protected void inactivate()
+    /**
+     * Called to decouple this LOB object from
+     * a associated {@link org.apache.ojb.broker.PersistenceBroker} instance.
+     */
+    protected void decouple()
     {
         this.active = false;
-        this.isTransient = false;
-        if(!isTransient()) this.locator = null;
+        if(!isTransient())
+        {
+            this.dirty = false;
+            this.locator = null;
+        }
     }
 
-    protected boolean isActive()
+    /**
+     * Returns <em>true</em> if this LOB object is associated
+     * with a {@link org.apache.ojb.broker.PersistenceBroker} instance.
+     */
+    protected boolean isCoupled()
     {
         return this.active;
     }
 
     protected void checkActive()
     {
-        if(!isTransient() && !isActive()) throw new InactiveLobException(
+        if(!isTransient() && !isCoupled()) throw new InactiveLobException(
                 "Current LOB is not valid for access (no active PB-tx or PB-tx changed), "
                         + "refresh the persistent object LOB content after PB-tx starts");
     }
@@ -105,7 +172,7 @@
     //===================================================================
     public void beforeClose(PBStateEvent event)
     {
-        inactivate();
+        decouple();
     }
 
     public void beforeRollback(PBStateEvent event)

Modified: db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/lob/LobHelperImpl.java
URL: http://svn.apache.org/viewvc/db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/lob/LobHelperImpl.java?rev=410616&r1=410615&r2=410616&view=diff
==============================================================================
--- db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/lob/LobHelperImpl.java (original)
+++ db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/lob/LobHelperImpl.java Wed May 31 11:01:48 2006
@@ -108,9 +108,9 @@
 
     public void refreshLob(Object target, ClassDescriptor cld)
     {
-        if(broker.isInTransaction())
+        if(cld.hasLobField())
         {
-            if(cld.hasLobField())
+            if(broker.isInTransaction())
             {
                 FieldDescriptor[] pkFields = cld.getPkFields();
                 FieldDescriptor[] fields = cld.getFieldDescriptor(true);
@@ -119,17 +119,16 @@
                     FieldDescriptor field = fields[i];
                     if(needsRefresh(field, target))
                     {
-                        refreshLob(field, target, pkFields);
+                        performRefreshLob(field, target, pkFields);
                     }
                 }
             }
-        }
-        else
-        {
-            if(log.isDebugEnabled())
+            else
             {
-                log.debug("Can't refresh LOB-objects, an active PB-tx is needed. Specified PersistenceBroker: "
-                        + broker);
+                if(log.isDebugEnabled())
+                {
+                    log.debug("No active transaction, can't refresh LOB-content for object " + target);
+                }
             }
         }
     }
@@ -138,7 +137,7 @@
      * Refresh the specified LOB type field by querying a new LOB-locator object via ReportQuery
      * and replace the LOB-object in source object.
      */
-    protected void refreshLob(FieldDescriptor lobField, Object source, FieldDescriptor[] pkFields)
+    protected void performRefreshLob(FieldDescriptor lobField, Object source, FieldDescriptor[] pkFields)
     {
         if(source == null)
         {
@@ -200,7 +199,7 @@
         if(result)
         {
             Object lob = field.getPersistentField().get(source);
-            if(lob instanceof LobHandle && ((LobHandle) lob).isActive())
+            if(lob instanceof LobHandle && ((LobHandle) lob).isCoupled())
             {
                 // used LOB value doesn't need refresh, it's already bound to a PB instance
                 result = false;

Modified: db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/metadata/ClassDescriptor.java
URL: http://svn.apache.org/viewvc/db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/metadata/ClassDescriptor.java?rev=410616&r1=410615&r2=410616&view=diff
==============================================================================
--- db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/metadata/ClassDescriptor.java (original)
+++ db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/metadata/ClassDescriptor.java Wed May 31 11:01:48 2006
@@ -138,7 +138,7 @@
     /**
      * Indicate whether or not this class has LOB fields.
      */
-    private Boolean hasLobField;
+    private FieldDescriptor[] lobFields;
 
     private String baseClass = null;
     /**
@@ -436,7 +436,7 @@
         m_lockingFieldDescriptors = null;
         m_RwFieldDescriptors = null;
         m_RwNonPkFieldDescriptors = null;
-        hasLobField = null;
+        lobFields = null;
     }
 
     public boolean removeFieldDescriptor(FieldDescriptor fld)
@@ -454,7 +454,7 @@
         m_lockingFieldDescriptors = null;
         m_RwFieldDescriptors = null;
         m_RwNonPkFieldDescriptors = null;
-        hasLobField = null;
+        lobFields = null;
         return result;
     }
 
@@ -2237,23 +2237,40 @@
 
     /**
      * Returns <em>true</em> if this class has one or more LOB fields (Blob, Clob).
+     *
+     * @return <em>True</em> if this class (with inherited) has LOB fields.
      */
     public boolean hasLobField()
     {
-        if(hasLobField == null)
+        return getLobFields().length > 0;
+    }
+
+    /**
+     * Return the LOB fields (including inherited) of this class.
+     *
+     * @return The LOB fields of this class or empty array.
+     */
+    public FieldDescriptor[] getLobFields()
+    {
+        if(lobFields == null)
         {
-            hasLobField = Boolean.FALSE;
+            FieldDescriptor[] result = new FieldDescriptor[]{};
+            ArrayList tmp = new ArrayList();
             FieldDescriptor[] fields = getFieldDescriptor(true);
             for(int i = 0; i < fields.length; i++)
             {
                 FieldDescriptor field = fields[i];
                 if(field.isLobFieldType())
                 {
-                    hasLobField = Boolean.TRUE;
-                    break;
+                    tmp.add(field);
                 }
             }
+            if(tmp.size() > 0)
+            {
+                result = (FieldDescriptor[]) tmp.toArray(new FieldDescriptor[tmp.size()]);
+            }
+            lobFields = result;
         }
-        return hasLobField.booleanValue();
+        return lobFields;
     }
 }

Modified: db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/metadata/FieldType.java
URL: http://svn.apache.org/viewvc/db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/metadata/FieldType.java?rev=410616&r1=410615&r2=410616&view=diff
==============================================================================
--- db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/metadata/FieldType.java (original)
+++ db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/metadata/FieldType.java Wed May 31 11:01:48 2006
@@ -48,20 +48,10 @@
      */
     public boolean equals(Object firstValue, Object secondValue);
 
-//    /**
-//     * Returns the sql {@link java.sql.Types} of this field.
-//     */
-//    public int getSqlType();
-//
-//    /**
-//     * Dets the associated sql field type of this field.
-//     * @param jdbcType The associated {@link org.apache.ojb.broker.metadata.JdbcType}.
-//     */
-//    public void setSqlType(JdbcType jdbcType);
-
     /**
-     * Returns <em>true</em> if the field type is mutable, e.g. a jdbc BLOB field or
-     * jdbc TIMESTAMP field.
+     * Returns <em>true</em> if the field type is mutable, e.g.
+     * <code>Timestamp</code> field. All immutable fields types,
+     * e.g like <code>String</code>, will return <em>false</em>.
      */
     public boolean isMutable();
 

Modified: db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/metadata/FieldTypes.java
URL: http://svn.apache.org/viewvc/db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/metadata/FieldTypes.java?rev=410616&r1=410615&r2=410616&view=diff
==============================================================================
--- db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/metadata/FieldTypes.java (original)
+++ db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/metadata/FieldTypes.java Wed May 31 11:01:48 2006
@@ -21,12 +21,16 @@
 import java.sql.Time;
 import java.sql.Timestamp;
 import java.util.Arrays;
+import java.net.URL;
+import java.net.MalformedURLException;
 
 import org.apache.commons.lang.ArrayUtils;
 import org.apache.commons.lang.ObjectUtils;
 import org.apache.commons.lang.SerializationUtils;
 import org.apache.commons.lang.builder.ToStringBuilder;
 import org.apache.ojb.broker.util.logging.LoggerFactory;
+import org.apache.ojb.broker.OJBRuntimeException;
+import org.apache.ojb.broker.lob.LobHandle;
 
 /**
  * Encapsulates {@link org.apache.ojb.broker.metadata.FieldType} implementations as inner classes.
@@ -153,21 +157,88 @@
     }
 
     /**
-     * Clob (like other LOB's) fields are logical pointer to DB, so
-     * for OJB it's immutable.
-     *
-     * @see BlobFieldType
+     * Base class for LOB fields implemented as mutable field.
      */
-    public static class ClobFieldType extends ImmutableFieldType
+    static class LobFieldType extends MutableFieldType
     {
         public boolean isLobField()
         {
             return true;
         }
+
+        /**
+         * It's not possible to copy locator objects, thus this method always
+         * returns a decoupled LOB wrapper object.
+         *
+         * @param fieldValue The value to copy.
+         * @return A decoupled locator instance.
+         */
+        public Object copy(Object fieldValue)
+        {
+            if(fieldValue != null)
+            {
+                LobHandle lob = (LobHandle) fieldValue;
+                return lob.decoupledCopy();
+            }
+            else
+            {
+                return null;
+            }
+        }
+
+        /**
+         * Compare locator objects is different from "normal fields", because the locator object
+         * itself can't be compared. Thus we expect that the locator is of
+         * type {@link org.apache.ojb.broker.lob.LobHandle}.
+         *
+         * @param firstValue First value to compare.
+         * @param secondValue Second value to compare.
+         * @return The comparision state of both fields.
+         */
+        public boolean equals(Object firstValue, Object secondValue)
+        {
+            LobHandle first = (LobHandle) firstValue;
+            LobHandle second = (LobHandle) secondValue;
+            boolean result = true;
+            if(first != null)
+            {
+                // one was nullified
+                if(second == null)
+                {
+                    result = false;
+                }
+                // both are not null, check internal state
+                else
+                {
+                    result = !first.isDirty() || !second.isDirty();
+                }
+            }
+            else
+            {
+                // second isn't null
+                if(second != null)
+                {
+                    result = false;
+                }
+                // else both are null
+            }
+            return result;
+        }
     }
 
     /**
-     * Blob fields are logical pointer to DB, so for OJB it's immutable.
+     * Clob (like other LOB's) fields normally are logical pointer to DB
+     * thus it's mutable, because the LOB content could change.
+     *
+     * @see BlobFieldType
+     */
+    public static class ClobFieldType extends LobFieldType
+    {
+    }
+
+    /**
+     * Blob (like other LOB's) fields normally are logical pointer to DB
+     * thus it's mutable, because the LOB content could change.
      * Snip of JDBC specification:
      * "An application does not deal directly with the LOCATOR(blob) and
      * LOCATOR(clob) types that are defined in SQL. By default, a JDBC
@@ -175,12 +246,8 @@
      * appropriate locator type. Also by default, Blob and Clob objects
      * remain valid only during the transaction in which they are created."
      */
-    public static class BlobFieldType extends ImmutableFieldType
+    public static class BlobFieldType extends LobFieldType
     {
-        public boolean isLobField()
-        {
-            return true;
-        }
     }
 
     /**
@@ -290,6 +357,22 @@
         }
     }
 
+    public static class URLFieldType extends MutableFieldType
+    {
+        public Object copy(Object fieldValue)
+        {
+            URL url = (URL) fieldValue;
+            try
+            {
+                return new URL(url.getProtocol(), url.getHost(), url.getPort(), url.getFile());
+            }
+            catch(MalformedURLException e)
+            {
+                throw new CopyException("Can't copy URL: " + fieldValue);
+            }
+        }
+    }
+
     public static class StringFieldType extends ImmutableFieldType
     {
     }
@@ -331,8 +414,29 @@
 
     }
 
-    public static class URLFieldType extends ImmutableFieldType
+    /**
+     * A <em>CopyException</em> is thrown when an unexpected field copy error occur.
+     */
+    public static class CopyException extends OJBRuntimeException
     {
+        public CopyException()
+        {
+            super();
+        }
 
+        public CopyException(String msg)
+        {
+            super(msg);
+        }
+
+        public CopyException(Throwable cause)
+        {
+            super(cause);
+        }
+
+        public CopyException(String msg, Throwable cause)
+        {
+            super(msg, cause);
+        }
     }
 }



---------------------------------------------------------------------
To unsubscribe, e-mail: ojb-dev-unsubscribe@db.apache.org
For additional commands, e-mail: ojb-dev-help@db.apache.org