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/07/15 16:20:27 UTC

svn commit: r422231 [1/4] - in /db/ojb/trunk/src/java/org/apache/ojb/broker: ./ accesslayer/ accesslayer/sql/ cache/ core/ locking/ metadata/ metadata/fieldaccess/

Author: arminw
Date: Sat Jul 15 07:20:25 2006
New Revision: 422231

URL: http://svn.apache.org/viewvc?rev=422231&view=rev
Log:
merge trunk with 1.0.x

Modified:
    db/ojb/trunk/src/java/org/apache/ojb/broker/ContainerHelper.java
    db/ojb/trunk/src/java/org/apache/ojb/broker/Identity.java
    db/ojb/trunk/src/java/org/apache/ojb/broker/IdentityFactory.java
    db/ojb/trunk/src/java/org/apache/ojb/broker/accesslayer/SqlBasedReportQueryRsIterator.java
    db/ojb/trunk/src/java/org/apache/ojb/broker/accesslayer/sql/SqlUpdateStatement.java
    db/ojb/trunk/src/java/org/apache/ojb/broker/cache/MaterializationCache.java
    db/ojb/trunk/src/java/org/apache/ojb/broker/cache/SessionCacheImpl.java
    db/ojb/trunk/src/java/org/apache/ojb/broker/core/DelegatingPersistenceBroker.java
    db/ojb/trunk/src/java/org/apache/ojb/broker/core/IdentityFactoryImpl.java
    db/ojb/trunk/src/java/org/apache/ojb/broker/core/PersistenceBrokerAbstractImpl.java
    db/ojb/trunk/src/java/org/apache/ojb/broker/core/PersistenceBrokerFactoryDefaultImpl.java
    db/ojb/trunk/src/java/org/apache/ojb/broker/core/PersistenceBrokerHandle.java
    db/ojb/trunk/src/java/org/apache/ojb/broker/core/PersistenceBrokerImpl.java
    db/ojb/trunk/src/java/org/apache/ojb/broker/core/QueryReferenceBroker.java
    db/ojb/trunk/src/java/org/apache/ojb/broker/core/ValueContainer.java
    db/ojb/trunk/src/java/org/apache/ojb/broker/locking/IsolationLevels.java
    db/ojb/trunk/src/java/org/apache/ojb/broker/locking/LockIsolation.java
    db/ojb/trunk/src/java/org/apache/ojb/broker/locking/LockIsolationManager.java
    db/ojb/trunk/src/java/org/apache/ojb/broker/locking/LockManager.java
    db/ojb/trunk/src/java/org/apache/ojb/broker/locking/LockManagerCommonsImpl.java
    db/ojb/trunk/src/java/org/apache/ojb/broker/locking/LockManagerInMemoryImpl.java
    db/ojb/trunk/src/java/org/apache/ojb/broker/locking/LockManagerRemoteImpl.java
    db/ojb/trunk/src/java/org/apache/ojb/broker/locking/LockManagerServlet.java
    db/ojb/trunk/src/java/org/apache/ojb/broker/metadata/ClassDescriptor.java
    db/ojb/trunk/src/java/org/apache/ojb/broker/metadata/CollectionDescriptor.java
    db/ojb/trunk/src/java/org/apache/ojb/broker/metadata/fieldaccess/AnonymousPersistentField.java
    db/ojb/trunk/src/java/org/apache/ojb/broker/metadata/fieldaccess/PersistentField.java
    db/ojb/trunk/src/java/org/apache/ojb/broker/metadata/fieldaccess/PersistentFieldAutoProxyImpl.java
    db/ojb/trunk/src/java/org/apache/ojb/broker/metadata/fieldaccess/PersistentFieldBase.java
    db/ojb/trunk/src/java/org/apache/ojb/broker/metadata/fieldaccess/PersistentFieldDirectImpl.java
    db/ojb/trunk/src/java/org/apache/ojb/broker/metadata/fieldaccess/PersistentFieldDynaBeanImpl.java
    db/ojb/trunk/src/java/org/apache/ojb/broker/metadata/fieldaccess/PersistentFieldIntrospectorImpl.java

Modified: db/ojb/trunk/src/java/org/apache/ojb/broker/ContainerHelper.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/broker/ContainerHelper.java?rev=422231&r1=422230&r2=422231&view=diff
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/broker/ContainerHelper.java (original)
+++ db/ojb/trunk/src/java/org/apache/ojb/broker/ContainerHelper.java Sat Jul 15 07:20:25 2006
@@ -47,6 +47,7 @@
 import org.apache.ojb.broker.cache.SessionCache;
 import org.apache.ojb.broker.core.IdentityFactoryImpl;
 import org.apache.ojb.broker.core.PBPoolConfiguration;
+import org.apache.ojb.broker.core.PersistenceBrokerAbstractImpl;
 import org.apache.ojb.broker.core.PersistenceBrokerFactoryDefaultImpl;
 import org.apache.ojb.broker.core.PersistenceBrokerFactoryIF;
 import org.apache.ojb.broker.core.PersistenceBrokerImpl;
@@ -62,6 +63,8 @@
 import org.apache.ojb.broker.core.proxy.ProxyFactoryJDKImpl;
 import org.apache.ojb.broker.core.proxy.SetProxy;
 import org.apache.ojb.broker.core.proxy.SetProxyDefaultImpl;
+import org.apache.ojb.broker.lob.LobHelper;
+import org.apache.ojb.broker.lob.LobHelperImpl;
 import org.apache.ojb.broker.locking.LockManager;
 import org.apache.ojb.broker.locking.LockManagerInMemoryImpl;
 import org.apache.ojb.broker.locking.LockManagerRemoteImpl;
@@ -117,11 +120,17 @@
                             MetadataManager.class.getName() + ".usingSerializedRepository");
         _translationMap.put("serializedRepositoryPath",
                             MetadataManager.class.getName() + ".serializedRepositoryPath");
+        _translationMap.put("RepositoryPersistorClass",
+                            MetadataManager.class.getName() + ".repositoryPersistorClass");
 
         _translationMap.put("PersistenceBrokerFactoryClass",
                             PersistenceBrokerFactoryIF.class.getName() + ".class");
         _translationMap.put("PersistenceBrokerClass",
                             PersistenceBroker.class.getName() + ".class");
+        _translationMap.put("TxCheck",
+                            PersistenceBrokerAbstractImpl.class.getName() + ".txCheck");
+        _translationMap.put("BrokerLeakDetection",
+                            PersistenceBrokerImpl.class.getName() + ".brokerLeakDetection");
         
         _translationMap.put("maxActive",
                             PBPoolConfiguration.class.getName() + ".maxActive");
@@ -166,6 +175,10 @@
                             IdentityFactory.class.getName() + ".class");
         _translationMap.put("ObjectFactoryClass",
                             ObjectFactory.class.getName() + ".class");
+        _translationMap.put("LobHelperClass",
+                            LobHelper.class.getName() + ".class");
+        _translationMap.put("LobAutoRefresh",
+                            LobHelper.class.getName() + ".lobAutoRefresh");
 
         _translationMap.put("SessionCacheClass",
                             SessionCache.class.getName() + ".class");
@@ -194,8 +207,6 @@
                             ImplementationExt.class.getName() + ".impliciteWriteLocks");
         _translationMap.put("Ordering",
                             ImplementationExt.class.getName() + ".ordering");
-        _translationMap.put("NoteUserOrder",
-                            ImplementationExt.class.getName() + ".noteUserOrder");
         _translationMap.put("LockManagerOdmgClass",
                             org.apache.ojb.odmg.locking.LockManager.class.getName() + ".class");
         _translationMap.put("DListClass",
@@ -244,6 +255,9 @@
         container.ensureImplementationClass(ConnectionFactory.class, ConnectionFactoryPooledImpl.class);
         container.ensureImplementationClass(ConnectionManagerIF.class, ConnectionManagerImpl.class);
         container.ensureImplementationClass(IdentityFactory.class, IdentityFactoryImpl.class);
+        container.ensureImplementationClass(LobHelper.class, LobHelperImpl.class);
+        // todo: is this needed, register a a normal class?
+        //container.ensureImplementationClass(RepositoryPersistor.class, RepositoryPersistor.class);
         container.ensureImplementationClass(Implementation.class, ImplementationImpl.class);
         container.ensureImplementationClass(JdbcAccess.class, JdbcAccessImpl.class);
         container.ensureImplementationClass(LockManager.class, LockManagerInMemoryImpl.class);
@@ -313,6 +327,7 @@
 
             if (url == null)
             {
+                log.info("No success load resource '" + path +"', try to load OJB's properties as file");
                 url = (new File(path)).toURL();
             }
 

Modified: db/ojb/trunk/src/java/org/apache/ojb/broker/Identity.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/broker/Identity.java?rev=422231&r1=422230&r2=422231&view=diff
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/broker/Identity.java (original)
+++ db/ojb/trunk/src/java/org/apache/ojb/broker/Identity.java Sat Jul 15 07:20:25 2006
@@ -49,11 +49,15 @@
  * <li>
  * an array of all primary key value objects
  * </li>
+ * <li>
+ * a flag which indicates whether this is a <em>transient Identity</em>
+ * (identity of a non-persistent, "new" object) or a <em>persistent Identity</em> (identity object
+ * of a persistent, "already written to datastore" object).
+ * </li>
  * </ul>
  * <p>
- * If in the metadata of an persistent capable object class the attribute <em>autoincrement</em>
- * is set true, new primary key values will be automatic assigned to the given object passed as
- * constructor argument.
+ * To create <code>Identity</code> objects it's strongly recommended to use the {@link IdentityFactory}, because
+ * in future releases of OJB the <code>Identity</code> constructors will be no longer reachable or forbidden to use.
  * </p>
  * <p>
  * NOTE: An <em>Identity</em> object must be unique
@@ -62,34 +66,37 @@
  * </p>
  * @see org.apache.ojb.broker.IdentityFactory
 
- * @author <a href="mailto:thma@apache.org">Thomas Mahler<a>
  * @version $Id$
  */
 public class Identity implements Serializable
 {
-	static final long serialVersionUID = 3182285550574178710L;
+    /** Unique id for serialization purposes. */
+    private static final long serialVersionUID = 3182285550574178710L;
+
+    private static final int IS_TRANSIENT = 3;
+    private static final int IS_PERMANENT = 17;
     /**
-     * used for hashCode calculation.
+     * Used for hashCode calculation.
      */
     private static final int iConstant = 37;
 
     /**
-     * the top-level Class of the identified object<br>
-     * ie: an Interface
+     * The top-level Class of the identified object, ie. an interface.
      */
     private Class m_objectsTopLevelClass;
 
     /**
-     * the real Class of the identified object<br>
-     * ie: the implementing Class
+     * The real Class of the identified object, ie. the implementing class.
      */
     private Class m_objectsRealClass = null;
 
     /**
-     * The ordered list of primary key values maintaining the objects identity in the underlying RDBMS
+     * The ordered list of primary key values maintaining the objects identity in the underlying RDBMS.
      */
     private Object[] m_pkValues;
 
+    private final int isTransient;
+
     /*
     the hashcode of different objects has to be unique across different
     JVM and have to be the same for the same object in different JVM.
@@ -102,26 +109,39 @@
     private transient Integer m_hashCode;
 
     /**
-     * creates an Identity from a class and the objects primary key values.
+     * For internal use only!
+     */
+    protected Identity()
+    {
+        isTransient = IS_TRANSIENT;
+    }
+
+    /**
+     * For internal use only!. Creates an em from a class and the objects primary key values.
      * used for the definition of proxies.
+     * <br/>
+     * OJB user have to use {@link IdentityFactory} to create object identity.
+     *
      *
      * @param realClass the concrete class of the object, or null if not known.
      * @param topLevel the highest persistence-capable class or
      * interface (in the inheritance hierarchy) that the identified object is an instance of
      * @param pkValues (unique across the extents !)
+     * @param isTransient If <em>true</em>
     */
-    public Identity(final Class realClass, final Class topLevel, final Object[] pkValues)
+    public Identity(final Class realClass, final Class topLevel, final Object[] pkValues, final boolean isTransient)
     {
         m_objectsTopLevelClass = topLevel;
         m_objectsRealClass = realClass;
         m_pkValues = pkValues;
+        this.isTransient = isTransient ? IS_TRANSIENT : IS_PERMANENT;
         checkForPrimaryKeys(null);
     }
 
     /**
-     * Creates an identity object for the given class descriptor by reading the field values from
-     * the given map.
-     * 
+     * For internal use only! Creates an identity object for the given class
+     * descriptor by reading the field values from the given map.
+     *
      * @param targetClass The target class descriptor
      * @param topLevel    The highest persistence-capable class
      * @param fields      The fields to use for building the identity
@@ -137,18 +157,54 @@
         }
 
         m_objectsTopLevelClass = topLevel;
-        m_objectsRealClass     = targetClass.getClassOfObject();
+        m_objectsRealClass     = targetClass.isMappedToTable() ? targetClass.getClassOfObject() : null;
         m_pkValues             = values;
+        this.isTransient = IS_PERMANENT;
+        checkForPrimaryKeys(null);
+    }
+
+    /**
+     * For internal use only! Creates an Identity from a class and the objects primary key values.
+     * used for the definition of proxies.
+     * <br/>
+     * OJB user have to use {@link IdentityFactory} to create object identity.
+     * 
+     * @param realClass the concrete class of the object, or null if not known.
+     * @param topLevel the highest persistence-capable class or
+     * interface (in the inheritance hierarchy) that the identified object is an instance of
+     * @param pkValues (unique across the extents !)
+     */
+    public Identity(final Class realClass, final Class topLevel, final Object[] pkValues)
+    {
+        m_objectsTopLevelClass = topLevel;
+        m_objectsRealClass = realClass;
+        m_pkValues = pkValues;
+        this.isTransient = IS_PERMANENT;
         checkForPrimaryKeys(null);
     }
 
+    /**
+     * Constructor for internal use. Use {@link IdentityFactory} to create an object identity.
+     *
+     * @param objectToIdentitify The object for which to create the identity
+     * @param targetBroker       The persistence broker
+     */
     public Identity(final Object objectToIdentitify, final PersistenceBroker targetBroker)
     {
+        this.isTransient = IS_PERMANENT;
         init(objectToIdentitify, targetBroker, null);
     }
 
+    /**
+     * Constructor for internal use. Use {@link IdentityFactory} to create an object identity.
+     *
+     * @param objectToIdentitify The object for which to create the identity
+     * @param targetBroker       The persistence broker
+     * @param cld                The class descriptor
+     */
     public Identity(final Object objectToIdentitify, final PersistenceBroker targetBroker, final ClassDescriptor cld)
     {
+        this.isTransient = IS_PERMANENT;
         init(objectToIdentitify, targetBroker, cld);
     }
 
@@ -157,36 +213,38 @@
         if(objectToIdentify == null) throw new OJBRuntimeException("Can't create Identity for 'null'-object");
         try
         {
-            //IndirectionHandler handler = ProxyHelper.getIndirectionHandler(objectToIdentify);
             final IndirectionHandler handler = targetBroker.getConfiguration().getOjb().getProxyFactory().getIndirectionHandler(objectToIdentify);
 
-            if (handler != null)
-            {
-                final Identity sourceOID = handler.getIdentity();
-                m_objectsTopLevelClass = sourceOID.m_objectsTopLevelClass;
-                m_objectsRealClass = sourceOID.m_objectsRealClass;
-                m_pkValues = sourceOID.m_pkValues;
-            }
-            else
+            synchronized(objectToIdentify)
             {
-                if (cld == null)
+                if (handler != null)
                 {
-                    cld = targetBroker.getClassDescriptor(objectToIdentify.getClass());
+                    final Identity sourceOID = handler.getIdentity();
+                    m_objectsTopLevelClass = sourceOID.m_objectsTopLevelClass;
+                    m_objectsRealClass = sourceOID.m_objectsRealClass;
+                    m_pkValues = sourceOID.m_pkValues;
                 }
-
-                // identities must be unique accross extents !
-                m_objectsTopLevelClass = targetBroker.getTopLevelClass(objectToIdentify.getClass());
-                m_objectsRealClass = objectToIdentify.getClass();
-
-                // BRJ: definitely do NOT convertToSql
-                // conversion is done when binding the sql-statement
-                final BrokerHelper helper = targetBroker.serviceBrokerHelper();
-                final ValueContainer[] pkValues = helper.getKeyValues(cld, objectToIdentify, false);
-                if (pkValues == null || pkValues.length == 0)
+                else
                 {
-                    throw createException("Can't extract PK value fields", objectToIdentify, null);
+                    if (cld == null)
+                    {
+                        cld = targetBroker.getClassDescriptor(objectToIdentify.getClass());
+                    }
+
+                    // identities must be unique accross extents !
+                    m_objectsTopLevelClass = targetBroker.getTopLevelClass(objectToIdentify.getClass());
+                    m_objectsRealClass = objectToIdentify.getClass();
+
+                    // BRJ: definitely do NOT convertToSql
+                    // conversion is done when binding the sql-statement
+                    final BrokerHelper helper = targetBroker.serviceBrokerHelper();
+                        final ValueContainer[] pkValues = helper.getValuesForObject(cld.getPkFields(), objectToIdentify, false, true);
+                    if (pkValues == null || pkValues.length == 0)
+                    {
+                        throw createException("Can't extract PK value fields", objectToIdentify, null);
+                    }
+                    m_pkValues = helper.extractValueArray(pkValues);
                 }
-                m_pkValues = helper.extractValueArray(pkValues);
             }
 
             checkForPrimaryKeys(objectToIdentify);
@@ -202,8 +260,11 @@
     }
 
     /**
-     * Factory method that returns an Identity object from the given
-     * byte array - see {@link #serialize}.
+     * Factory method that returns an Identity object created from a serializated representation.
+     *
+     * @param anArray The serialized representation
+     * @return The identity
+     * @see {@link #serialize}.
      * @deprecated
      */
     public static Identity fromByteArray(final byte[] anArray) throws PersistenceBrokerException
@@ -213,10 +274,10 @@
         // a GZIPInputStream and then deserialize by reading from the ObjectInputStream
         try
         {
-            ByteArrayInputStream bais = new ByteArrayInputStream(anArray);
-            GZIPInputStream gis = new GZIPInputStream(bais);
-            ObjectInputStream ois = new ObjectInputStream(gis);
-            Identity result = (Identity) ois.readObject();
+            final ByteArrayInputStream bais = new ByteArrayInputStream(anArray);
+            final GZIPInputStream gis = new GZIPInputStream(bais);
+            final ObjectInputStream ois = new ObjectInputStream(gis);
+            final Identity result = (Identity) ois.readObject();
             ois.close();
             gis.close();
             bais.close();
@@ -229,11 +290,21 @@
     }
 
     /**
-     * Return the top-level class of the real
-     * subject (means class name of a base class,
+     * Determines whether the identity is transient.
+     *
+     * @return <code>true</code> if the identity is transient
+     */
+    public boolean isTransient()
+    {
+        return isTransient == IS_TRANSIENT;
+    }
+
+    /**
+     * Returns the top-level class of the real subject (base class,
      * base interface denoted in the repository or
-     * objects real class name if none top-level was found)
+     * objects real class if no top-level was found).
      *
+     * @return The top level class
      */
     public Class getObjectsTopLevelClass()
     {
@@ -241,7 +312,9 @@
     }
 
     /**
-     * Return the "real" Class of the real subject
+     * Return the "real" class of the real subject.
+     *
+     * @return The real class
      */
     public Class getObjectsRealClass()
     {
@@ -249,7 +322,9 @@
     }
 
     /**
-     * Set the objects real class
+     * Set the real class of the subject.
+     *
+     * @param objectsRealClass The real class
      */
     public void setObjectsRealClass(final Class objectsRealClass)
     {
@@ -257,8 +332,11 @@
     }
 
     /**
-     * Return a serialized Identity as byte[].
+     * Return the serialized form of this Identity.
+     *
+     * @return The serialized representation
      * @see #fromByteArray
+     * @deprecated
      */
     public byte[] serialize() throws PersistenceBrokerException
     {
@@ -299,6 +377,7 @@
                 buf.append(m_pkValues[i]);
             }
             buf.append("}");
+            if(isTransient == IS_TRANSIENT) buf.append("-transient");
             m_stringRepresentation = buf.toString();
         }
         return m_stringRepresentation;
@@ -308,8 +387,9 @@
     /**
      * OJB can handle only classes that declare at least one primary key attribute,
      * this method checks this condition.
-     * @exception ClassNotPersistenceCapableException thrown if no primary key is
-     * specified for the objects class
+     *
+     * @param realObject The real object to check
+     * @throws ClassNotPersistenceCapableException thrown if no primary key is specified for the objects class
      */
     protected void checkForPrimaryKeys(final Object realObject) throws ClassNotPersistenceCapableException
     {
@@ -324,8 +404,9 @@
     }
 
     /**
-     * return the list of Primary Key Values of the real subject
-     * @return Object[]
+     * Returns the primary key values of the real subject.
+     *
+     * @return The pk values
      */
     public Object[] getPrimaryKeyValues()
     {
@@ -333,8 +414,7 @@
     }
 
     /**
-     * Compare this Identity object to any other object. This comparison is delegated
-     * to the super-class.
+     * {@inheritDoc}
      */
     public boolean equals(final Object obj)
     {
@@ -344,7 +424,7 @@
         if (obj instanceof Identity)
         {
             final Identity id = (Identity) obj;
-            result = m_objectsTopLevelClass.equals(id.m_objectsTopLevelClass);
+            result = m_objectsTopLevelClass.equals(id.m_objectsTopLevelClass) && isTransient == id.isTransient;
             if(result)
             {
                 final Object[] otherPkValues = id.m_pkValues;
@@ -369,12 +449,7 @@
     }
 
     /**
-     * Calculate a hashcode for this Identity. The Hashcode should be
-     * equal for Identities where Identity.equals() returns true. Therefore
-     * all primary key values that return a hashcode depending on its content
-     * (this is assumed for String and Number) are taken into account. Additionally
-     * the hashCode() of the top-level class name of this Identity is representing
-     * is taken into account.
+     * {@inheritDoc}
      */
     public int hashCode()
     {
@@ -385,7 +460,7 @@
         */
         if(m_hashCode == null)
         {
-            int iTotal = 17;
+            int iTotal = isTransient;
             Object obj;
             for (int i = 0; i < m_pkValues.length; i++)
             {

Modified: db/ojb/trunk/src/java/org/apache/ojb/broker/IdentityFactory.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/broker/IdentityFactory.java?rev=422231&r1=422230&r2=422231&view=diff
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/broker/IdentityFactory.java (original)
+++ db/ojb/trunk/src/java/org/apache/ojb/broker/IdentityFactory.java Sat Jul 15 07:20:25 2006
@@ -1,5 +1,20 @@
 package org.apache.ojb.broker;
 
+/* Copyright 2002-2005 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 import org.apache.ojb.broker.metadata.ClassDescriptor;
 
 /**
@@ -14,14 +29,13 @@
  * </ul>
  * NOTE:
  * <br/>
- * It is possible to assign new created objects
- * with a valid UID before they are written to database - more info see {@link org.apache.ojb.broker.Identity}.
- * This should be
- * used with care, because not all {@link org.apache.ojb.broker.util.sequence.SequenceManager}
- * implementations return the "real" UID value before the object was stored (e.g. when database based
- * Identity columns are used, a temporary placeholder is returned).
+ * It is possible to create transient {@link Identity} objects for transient,
+ * "new created" persistence capable objects. But keep in mind that this transient
+ * {@link Identity} object is only valid till the persistence capable object was written
+ * to datastore. After this the {@link Identity} have to be renewed by calling
+ * <code>IdentityFactory.buildIdentity(...)</code> again (then the transient Identity
+ * will be replaced by the persistent Identity).
  *
- * @author <a href="mailto:armin@codeAuLait.de">Armin Waibel</a>
  * @version $Id$
  */
 public interface IdentityFactory
@@ -30,8 +44,8 @@
      * Build a unique {@link org.apache.ojb.broker.Identity} for the given
      * persistence capable object.
      *
-     * @param obj The object to build the {@link Identity} for.
-     * @return The a new created <em>Identity</em> object.
+     * @param obj The object to build the {@link Identity} for
+     * @return The new <em>Identity</em> object
      */
     Identity buildIdentity(Object obj);
 
@@ -39,10 +53,9 @@
      * Build a unique {@link org.apache.ojb.broker.Identity} for the given
      * persistence capable object.
      *
-     * @param cld The {@link org.apache.ojb.broker.metadata.ClassDescriptor} of the
-     * object.
-     * @param obj The object to build the {@link Identity} for.
-     * @return The a new created <em>Identity</em> object.
+     * @param cld The {@link org.apache.ojb.broker.metadata.ClassDescriptor} of the object
+     * @param obj The object to build the {@link Identity} for
+     * @return The new <em>Identity</em> object.
      */
     Identity buildIdentity(ClassDescriptor cld, Object obj);
 
@@ -51,27 +64,32 @@
      * for the given primary key values (composite PK's) of a
      * persistence capable object.
      *
-     * @param realClass The class of the associated object.
-     * @param topLevelClass The top-level class of the associated object.
-     * @param pkFieldName The field names of the PK fields.
-     * @param pkValues The PK values.
-     * @return The a new created <em>Identity</em> object.
+     * @param realClass     The class of the associated object
+     * @param topLevelClass The top-level class of the associated object
+     * @param pkFieldName   The field names of the PK fields
+     * @param pkValues      The PK values
+     * @return The new <em>Identity</em> object
      */
     Identity buildIdentity(Class realClass, Class topLevelClass, String[] pkFieldName, Object[] pkValues);
 
     /**
-     * Convenience method for
-     * {@link #buildIdentity(java.lang.Class, java.lang.Class, java.lang.String[], java.lang.Object[])}
+     * Convenience shortcut method for
+     * {@link #buildIdentity(java.lang.Class, java.lang.Class, java.lang.String[], java.lang.Object[])}.
+     *
+     * @param realClass     The class of the associated object
+     * @param pkFieldName   The field names of the PK fields
+     * @param pkValues      The PK values
+     * @return The new <em>Identity</em> object
      */
-    Identity buildIdentity(Class realClass, String[] fieldName, Object[] pkValues);
+    Identity buildIdentity(Class realClass, String[] pkFieldName, Object[] pkValues);
 
     /**
      * Convenience method for persistent objects with single primary key.
      * NOTE: Do not use for objects with composed PK!
      *
-     * @param realClass The class of the associated object.
-     * @param pkValue The PK value.
-     * @return The a new created <em>Identity</em> object.
+     * @param realClass The class of the associated object
+     * @param pkValue   The PK value
+     * @return The new <em>Identity</em> object
      * @see #buildIdentity(java.lang.Class, java.lang.String[], java.lang.Object[])
      */
     Identity buildIdentity(Class realClass, Object pkValue);
@@ -79,12 +97,13 @@
     /**
      * Create a new {@link Identity} object based on given arguments - NOTE: There
      * will be no check to resolve the order of the PK values. This method expect
-     * the correct order.
+     * the correct order based on the declaration of the {@link org.apache.ojb.broker.metadata.FieldDescriptor}
+     * in the mapping file.
      *
-     * @param realClass The class of the associated object.
-     * @param topLevelClass The top-level class of the associated object.
-     * @param pkValues The PK values.
-     * @return The a new created <em>Identity</em> object.
+     * @param realClass     The class of the associated object
+     * @param topLevelClass The top-level class of the associated object
+     * @param pkValues      The PK values
+     * @return The new <em>Identity</em> object
      */
     Identity buildIdentity(Class realClass, Class topLevelClass, Object[] pkValues);
 }

Modified: db/ojb/trunk/src/java/org/apache/ojb/broker/accesslayer/SqlBasedReportQueryRsIterator.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/broker/accesslayer/SqlBasedReportQueryRsIterator.java?rev=422231&r1=422230&r2=422231&view=diff
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/broker/accesslayer/SqlBasedReportQueryRsIterator.java (original)
+++ db/ojb/trunk/src/java/org/apache/ojb/broker/accesslayer/SqlBasedReportQueryRsIterator.java Sat Jul 15 07:20:25 2006
@@ -21,11 +21,11 @@
 import org.apache.ojb.broker.PersistenceBrokerException;
 import org.apache.ojb.broker.PersistenceBrokerInternal;
 import org.apache.ojb.broker.metadata.JdbcTypesHelper;
+import org.apache.ojb.broker.metadata.JdbcType;
 
 /**
  * ReporQueryRsIterator based on SQL-Statement
  *
- * @author <a href="mailto:jbraeuchi@gmx.ch">Jakob Braeuchi</a>
  * @version $Id$
  */
 public class SqlBasedReportQueryRsIterator extends SqlBasedRsIterator
@@ -65,8 +65,9 @@
             try
             {
                 int jdbcType = rsMetaData.getColumnType(i + 1);
-                Object item = JdbcTypesHelper.getObjectFromColumn(getRsAndStmt().m_rs, new Integer(jdbcType), i + 1);
-                result[i] = item;
+                JdbcType type = JdbcTypesHelper.getJdbcTypeByTypesIndex(new Integer(jdbcType));
+                //Object item = JdbcTypesHelper.getObjectFromColumn(getRsAndStmt().m_rs, new Integer(jdbcType), i + 1);
+                result[i] = type.getObjectFromColumn(getRsAndStmt().m_rs, i + 1);
             }
             catch (SQLException e)
             {

Modified: db/ojb/trunk/src/java/org/apache/ojb/broker/accesslayer/sql/SqlUpdateStatement.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/broker/accesslayer/sql/SqlUpdateStatement.java?rev=422231&r1=422230&r2=422231&view=diff
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/broker/accesslayer/sql/SqlUpdateStatement.java (original)
+++ db/ojb/trunk/src/java/org/apache/ojb/broker/accesslayer/sql/SqlUpdateStatement.java Sat Jul 15 07:20:25 2006
@@ -23,7 +23,6 @@
 /**
  * Model an UPDATE Statement
  * 
- * @author <a href="mailto:jbraeuchi@gmx.ch">Jakob Braeuchi</a>
  * @version $Id$
  */
 public class SqlUpdateStatement extends SqlPkStatement

Modified: db/ojb/trunk/src/java/org/apache/ojb/broker/cache/MaterializationCache.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/broker/cache/MaterializationCache.java?rev=422231&r1=422230&r2=422231&view=diff
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/broker/cache/MaterializationCache.java (original)
+++ db/ojb/trunk/src/java/org/apache/ojb/broker/cache/MaterializationCache.java Sat Jul 15 07:20:25 2006
@@ -29,14 +29,13 @@
  * materialized objects to higher level caches this class act as a temporary storage
  * for unmaterialized (new read or refreshed) objects.
  *
- * @author <a href="mailto:arminw@apache.org">Armin Waibel</a>
  * @version $Id$
  */
 class MaterializationCache
 {
     private static Logger log = LoggerFactory.getLogger(MaterializationCache.class);
 
-    private static final int INITIAL_CAPACITY = 75;
+    private static final int INITIAL_CAPACITY = 100;
 
     private HashMap objectBuffer;
     private boolean enabledReadCache;
@@ -51,6 +50,17 @@
     }
 
     /**
+     * Returns <em>true</em> if the cache is enabled.
+     *
+     * @return The cache state.
+     * @see #enableMaterializationCache() 
+     */
+    public boolean isEnabledMaterializationCache()
+    {
+        return enabledReadCache;
+    }
+
+    /**
      * For internal use only! Helper method to guarantee that only full materialized objects
      * will be pushed to the application cache regardless if an local PB transaction
      * is running or not. When a complex object is materialized there will be
@@ -71,6 +81,8 @@
     }
 
     /**
+     * Disable the cache.
+     *
      * @see #enableMaterializationCache()
      */
     public void disableMaterializationCache()
@@ -101,6 +113,12 @@
         }
     }
 
+    /**
+     * Lookup an object from cache.
+     *
+     * @param oid The {@link org.apache.ojb.broker.Identity} object.
+     * @return The cached {@link ObjectEntry} or <em>null</em>.
+     */
     public ObjectEntry lookup(Identity oid)
     {
         ObjectEntry result = null;
@@ -111,16 +129,29 @@
         return result;
     }
 
+    /**
+     * Evict the specified object from cache.
+     *
+     * @param oid The {@link org.apache.ojb.broker.Identity} object.
+     */
     public void evict(Identity oid)
     {
         objectBuffer.remove(oid);
     }
 
+    /**
+     * Evict the cache.
+     */
     public void evictAll()
     {
         objectBuffer.clear();
     }
 
+    /**
+     * Evict all objects of the specified (top-level) class.
+     *
+     * @param topLevelClass
+     */
     public void evict(Class topLevelClass)
     {
         Iterator it = objectBuffer.keySet().iterator();
@@ -135,6 +166,12 @@
         }
     }
 
+    /**
+     * Put the object to cache - if the cache is enabled.
+     *
+     * @param entry The object to cache.
+     * @see #enableMaterializationCache()
+     */
     public void cache(SessionEntry entry)
     {
         if(enabledReadCache)
@@ -143,6 +180,10 @@
         }
     }
 
+    /**
+     * Push all cached objects to the session cache, if the
+     * specified cache level is higher then {@link SessionCache.LEVEL_MATERIALIZE}.
+     */
     private void pushObjects()
     {
         Iterator it = objectBuffer.values().iterator();
@@ -158,16 +199,14 @@
         }
     }
 
+    /**
+     * Reset the whole cache.
+     */
     public void reset()
     {
         if(log.isDebugEnabled()) log.debug("Reset materialization cache");
         invokeCounter = 0;
         enabledReadCache = false;
         objectBuffer.clear();
-    }
-
-    public boolean isEnabledMaterializationCache()
-    {
-        return enabledReadCache;
     }
 }

Modified: db/ojb/trunk/src/java/org/apache/ojb/broker/cache/SessionCacheImpl.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/broker/cache/SessionCacheImpl.java?rev=422231&r1=422230&r2=422231&view=diff
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/broker/cache/SessionCacheImpl.java (original)
+++ db/ojb/trunk/src/java/org/apache/ojb/broker/cache/SessionCacheImpl.java Sat Jul 15 07:20:25 2006
@@ -312,6 +312,9 @@
         }
         finally
         {
+            /*
+            todo: Shall we really evict the session cache on commit of tx or shall we make this configurable?
+            */
             evictAll(LEVEL_SESSION);
         }
     }
@@ -373,8 +376,7 @@
 
 
     /**
-     * @author <a href="mailto:arminw@apache.org">Armin Waibel</a>
-     * @version $Id$
+     * This class wraps the cached object.
      */
     static final class SessionEntryImpl implements SessionEntry
     {

Modified: db/ojb/trunk/src/java/org/apache/ojb/broker/core/DelegatingPersistenceBroker.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/broker/core/DelegatingPersistenceBroker.java?rev=422231&r1=422230&r2=422231&view=diff
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/broker/core/DelegatingPersistenceBroker.java (original)
+++ db/ojb/trunk/src/java/org/apache/ojb/broker/core/DelegatingPersistenceBroker.java Sat Jul 15 07:20:25 2006
@@ -34,6 +34,7 @@
 import org.apache.ojb.broker.TransactionAbortedException;
 import org.apache.ojb.broker.TransactionInProgressException;
 import org.apache.ojb.broker.TransactionNotInProgressException;
+import org.apache.ojb.broker.lob.LobHelper;
 import org.apache.ojb.broker.accesslayer.CollectionCreationContext;
 import org.apache.ojb.broker.accesslayer.ConnectionManagerIF;
 import org.apache.ojb.broker.accesslayer.JdbcAccess;
@@ -154,9 +155,6 @@
         return getBroker().getReferenceBroker();
     }
 
-    /**
-     * @see org.apache.ojb.broker.PersistenceBrokerInternal#refreshRelationships(java.lang.Object, org.apache.ojb.broker.metadata.ClassDescriptor)
-     */
     public void refreshRelationships(Object obj, ClassDescriptor cld)
     {
         getBroker().refreshRelationships(obj, cld);
@@ -363,6 +361,11 @@
     public IdentityFactory serviceIdentity()
     {
         return getBroker().serviceIdentity();
+    }
+
+    public LobHelper serviceLobHelper()
+    {
+        return getBroker().serviceLobHelper();
     }
 
 	public void fireBrokerEvent(PersistenceBrokerEvent event)

Modified: db/ojb/trunk/src/java/org/apache/ojb/broker/core/IdentityFactoryImpl.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/broker/core/IdentityFactoryImpl.java?rev=422231&r1=422230&r2=422231&view=diff
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/broker/core/IdentityFactoryImpl.java (original)
+++ db/ojb/trunk/src/java/org/apache/ojb/broker/core/IdentityFactoryImpl.java Sat Jul 15 07:20:25 2006
@@ -1,47 +1,163 @@
 package org.apache.ojb.broker.core;
 
+/* Copyright 2002-2005 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.Map;
+
+import org.apache.commons.collections.map.ReferenceIdentityMap;
+import org.apache.commons.lang.ArrayUtils;
+import org.apache.commons.lang.SystemUtils;
+import org.apache.commons.lang.exception.ExceptionUtils;
 import org.apache.ojb.broker.Identity;
 import org.apache.ojb.broker.IdentityFactory;
-import org.apache.ojb.broker.PersistenceBroker;
+import org.apache.ojb.broker.PBStateEvent;
+import org.apache.ojb.broker.PBStateListener;
 import org.apache.ojb.broker.PersistenceBrokerException;
+import org.apache.ojb.broker.PersistenceBrokerInternal;
+import org.apache.ojb.broker.core.proxy.IndirectionHandler;
 import org.apache.ojb.broker.metadata.ClassDescriptor;
+import org.apache.ojb.broker.metadata.ClassNotPersistenceCapableException;
 import org.apache.ojb.broker.metadata.FieldDescriptor;
+import org.apache.ojb.broker.util.BrokerHelper;
+import org.apache.ojb.broker.util.sequence.SequenceManager;
+import org.apache.ojb.broker.util.sequence.SequenceManagerTransientImpl;
 
 /**
- * @see org.apache.ojb.broker.IdentityFactory
- * 
- * @author <a href="mailto:armin@codeAuLait.de">Armin Waibel</a>
+ * Implementation class for {@link org.apache.ojb.broker.IdentityFactory}.
+ *
  * @version $Id$
+ * @see org.apache.ojb.broker.IdentityFactory
  */
-public class IdentityFactoryImpl implements IdentityFactory
+public class IdentityFactoryImpl implements IdentityFactory, PBStateListener
 {
-    private PersistenceBroker broker;
+    private PersistenceBrokerInternal broker;
+    //private final Map persistentIdentityMap;
+    private final Map transientIdentityMap;
+    private final SequenceManager transientSequenceManager;
 
-    public IdentityFactoryImpl(PersistenceBroker broker)
+    public IdentityFactoryImpl(PersistenceBrokerInternal broker)
     {
         this.broker = broker;
+        this.transientIdentityMap = new ReferenceIdentityMap(ReferenceIdentityMap.WEAK, ReferenceIdentityMap.HARD, false);
+        /*
+        TODO: Introduce cache for persistent object Identity objects, as long as user can use the direct
+        constructor call of Identity class we can run into problems when an object is stored/deleted/stored in
+        the same PB-tx, because then the PK of the object can change (e.g. when DB identity columns are used)
+        but the cached Identity object will always be the same when the Identity object is requested by the
+        IdentityFactory
+        */
+        //this.persistentIdentityMap = new ReferenceIdentityMap(ReferenceIdentityMap.WEAK, ReferenceIdentityMap.HARD, true);
+        this.transientSequenceManager = new SequenceManagerTransientImpl(broker);
+        broker.addListener(this, true);
     }
 
     /**
-     * @see org.apache.ojb.broker.IdentityFactory#buildIdentity(java.lang.Object)
+     * This methods creates a new transient (if at least one PK field is 'null') or persistent
+     * (if the PK fields are populated) {@link org.apache.ojb.broker.Identity} instance. If the specified object
+     * is transient and former call for the same object returns already a transient Identity, the same transient
+     * Identity object will be returned.
      */
-    public Identity buildIdentity(Object obj)
+    protected Identity createTransientOrRealIdentity(ClassDescriptor cld, final Object objOrProxy)
     {
-        return new Identity(obj, broker);
-    }
+        if(objOrProxy == null) throw new NullPointerException("Can't create Identity for 'null'-object");
+        Identity result = null;
+        Class topLevelClass = null;
+        Class realClass = null;
+        Object[] pks = null;
+        try
+        {
+            final IndirectionHandler handler = broker.getProxyFactory().getIndirectionHandler(objOrProxy);
+            if(handler != null)
+            {
+                result = handler.getIdentity();
+            }
+            else
+            {
+                //result = (Identity) persistentIdentityMap.get(objOrProxy);
+                if(result == null)
+                {
+                    // now we are sure that the specified object is not a proxy
+                    realClass = objOrProxy.getClass();
+                    topLevelClass = broker.getTopLevelClass(objOrProxy.getClass());
+                    if(cld == null)
+                    {
+                        cld = broker.getClassDescriptor(objOrProxy.getClass());
+                    }
+                    BrokerHelper helper = broker.serviceBrokerHelper();
 
-    /**
-     * @see org.apache.ojb.broker.IdentityFactory#buildIdentity(java.lang.Object)
+                    FieldDescriptor[] fields = cld.getPkFields();
+                    pks = new Object[fields.length];
+                    FieldDescriptor fld;
+                    for(int i = 0; i < fields.length; i++)
+                    {
+                        fld = fields[i];
+                        /*
+                        we check all PK fields for 'null'-values
      */
-    public Identity buildIdentity(ClassDescriptor cld, Object obj)
+                        Object value = fld.getPersistentField().get(objOrProxy);
+                        if(helper.representsNull(fld, value))
+                        {
+                            result = (Identity) transientIdentityMap.get(objOrProxy);
+                            if(result == null)
+                            {
+                                pks[i] = transientSequenceManager.getUniqueValue(fld);
+                                result = new Identity(realClass, topLevelClass, pks, true);
+                                //if(activeTx) objectToIdentityMap.put(objOrProxy, result);
+                                transientIdentityMap.put(objOrProxy, result);
+                            }
+                            break;
+                        }
+                        else
+                        {
+                            pks[i] = value;
+                        }
+                    }
+                    if(result == null)
+                    {
+                        result = new Identity(realClass, topLevelClass, pks, false);
+                        //persistentIdentityMap.put(objOrProxy, result);
+                    }
+                }
+            }
+        }
+        catch(ClassNotPersistenceCapableException e)
+        {
+            throw e;
+        }
+        catch(Exception e)
+        {
+            throw createException(e, "Can not init Identity for given object.", objOrProxy, topLevelClass, realClass, pks);
+        }
+        return result;
+    }
+
+    /** @see org.apache.ojb.broker.IdentityFactory#buildIdentity(Object) */
+    public Identity buildIdentity(final Object obj)
     {
-        return new Identity(obj, broker, cld);
+        return createTransientOrRealIdentity(broker.getClassDescriptor(broker.getProxyFactory().getRealClass(obj)), obj);
     }
 
-    /**
-     * @see org.apache.ojb.broker.IdentityFactory#buildIdentity(java.lang.Class, java.lang.Class, java.lang.String[], java.lang.Object[])
-     */
-    public Identity buildIdentity(Class realClass, Class topLevelClass, String[] pkFieldNames, Object[] pkValues)
+    /** @see org.apache.ojb.broker.IdentityFactory#buildIdentity(Object) */
+    public Identity buildIdentity(final ClassDescriptor cld, final Object obj)
+    {
+        return createTransientOrRealIdentity(cld, obj);
+    }
+
+    /** @see org.apache.ojb.broker.IdentityFactory#buildIdentity(Class, Class, String[], Object[]) */
+    public Identity buildIdentity(final Class realClass, final Class topLevelClass, final String[] pkFieldNames, final Object[] pkValues)
     {
         Object[] orderedPKValues = pkValues;
         if(pkValues == null)
@@ -61,29 +177,38 @@
             FieldDescriptor[] flds = broker.getClassDescriptor(realClass).getPkFields();
             if(!isOrdered(flds, pkFieldNames))
             {
-                orderedPKValues = reorderPKValues(flds, pkFieldNames, pkValues);
+                orderedPKValues = reorderFieldValues(flds, pkFieldNames, pkValues);
             }
         }
-        
-        return buildIdentity(realClass, topLevelClass, orderedPKValues);
+        return new Identity(realClass, topLevelClass, orderedPKValues);
     }
 
-    private Object[] reorderPKValues(FieldDescriptor[] flds, String[] pkFieldNames, Object[] pkValues)
+    /**
+     * This method orders the specified field values based on the
+     * specified {@link org.apache.ojb.broker.metadata.FieldDescriptor}.
+     *
+     * @param flds The {@link org.apache.ojb.broker.metadata.FieldDescriptor} array.
+     * @param fieldNames The field names.
+     * @param fieldValues The field values.
+     * @return The ordered field values.
+     */
+    private Object[] reorderFieldValues(final FieldDescriptor[] flds, final String[] fieldNames, final Object[] fieldValues)
     {
         String fieldName;
-        Object[] orderedPKValues = new Object[flds.length];
-        for (int i = 0; i < flds.length; i++)
+        Object[] orderedValues = new Object[flds.length];
+        for(int i = 0; i < flds.length; i++)
         {
             fieldName = flds[i].getPersistentField().getName();
-            int realPosition = findFieldName(pkFieldNames, fieldName);
-            orderedPKValues[i] = pkValues[realPosition];
+            int realPosition = findIndexForName(fieldNames, fieldName);
+            orderedValues[i] = fieldValues[realPosition];
         }
-        return orderedPKValues;
+        return orderedValues;
     }
 
-    private int findFieldName(String[] fieldNames, String searchName)
+    /** Find the index of the specified name in field name array. */
+    private int findIndexForName(String[] fieldNames, String searchName)
     {
-        for (int i = 0; i < fieldNames.length; i++)
+        for(int i = 0; i < fieldNames.length; i++)
         {
             if(searchName.equals(fieldNames[i]))
             {
@@ -94,9 +219,7 @@
                 "' in given array of field names");
     }
 
-    /**
-     * Checks length and compare order of field names with declared PK fields in metadata.
-     */
+    /** Checks length and compare order of field names with declared PK fields in metadata. */
     private boolean isOrdered(FieldDescriptor[] flds, String[] pkFieldNames)
     {
         if((flds.length > 1 && pkFieldNames == null) || flds.length != pkFieldNames.length)
@@ -106,7 +229,7 @@
                     (pkFieldNames != null ? pkFieldNames.length : 0));
         }
         boolean result = true;
-        for (int i = 0; i < flds.length; i++)
+        for(int i = 0; i < flds.length; i++)
         {
             FieldDescriptor fld = flds[i];
             result = result && fld.getPersistentField().getName().equals(pkFieldNames[i]);
@@ -114,27 +237,105 @@
         return result;
     }
 
-    /**
-     * @see org.apache.ojb.broker.IdentityFactory#buildIdentity(java.lang.Class, java.lang.String[], java.lang.Object[])
-     */
-    public Identity buildIdentity(Class realClass, String[] pkFieldNames, Object[] pkValues)
+    /** @see org.apache.ojb.broker.IdentityFactory#buildIdentity(Class, String[], Object[]) */
+    public Identity buildIdentity(final Class realClass, final String[] pkFieldNames, final Object[] pkValues)
     {
         return buildIdentity(realClass, broker.getTopLevelClass(realClass), pkFieldNames, pkValues);
     }
 
-    /**
-     * @see org.apache.ojb.broker.IdentityFactory#buildIdentity(java.lang.Class, java.lang.String[], java.lang.Object[])
-     */
-    public Identity buildIdentity(Class realClass, Class topLevelClass, Object[] pkValues)
+    /** @see org.apache.ojb.broker.IdentityFactory#buildIdentity(Class, String[], Object[]) */
+    public Identity buildIdentity(final Class realClass, final Class topLevelClass, final Object[] pkValues)
     {
         return new Identity(realClass, topLevelClass, pkValues);
     }
-    
+
+    /** @see org.apache.ojb.broker.IdentityFactory#buildIdentity(Class, Object) */
+    public Identity buildIdentity(final Class realClass, final Object pkValue)
+    {
+        return buildIdentity(realClass, (String[]) null, new Object[]{pkValue});
+    }
+
     /**
-     * @see org.apache.ojb.broker.IdentityFactory#buildIdentity(java.lang.Class, java.lang.Object)
+     * Helper method which supports creation of proper error messages.
+     *
+     * @param ex An exception to include or <em>null</em>.
+     * @param message The error message or <em>null</em>.
+     * @param objectToIdentify The current used object or <em>null</em>.
+     * @param topLevelClass The object top-level class or <em>null</em>.
+     * @param realClass The object real class or <em>null</em>.
+     * @param pks The associated PK values of the object or <em>null</em>.
+     * @return The generated exception.
      */
-    public Identity buildIdentity(Class realClass, Object pkValue)
+    private PersistenceBrokerException createException(final Exception ex, String message, final Object objectToIdentify, Class topLevelClass, Class realClass, Object[] pks)
+    {
+        final String eol = SystemUtils.LINE_SEPARATOR;
+        StringBuffer msg = new StringBuffer();
+        if(message == null)
+        {
+            msg.append("Unexpected error: ");
+        }
+        else
+        {
+            msg.append(message).append(" :");
+        }
+        if(topLevelClass != null) msg.append(eol).append("objectTopLevelClass=").append(topLevelClass.getName());
+        if(realClass != null) msg.append(eol).append("objectRealClass=").append(realClass.getName());
+        if(pks != null) msg.append(eol).append("pkValues=").append(ArrayUtils.toString(pks));
+        if(objectToIdentify != null) msg.append(eol).append("object to identify: ").append(objectToIdentify);
+        if(ex != null)
+        {
+            // add causing stack trace
+            Throwable rootCause = ExceptionUtils.getRootCause(ex);
+            if(rootCause != null)
+            {
+                msg.append(eol).append("The root stack trace is --> ");
+                String rootStack = ExceptionUtils.getStackTrace(rootCause);
+                msg.append(eol).append(rootStack);
+            }
+
+            return new PersistenceBrokerException(msg.toString(), ex);
+        }
+        else
+        {
+            return new PersistenceBrokerException(msg.toString());
+        }
+    }
+
+    //===================================================================
+    // PBStateListener interface
+    //===================================================================
+    public void afterBegin(PBStateEvent event)
+    {
+    }
+
+    public void afterCommit(PBStateEvent event)
+    {
+        if(transientIdentityMap.size() > 0) transientIdentityMap.clear();
+    }
+
+    public void afterRollback(PBStateEvent event)
+    {
+        if(transientIdentityMap.size() > 0) transientIdentityMap.clear();
+    }
+
+    public void beforeClose(PBStateEvent event)
+    {
+        if(transientIdentityMap.size() > 0) transientIdentityMap.clear();
+    }
+
+    public void beforeRollback(PBStateEvent event)
+    {
+    }
+
+    public void afterOpen(PBStateEvent event)
+    {
+    }
+
+    public void beforeBegin(PBStateEvent event)
+    {
+    }
+
+    public void beforeCommit(PBStateEvent event)
     {
-        return buildIdentity(realClass, (String[]) null, new Object[]{pkValue});
     }
 }

Modified: db/ojb/trunk/src/java/org/apache/ojb/broker/core/PersistenceBrokerAbstractImpl.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/broker/core/PersistenceBrokerAbstractImpl.java?rev=422231&r1=422230&r2=422231&view=diff
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/broker/core/PersistenceBrokerAbstractImpl.java (original)
+++ db/ojb/trunk/src/java/org/apache/ojb/broker/core/PersistenceBrokerAbstractImpl.java Sat Jul 15 07:20:25 2006
@@ -1,6 +1,6 @@
 package org.apache.ojb.broker.core;
 
-/* Copyright 2003-2004 The Apache Software Foundation
+/* Copyright 2003-2006 The Apache Software Foundation
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -15,6 +15,9 @@
  * limitations under the License.
  */
 
+import java.util.Collections;
+import java.util.List;
+
 import org.apache.ojb.broker.PBLifeCycleEvent;
 import org.apache.ojb.broker.PBLifeCycleListener;
 import org.apache.ojb.broker.PBListener;
@@ -23,6 +26,7 @@
 import org.apache.ojb.broker.PersistenceBrokerEvent;
 import org.apache.ojb.broker.PersistenceBrokerException;
 import org.apache.ojb.broker.PersistenceBrokerInternal;
+import org.apache.ojb.broker.util.IdentityArrayList;
 import org.apache.ojb.broker.util.logging.LoggerFactory;
 
 /**
@@ -33,41 +37,42 @@
  * @see org.apache.ojb.broker.PBLifeCycleListener
  * @see org.apache.ojb.broker.PersistenceBrokerAware
  * @see org.apache.ojb.broker.PBStateListener
- *
- * @author Created by Charles on 12-Sep-2002 08:04:47
- * @author Armin Waibel
  * @version $Id$
  */
 public abstract class PersistenceBrokerAbstractImpl implements PersistenceBrokerInternal
 {
-	private static final PBStateListener[] NO_STATE_LISTENERS = new PBStateListener[0];
-	private static final PBLifeCycleListener[] NO_LIFECYCLE_LISTENERS = new PBLifeCycleListener[0];
-
+    /** Returns <em>true</em> if PB-transaction check is enabled. */
     private boolean txCheck;
 
+    /*
+    PB instances are single threaded used, but we use synchronization here to
+    avoid problems with the JVM Finalizer thread - more details see issue
+    OJB-114 in JIRA
+    */
+
+    /**
+     * List containing all permanent {@link org.apache.ojb.broker.PBStateListener}
+     * instances.
+     */
+    private final List permanentStateListeners = Collections.synchronizedList(new IdentityArrayList());
+
+    /**
+     * List containing all temporary {@link org.apache.ojb.broker.PBStateListener}
+     * instances.
+     */
+    private final List temporaryStateListeners = Collections.synchronizedList(new IdentityArrayList());
+
     /**
-     * Array containing all permanent {@link org.apache.ojb.broker.PBStateListener}
+     * List containing all permanent {@link org.apache.ojb.broker.PBLifeCycleListener}
      * instances.
      */
-    private PBStateListener[] permanentStateListeners = NO_STATE_LISTENERS;
+    private List permanentLifeCycleListeners = Collections.synchronizedList(new IdentityArrayList(100));
 
-	/**
-	 * Array containing all temporary {@link org.apache.ojb.broker.PBStateListener}
-	 * instances.
-	 */
-	private PBStateListener[] temporaryStateListeners = NO_STATE_LISTENERS;
-
-	/**
-	 * Array containing all permanent {@link org.apache.ojb.broker.PBLifeCycleListener}
-	 * instances.
-	 */
-	private PBLifeCycleListener[] permanentLifeCycleListeners = NO_LIFECYCLE_LISTENERS;
-
-	/**
-	 * Array containing all temporary {@link org.apache.ojb.broker.PBLifeCycleListener}
-	 * instances.
-	 */
-	private PBLifeCycleListener[] temporaryLifeCycleListeners = NO_LIFECYCLE_LISTENERS;
+    /**
+     * List containing all temporary {@link org.apache.ojb.broker.PBLifeCycleListener}
+     * instances.
+     */
+    private List temporaryLifeCycleListeners = Collections.synchronizedList(new IdentityArrayList(100));
 
     /**
      * Returns <em>true</em> if the development checks are enabled.
@@ -97,169 +102,99 @@
         this.txCheck = txCheck;
     }
 
-    /**
-     * @see org.apache.ojb.broker.PersistenceBroker#addListener(PBListener listener)
-     */
+    /** @see org.apache.ojb.broker.PersistenceBroker#addListener(PBListener listener) */
     public void addListener(PBListener listener) throws PersistenceBrokerException
     {
         addListener(listener, false);
     }
 
-    /**
-     * @see org.apache.ojb.broker.PersistenceBroker#addListener(PBListener listener, boolean permanent)
-     */
+    /** @see org.apache.ojb.broker.PersistenceBroker#addListener(PBListener listener, boolean permanent) */
     public void addListener(PBListener listener, boolean permanent) throws PersistenceBrokerException
     {
-        if (listener instanceof PBStateListener)
+        if(listener instanceof PBStateListener)
+        {
+            if(permanent)
+            {
+                if(!permanentStateListeners.contains(listener))
+                {
+                    permanentStateListeners.add(listener);
+                }
+            }
+            else
+            {
+                if(!temporaryStateListeners.contains(listener))
+                {
+                    temporaryStateListeners.add(listener);
+                }
+            }
+        }
+
+        if(listener instanceof PBLifeCycleListener)
         {
-        	if (permanent)
-        	{
-        		if (!contains(permanentStateListeners, listener))
-        		{
-					PBStateListener[] newListeners = new PBStateListener[permanentStateListeners.length + 1];
-					System.arraycopy(permanentStateListeners, 0, newListeners, 0, permanentStateListeners.length);
-					newListeners[newListeners.length - 1] = (PBStateListener) listener;
-					permanentStateListeners = newListeners;
-        		}
-        	}
-        	else
-        	{
-				if (!contains(temporaryStateListeners, listener))
-				{
-					PBStateListener[] newListeners = new PBStateListener[temporaryStateListeners.length + 1];
-					System.arraycopy(temporaryStateListeners, 0, newListeners, 0, temporaryStateListeners.length);
-					newListeners[newListeners.length - 1] = (PBStateListener) listener;
-					temporaryStateListeners = newListeners;
-				}
-        	}
-        }
-
-        if (listener instanceof PBLifeCycleListener)
-        {
-			if (permanent)
-			{
-				if (!contains(permanentLifeCycleListeners, listener))
-				{
-					PBLifeCycleListener[] newListeners = new PBLifeCycleListener[permanentLifeCycleListeners.length + 1];
-					System.arraycopy(permanentLifeCycleListeners, 0, newListeners, 0, permanentLifeCycleListeners.length);
-					newListeners[newListeners.length - 1] = (PBLifeCycleListener) listener;
-					permanentLifeCycleListeners = newListeners;
-				}
-			}
-			else
-			{
-				if (!contains(temporaryLifeCycleListeners, listener))
-				{
-					PBLifeCycleListener[] newListeners = new PBLifeCycleListener[temporaryLifeCycleListeners.length + 1];
-					System.arraycopy(temporaryLifeCycleListeners, 0, newListeners, 0, temporaryLifeCycleListeners.length);
-					newListeners[newListeners.length - 1] = (PBLifeCycleListener) listener;
-					temporaryLifeCycleListeners = newListeners;
-				}
-			}
+            if(permanent)
+            {
+                if(!permanentLifeCycleListeners.contains(listener))
+                {
+                    permanentLifeCycleListeners.add(listener);
+                }
+            }
+            else
+            {
+                if(!temporaryLifeCycleListeners.contains(listener))
+                {
+                    temporaryLifeCycleListeners.add(listener);
+                }
+            }
         }
     }
 
-    /**
-     * @see org.apache.ojb.broker.PersistenceBroker#removeListener(PBListener listener)
-     */
+    /** @see org.apache.ojb.broker.PersistenceBroker#removeListener(PBListener listener) */
     public void removeListener(PBListener listener) throws PersistenceBrokerException
     {
-        if (listener instanceof PBStateListener)
+        if(listener instanceof PBStateListener)
         {
-        	if (contains(permanentStateListeners, listener))
-        	{
-				PBStateListener[] newListeners = new PBStateListener[permanentStateListeners.length - 1];
-        		int pos = 0;
-
-        		for (int i = 0; i < permanentStateListeners.length; i++)
-        		{
-        			if (permanentStateListeners[i] != listener)
-        			{
-        				newListeners[pos++] = permanentStateListeners[i];
-        			}
-        		}
-				permanentStateListeners = newListeners;
-        	}
-
-			if (contains(temporaryStateListeners, listener))
-			{
-				PBStateListener[] newListeners = new PBStateListener[temporaryStateListeners.length - 1];
-				int pos = 0;
-
-				for (int i = 0; i < temporaryStateListeners.length; i++)
-				{
-					if (temporaryStateListeners[i] != listener)
-					{
-						newListeners[pos++] = temporaryStateListeners[i];
-					}
-				}
-				temporaryStateListeners = newListeners;
-			}
-        }
-
-        if (listener instanceof PBLifeCycleListener)
-        {
-			if (contains(permanentLifeCycleListeners, listener))
-			{
-				PBLifeCycleListener[] newListeners = new PBLifeCycleListener[permanentLifeCycleListeners.length - 1];
-				int pos = 0;
-
-				for (int i = 0; i < permanentLifeCycleListeners.length; i++)
-				{
-					if (permanentLifeCycleListeners[i] != listener)
-					{
-						newListeners[pos++] = permanentLifeCycleListeners[i];
-					}
-				}
-				permanentLifeCycleListeners = newListeners;
-			}
-
-			if (contains(temporaryLifeCycleListeners, listener))
-			{
-				PBLifeCycleListener[] newListeners = new PBLifeCycleListener[temporaryLifeCycleListeners.length - 1];
-				int pos = 0;
-
-				for (int i = 0; i < temporaryLifeCycleListeners.length; i++)
-				{
-					if (temporaryLifeCycleListeners[i] != listener)
-					{
-						newListeners[pos++] = temporaryLifeCycleListeners[i];
-					}
-				}
-				temporaryLifeCycleListeners = newListeners;
-			}
-		}
-    }
-
-	protected boolean contains(PBListener[] listeners, PBListener listener)
-	{
-		for (int i = listeners.length - 1; i >= 0; i--)
-		{
-            if (listeners[i] == listener) return true;
-		}
+            permanentStateListeners.remove(listener);
+            temporaryStateListeners.remove(listener);
+        }
 
-		return false;
-	}
+        if(listener instanceof PBLifeCycleListener)
+        {
+            permanentLifeCycleListeners.remove(listener);
+            temporaryLifeCycleListeners.remove(listener);
+        }
+    }
 
-    /**
-     * @see org.apache.ojb.broker.PersistenceBroker#removeAllListeners(boolean)
-     */
+    /** @see org.apache.ojb.broker.PersistenceBroker#removeAllListeners(boolean) */
     public void removeAllListeners(boolean permanent) throws PersistenceBrokerException
     {
-        if (permanent)
+        if(permanent)
         {
             // remove permanent listeners as well
-            permanentStateListeners = NO_STATE_LISTENERS;
-            permanentLifeCycleListeners = NO_LIFECYCLE_LISTENERS;
+            permanentStateListeners.clear();
+            // this could be huge, thus simply replace instance
+            if(permanentLifeCycleListeners.size() > 10000)
+            {
+                permanentLifeCycleListeners = Collections.synchronizedList(new IdentityArrayList(100));
+            }
+            else
+            {
+                permanentLifeCycleListeners.clear();
+            }
         }
 
-		temporaryStateListeners = NO_STATE_LISTENERS;
-		temporaryLifeCycleListeners = NO_LIFECYCLE_LISTENERS;
+        temporaryStateListeners.clear();
+        // this could be huge, thus simply replace instance
+        if(temporaryLifeCycleListeners.size() > 10000)
+        {
+            temporaryLifeCycleListeners = Collections.synchronizedList(new IdentityArrayList(100));
+        }
+        else
+        {
+            temporaryLifeCycleListeners.clear();
+        }
     }
 
-    /**
-     * @see org.apache.ojb.broker.PersistenceBroker#removeAllListeners()
-     */
+    /** @see org.apache.ojb.broker.PersistenceBroker#removeAllListeners() */
     public void removeAllListeners() throws PersistenceBrokerException
     {
         removeAllListeners(false);
@@ -267,68 +202,71 @@
 
     public void fireBrokerEvent(PersistenceBrokerEvent event)
     {
-    	if (event instanceof PBLifeCycleEvent)
-    	{
-    		fireBrokerEvent((PBLifeCycleEvent) event);
-    	}
-    	else if (event instanceof PBStateEvent)
-		{
-			fireBrokerEvent((PBStateEvent) event);
-		}
-		else
-		{
-			LoggerFactory.getDefaultLogger().error(
-					PersistenceBrokerAbstractImpl.class.getName() + ": Unkown PersistenceBrokerEvent was fired " + event);
-		}
+        if(event instanceof PBLifeCycleEvent)
+        {
+            fireBrokerEvent((PBLifeCycleEvent) event);
+        }
+        else if(event instanceof PBStateEvent)
+        {
+            fireBrokerEvent((PBStateEvent) event);
+        }
+        else
+        {
+            LoggerFactory.getDefaultLogger().error(
+                    PersistenceBrokerAbstractImpl.class.getName() + ": Unkown PersistenceBrokerEvent was fired " + event);
+        }
     }
 
-	public void fireBrokerEvent(PBLifeCycleEvent event)
+    public void fireBrokerEvent(PBLifeCycleEvent event)
     {
-        if (event.getPersitenceBrokerAware() != null)
+        if(event.getPersitenceBrokerAware() != null)
         {
             // first we do the persistent object callback
             performCallBack(event);
         }
 
-        // copy array references so they can't change in the middle of iteration
-        PBLifeCycleListener[] permanent = permanentLifeCycleListeners;
-		PBLifeCycleListener[] temporary = temporaryLifeCycleListeners;
-
         // now we notify the listeners
-        for (int i = permanent.length - 1; i >= 0; i--)
+        synchronized(permanentLifeCycleListeners)
         {
-			notifiyObjectLifeCycleListener(permanent[i], event);
+            for(int i = permanentLifeCycleListeners.size() - 1; i >= 0; i--)
+            {
+                notifiyObjectLifeCycleListener((PBLifeCycleListener) permanentLifeCycleListeners.get(i), event);
+            }
         }
 
-        for (int i = temporary.length - 1; i >= 0; i--)
+        synchronized(temporaryLifeCycleListeners)
         {
-			notifiyObjectLifeCycleListener(temporary[i], event);
+            for(int i = temporaryLifeCycleListeners.size() - 1; i >= 0; i--)
+            {
+                notifiyObjectLifeCycleListener((PBLifeCycleListener) temporaryLifeCycleListeners.get(i), event);
+            }
         }
     }
 
-	public void fireBrokerEvent(PBStateEvent event)
+    public void fireBrokerEvent(PBStateEvent event)
     {
-		// copy array references so they can't change in the middle of iteration
-		PBStateListener[] permanent = permanentStateListeners;
-		PBStateListener[] temporary = temporaryStateListeners;
-
-		// now we notify the listeners
-		for (int i = permanent.length - 1; i >= 0; i--)
-		{
-			notifiyStateListener(permanent[i], event);
-		}
+        synchronized(permanentStateListeners)
+        {
+            for(int i = permanentStateListeners.size() - 1; i >= 0; i--)
+            {
+                notifiyStateListener((PBStateListener) permanentStateListeners.get(i), event);
+            }
+        }
 
-		for (int i = temporary.length - 1; i >= 0; i--)
-		{
-			notifiyStateListener(temporary[i], event);
-		}
+        synchronized(temporaryStateListeners)
+        {
+            for(int i = temporaryStateListeners.size() - 1; i >= 0; i--)
+            {
+                notifiyStateListener((PBStateListener) temporaryStateListeners.get(i), event);
+            }
+        }
     }
 
     private void performCallBack(PBLifeCycleEvent event)
     {
         // Check for null
-        if (event.getPersitenceBrokerAware() == null) return;
-        switch (event.getEventType().typeId())
+        if(event.getPersitenceBrokerAware() == null) return;
+        switch(event.getEventType().typeId())
         {
             case PBLifeCycleEvent.TYPE_AFTER_LOOKUP:
                 event.getPersitenceBrokerAware().afterLookup(event.getTriggeringBroker());
@@ -356,7 +294,7 @@
 
     private void notifiyStateListener(PBStateListener listener, PBStateEvent stateEvent)
     {
-        switch (stateEvent.getEventType().typeId())
+        switch(stateEvent.getEventType().typeId())
         {
             case PBStateEvent.KEY_BEFORE_COMMIT:
                 listener.beforeCommit(stateEvent);
@@ -387,7 +325,7 @@
 
     private void notifiyObjectLifeCycleListener(PBLifeCycleListener listener, PBLifeCycleEvent lifeEvent)
     {
-        switch (lifeEvent.getEventType().typeId())
+        switch(lifeEvent.getEventType().typeId())
         {
             case PBLifeCycleEvent.TYPE_AFTER_LOOKUP:
                 listener.afterLookup(lifeEvent);

Modified: db/ojb/trunk/src/java/org/apache/ojb/broker/core/PersistenceBrokerFactoryDefaultImpl.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/broker/core/PersistenceBrokerFactoryDefaultImpl.java?rev=422231&r1=422230&r2=422231&view=diff
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/broker/core/PersistenceBrokerFactoryDefaultImpl.java (original)
+++ db/ojb/trunk/src/java/org/apache/ojb/broker/core/PersistenceBrokerFactoryDefaultImpl.java Sat Jul 15 07:20:25 2006
@@ -1,6 +1,6 @@
 package org.apache.ojb.broker.core;
 
-/* Copyright 2003-2004 The Apache Software Foundation
+/* Copyright 2003-2005 The Apache Software Foundation
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.

Modified: db/ojb/trunk/src/java/org/apache/ojb/broker/core/PersistenceBrokerHandle.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/broker/core/PersistenceBrokerHandle.java?rev=422231&r1=422230&r2=422231&view=diff
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/broker/core/PersistenceBrokerHandle.java (original)
+++ db/ojb/trunk/src/java/org/apache/ojb/broker/core/PersistenceBrokerHandle.java Sat Jul 15 07:20:25 2006
@@ -1,8 +1,5 @@
 package org.apache.ojb.broker.core;
 
-import org.apache.ojb.broker.PersistenceBrokerException;
-import org.apache.ojb.broker.PersistenceBrokerInternal;
-
 /* Copyright 2003-2004 The Apache Software Foundation
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -17,8 +14,22 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
+import org.apache.ojb.broker.PersistenceBrokerException;
+import org.apache.ojb.broker.PersistenceBrokerInternal;
+
+/**
+ * A handle wraps a real (pooled) PB instance.
+ * In addition this class does set itself as current
+ * broker instance in {@link PersistenceBrokerThreadMapping#setCurrentPersistenceBroker}
+ * when instantiate and unset on broker close call.
+ *
+ * @version $Id$
+ */
 public class PersistenceBrokerHandle extends DelegatingPersistenceBroker
 {
+    private Boolean closed;
+
     /**
      * Constructor for the handle, set itself in
      * {@link PersistenceBrokerThreadMapping#setCurrentPersistenceBroker}
@@ -31,7 +42,11 @@
 
     public boolean isClosed()
     {
-        return super.isClosed();
+        if(closed == null)
+        {
+            closed = super.isClosed() ? Boolean.TRUE : Boolean.FALSE;
+        }
+        return closed.booleanValue();
     }
 
     public boolean isInTransaction() throws PersistenceBrokerException
@@ -50,6 +65,7 @@
         try
         {
             PersistenceBrokerThreadMapping.unsetCurrentPersistenceBroker(getPBKey(), this);
+            closed = Boolean.TRUE;
             super.close();
         }
         finally



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