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