db-ojb-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From olegn...@apache.org
Subject cvs commit: jakarta-ojb/src/java/org/apache/ojb/odmg OdmgConfiguration.java TransactionImpl.java
Date Mon, 02 Dec 2002 17:09:17 GMT
olegnitz    2002/12/02 09:09:17

  Modified:    src/java/org/apache/ojb/broker/accesslayer
                        ConnectionManager.java ConnectionManagerIF.java
               src/java/org/apache/ojb/broker/util/configuration/impl
                        OjbConfiguration.java
               src/java/org/apache/ojb/odmg OdmgConfiguration.java
                        TransactionImpl.java
  Log:
  ConnectionManager now has the batch mode - all PreparedStatements with
  the same SQL string are authomatically gathered into batches (off by default)
  OJB ODMG turns the batch mode on during commit
  (by default, can be turned off via OJB.properties BatchMode parameter)
  
  Revision  Changes    Path
  1.15      +52 -2     jakarta-ojb/src/java/org/apache/ojb/broker/accesslayer/ConnectionManager.java
  
  Index: ConnectionManager.java
  ===================================================================
  RCS file: /home/cvs/jakarta-ojb/src/java/org/apache/ojb/broker/accesslayer/ConnectionManager.java,v
  retrieving revision 1.14
  retrieving revision 1.15
  diff -u -r1.14 -r1.15
  --- ConnectionManager.java	28 Nov 2002 22:25:53 -0000	1.14
  +++ ConnectionManager.java	2 Dec 2002 17:09:16 -0000	1.15
  @@ -64,6 +64,7 @@
   import org.apache.ojb.broker.platforms.Platform;
   import org.apache.ojb.broker.platforms.PlatformConfiguration;
   import org.apache.ojb.broker.platforms.PlatformFactory;
  +import org.apache.ojb.broker.util.batch.BatchConnection;
   import org.apache.ojb.broker.util.configuration.Configurable;
   import org.apache.ojb.broker.util.configuration.Configuration;
   import org.apache.ojb.broker.util.configuration.ConfigurationException;
  @@ -92,6 +93,8 @@
       private int useAutoCommit;
       private boolean originalAutoCommitState;
       private boolean isInLocalTransaction;
  +    private boolean batchMode;
  +    private BatchConnection batchCon = null;
   
       public ConnectionManager(PersistenceBroker broker)
       {
  @@ -128,7 +131,19 @@
               }
               if (log.isDebugEnabled()) log.debug("Request new connection from ConnectionFactory: " + con);
           }
  -        return con;
  +
  +        if (batchMode)
  +        {
  +            if (batchCon == null)
  +            {
  +                batchCon = new BatchConnection(con);
  +            }
  +            return batchCon;
  +        }
  +        else
  +        {
  +            return con;
  +        }
       }
   
       /**
  @@ -257,6 +272,41 @@
           }
           this.connectionFactory.releaseConnection(this.jcd, this.con);
           this.con = null;
  +    }
  +
  +    /**
  +     * Sets the batch mode on or off.
  +     * @param mode the batch mode
  +     */
  +    public void setBatchMode(boolean mode) 
  +    {
  +        batchMode = (mode && platform.supportsBatchOperations());
  +    }
  +
  +    /**
  +     * @return the batch mode.
  +     */
  +    public boolean isBatchMode()
  +    {
  +        return batchMode;
  +    }
  +
  +    /**
  +     * Execute batch (if the batch mode where used).
  +     */
  +    public void executeBatch() throws OJBBatchUpdateException
  +    {
  +        if (batchCon != null)
  +        {
  +            try
  +            {
  +                batchCon.executeBatch();
  +            }
  +            catch (Throwable th)
  +            {
  +                throw new OJBBatchUpdateException(th);
  +            }
  +        }
       }
   
   }
  
  
  
  1.6       +16 -0     jakarta-ojb/src/java/org/apache/ojb/broker/accesslayer/ConnectionManagerIF.java
  
  Index: ConnectionManagerIF.java
  ===================================================================
  RCS file: /home/cvs/jakarta-ojb/src/java/org/apache/ojb/broker/accesslayer/ConnectionManagerIF.java,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- ConnectionManagerIF.java	28 Nov 2002 22:25:53 -0000	1.5
  +++ ConnectionManagerIF.java	2 Dec 2002 17:09:16 -0000	1.6
  @@ -94,4 +94,20 @@
        * Release the hold connection.
        */
       public void releaseConnection();
  +    
  +    /**
  +     * Sets the batch mode on or off.
  +     * @param the batch mode.
  +     */
  +    public void setBatchMode(boolean mode);
  +
  +    /**
  +     * @return the batch mode.
  +     */
  +    public boolean isBatchMode();
  +    
  +    /**
  +     * Execute batch (if the batch mode where used).
  +     */
  +    public void executeBatch();
   }
  
  
  
  1.15      +13 -2     jakarta-ojb/src/java/org/apache/ojb/broker/util/configuration/impl/OjbConfiguration.java
  
  Index: OjbConfiguration.java
  ===================================================================
  RCS file: /home/cvs/jakarta-ojb/src/java/org/apache/ojb/broker/util/configuration/impl/OjbConfiguration.java,v
  retrieving revision 1.14
  retrieving revision 1.15
  diff -u -r1.14 -r1.15
  --- OjbConfiguration.java	28 Nov 2002 21:22:13 -0000	1.14
  +++ OjbConfiguration.java	2 Dec 2002 17:09:17 -0000	1.15
  @@ -134,6 +134,7 @@
   
       // ODMG configuration
       private boolean useImplicitLocking;
  +    private boolean useBatchMode;
       private boolean lockAssociationAsWrites;
       private Class oqlCollectionClass;
       private Class lockManagerClass;
  @@ -360,6 +361,9 @@
           // load configuration for ImplicitLocking parameter:
           useImplicitLocking = getBoolean("ImplicitLocking", false);
   
  +        // load configuration for BatchMode parameter:
  +        useBatchMode = getBoolean("BatchMode", true);
  +
           // load configuration for LockAssociations parameter:
           lockAssociationAsWrites =
                   (getString("LockAssociations", "WRITE").equalsIgnoreCase("WRITE") ? true : false);
  @@ -419,4 +423,11 @@
           return useImplicitLocking;
       }
   
  -}
  \ No newline at end of file
  +    /**
  +     * @see org.apache.ojb.odmg.OdmgConfiguration#useBatchMode()
  +     */
  +    public boolean useBatchMode()
  +    {
  +        return useBatchMode;
  +    }
  +}
  
  
  
  1.5       +7 -2      jakarta-ojb/src/java/org/apache/ojb/odmg/OdmgConfiguration.java
  
  Index: OdmgConfiguration.java
  ===================================================================
  RCS file: /home/cvs/jakarta-ojb/src/java/org/apache/ojb/odmg/OdmgConfiguration.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- OdmgConfiguration.java	22 Sep 2002 13:00:47 -0000	1.4
  +++ OdmgConfiguration.java	2 Dec 2002 17:09:17 -0000	1.5
  @@ -78,7 +78,7 @@
       public Class getOqlCollectionClass();
       
       /**
  -     * defines if implicit lock acquisition is to be used. 
  +     * defines if implicit lock acquisition is to be used.
        * If set to true OJB implicitely locks objects to ODMG
        * transactions after performing OQL queries.
        * If implicit locking is used locking objects is recursive, that is
  @@ -87,5 +87,10 @@
        * queries and there is also no recursive locking.
        */
       public boolean useImplicitLocking();
  +
  +    /**
  +     * defines if batch updates should be used.
  +     */
  +    public boolean useBatchMode();
   
   }
  
  
  
  1.28      +1161 -1132jakarta-ojb/src/java/org/apache/ojb/odmg/TransactionImpl.java
  
  Index: TransactionImpl.java
  ===================================================================
  RCS file: /home/cvs/jakarta-ojb/src/java/org/apache/ojb/odmg/TransactionImpl.java,v
  retrieving revision 1.27
  retrieving revision 1.28
  diff -u -r1.27 -r1.28
  --- TransactionImpl.java	30 Nov 2002 17:36:28 -0000	1.27
  +++ TransactionImpl.java	2 Dec 2002 17:09:17 -0000	1.28
  @@ -1,167 +1,169 @@
  -package org.apache.ojb.odmg;
  -
  -/* ====================================================================
  - * The Apache Software License, Version 1.1
  - *
  - * Copyright (c) 2001 The Apache Software Foundation.  All rights
  - * reserved.
  - *
  - * Redistribution and use in source and binary forms, with or without
  - * modification, are permitted provided that the following conditions
  - * are met:
  - *
  - * 1. Redistributions of source code must retain the above copyright
  - *    notice, this list of conditions and the following disclaimer.
  - *
  - * 2. Redistributions in binary form must reproduce the above copyright
  - *    notice, this list of conditions and the following disclaimer in
  - *    the documentation and/or other materials provided with the
  - *    distribution.
  - *
  - * 3. The end-user documentation included with the redistribution,
  - *    if any, must include the following acknowledgment:
  - *       "This product includes software developed by the
  - *        Apache Software Foundation (http://www.apache.org/)."
  - *    Alternately, this acknowledgment may appear in the software itself,
  - *    if and wherever such third-party acknowledgments normally appear.
  - *
  - * 4. The names "Apache" and "Apache Software Foundation" and
  - *    "Apache ObjectRelationalBridge" must not be used to endorse or promote products
  - *    derived from this software without prior written permission. For
  - *    written permission, please contact apache@apache.org.
  - *
  - * 5. Products derived from this software may not be called "Apache",
  - *    "Apache ObjectRelationalBridge", nor may "Apache" appear in their name, without
  - *    prior written permission of the Apache Software Foundation.
  - *
  - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
  - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  - * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
  - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
  - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  - * SUCH DAMAGE.
  - * ====================================================================
  - *
  - * This software consists of voluntary contributions made by many
  - * individuals on behalf of the Apache Software Foundation.  For more
  - * information on the Apache Software Foundation, please see
  - * <http://www.apache.org/>.
  - */
  -
  -
  -import org.apache.ojb.broker.Identity;
  -import org.apache.ojb.broker.ManageableCollection;
  -import org.apache.ojb.broker.PBFactoryException;
  -import org.apache.ojb.broker.PersistenceBroker;
  -import org.apache.ojb.broker.PersistenceBrokerException;
  -import org.apache.ojb.broker.PersistenceBrokerFactory;
  -import org.apache.ojb.broker.VirtualProxy;
  -import org.apache.ojb.broker.accesslayer.IndirectionHandler;
  -import org.apache.ojb.broker.accesslayer.MaterializationListener;
  -import org.apache.ojb.broker.metadata.ClassDescriptor;
  -import org.apache.ojb.broker.metadata.CollectionDescriptor;
  -import org.apache.ojb.broker.metadata.FieldDescriptor;
  -import org.apache.ojb.broker.metadata.ObjectReferenceDescriptor;
  -import org.apache.ojb.broker.util.ArrayIterator;
  -import org.apache.ojb.broker.util.GUID;
  -import org.apache.ojb.broker.util.configuration.Configurable;
  -import org.apache.ojb.broker.util.configuration.Configuration;
  -import org.apache.ojb.broker.util.configuration.ConfigurationException;
  -import org.apache.ojb.broker.util.logging.Logger;
  -import org.apache.ojb.broker.util.logging.LoggerFactory;
  -import org.apache.ojb.odmg.locking.LockManager;
  -import org.apache.ojb.odmg.locking.LockManagerFactory;
  -import org.odmg.DatabaseClosedException;
  -import org.odmg.LockNotGrantedException;
  -import org.odmg.Transaction;
  -import org.odmg.TransactionAbortedException;
  -import org.odmg.TransactionNotInProgressException;
  -
  -import javax.transaction.Status;
  -import java.util.ArrayList;
  -import java.util.Collection;
  -import java.util.Enumeration;
  -import java.util.HashMap;
  -import java.util.Hashtable;
  -import java.util.Iterator;
  -import java.util.Vector;
  -
  -//#ifdef JDK13
  -import java.lang.reflect.Proxy;
  -//#else
  -/*
  -import com.develop.java.lang.reflect.Proxy;
  -*/
  -//#endif
  -
  -/**
  - *
  - * Implementation of Transaction for org.odmg.Transaction.
  - *
  - * @author     Thomas Mahler & David Dixon-Peugh
  - * @author <a href="mailto:mattbaird@yahoo.com">Matthew Baird</a>
  - * @author <a href="mailto:armin@codeAuLait.de">Armin Waibel</a>
  - * @version $Id$
  - *
  - */
  -public class TransactionImpl
  -        implements Transaction, MaterializationListener, Configurable, HasBroker
  -{
  -    private Logger log = LoggerFactory.getLogger(TransactionImpl.class);
  -    private Hashtable myNrm = null;
  -    private boolean useWriteLocks;
  -    private boolean useImplicitLocking;
  -    private String txGUID;
  -    protected PersistenceBroker broker = null;
  -    private HashMap registeredForLock = new HashMap();
  -    private OJBTxManager txManager;
  -    /**
  -     * The status of the current transaction, as specified by the
  -     * javax.transaction package.
  -     * See {@link javax.transaction.Status} for list of valid values.
  -     */
  -    private int m_txStatus = Status.STATUS_NO_TRANSACTION;
  -
  -    /**
  -     * the internal table containing all Objects "touched" by this tx and their
  -     * respective transactional state
  -     */
  -    private ObjectEnvelopeTable objectEnvelopeTable = null;
  -
  -    /**
  -     * reference to the currently opened database
  -     */
  -    private DatabaseImpl curDB;
  -    /**
  -     * The tx may me listening to a number of IndirectionHandlers.
  -     * on abort or commit these Handlers must be informed to remove
  -     * tx from their List of Listeners.
  -     */
  -    private ArrayList registeredIndirectionHandlers = new ArrayList();
  -    /**
  -     * list of proxy objects that were locked, but haven't been materialized yet.
  -     * This is necessary so the locks can be released on closing the transaction
  -     */
  -    private ArrayList unmaterializedLocks = new ArrayList();
  -
  -    /**
  -     * Creates new Transaction
  -     * @param theCurrentDB - create a transaction that is associated with the database.
  -     */
  -    public TransactionImpl(DatabaseImpl theCurrentDB)
  -    {
  -        txManager = TxManagerFactory.instance();
  -        // assign a globally uniqe id to this tx
  -        txGUID = new GUID().toString();
  -        curDB = theCurrentDB;
  -    }
  -
  +package org.apache.ojb.odmg;
  +
  +/* ====================================================================
  + * The Apache Software License, Version 1.1
  + *
  + * Copyright (c) 2001 The Apache Software Foundation.  All rights
  + * reserved.
  + *
  + * Redistribution and use in source and binary forms, with or without
  + * modification, are permitted provided that the following conditions
  + * are met:
  + *
  + * 1. Redistributions of source code must retain the above copyright
  + *    notice, this list of conditions and the following disclaimer.
  + *
  + * 2. Redistributions in binary form must reproduce the above copyright
  + *    notice, this list of conditions and the following disclaimer in
  + *    the documentation and/or other materials provided with the
  + *    distribution.
  + *
  + * 3. The end-user documentation included with the redistribution,
  + *    if any, must include the following acknowledgment:
  + *       "This product includes software developed by the
  + *        Apache Software Foundation (http://www.apache.org/)."
  + *    Alternately, this acknowledgment may appear in the software itself,
  + *    if and wherever such third-party acknowledgments normally appear.
  + *
  + * 4. The names "Apache" and "Apache Software Foundation" and
  + *    "Apache ObjectRelationalBridge" must not be used to endorse or promote products
  + *    derived from this software without prior written permission. For
  + *    written permission, please contact apache@apache.org.
  + *
  + * 5. Products derived from this software may not be called "Apache",
  + *    "Apache ObjectRelationalBridge", nor may "Apache" appear in their name, without
  + *    prior written permission of the Apache Software Foundation.
  + *
  + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
  + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  + * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
  + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
  + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  + * SUCH DAMAGE.
  + * ====================================================================
  + *
  + * This software consists of voluntary contributions made by many
  + * individuals on behalf of the Apache Software Foundation.  For more
  + * information on the Apache Software Foundation, please see
  + * <http://www.apache.org/>.
  + */
  +
  +
  +import org.apache.ojb.broker.Identity;
  +import org.apache.ojb.broker.ManageableCollection;
  +import org.apache.ojb.broker.PBFactoryException;
  +import org.apache.ojb.broker.PersistenceBroker;
  +import org.apache.ojb.broker.PersistenceBrokerException;
  +import org.apache.ojb.broker.PersistenceBrokerFactory;
  +import org.apache.ojb.broker.VirtualProxy;
  +import org.apache.ojb.broker.accesslayer.ConnectionManagerIF;
  +import org.apache.ojb.broker.accesslayer.IndirectionHandler;
  +import org.apache.ojb.broker.accesslayer.MaterializationListener;
  +import org.apache.ojb.broker.metadata.ClassDescriptor;
  +import org.apache.ojb.broker.metadata.CollectionDescriptor;
  +import org.apache.ojb.broker.metadata.FieldDescriptor;
  +import org.apache.ojb.broker.metadata.ObjectReferenceDescriptor;
  +import org.apache.ojb.broker.util.ArrayIterator;
  +import org.apache.ojb.broker.util.GUID;
  +import org.apache.ojb.broker.util.configuration.Configurable;
  +import org.apache.ojb.broker.util.configuration.Configuration;
  +import org.apache.ojb.broker.util.configuration.ConfigurationException;
  +import org.apache.ojb.broker.util.logging.Logger;
  +import org.apache.ojb.broker.util.logging.LoggerFactory;
  +import org.apache.ojb.odmg.locking.LockManager;
  +import org.apache.ojb.odmg.locking.LockManagerFactory;
  +import org.odmg.DatabaseClosedException;
  +import org.odmg.LockNotGrantedException;
  +import org.odmg.Transaction;
  +import org.odmg.TransactionAbortedException;
  +import org.odmg.TransactionNotInProgressException;
  +
  +import javax.transaction.Status;
  +import java.util.ArrayList;
  +import java.util.Collection;
  +import java.util.Enumeration;
  +import java.util.HashMap;
  +import java.util.Hashtable;
  +import java.util.Iterator;
  +import java.util.Vector;
  +
  +//#ifdef JDK13
  +import java.lang.reflect.Proxy;
  +//#else
  +/*
  +import com.develop.java.lang.reflect.Proxy;
  +*/
  +//#endif
  +
  +/**
  + *
  + * Implementation of Transaction for org.odmg.Transaction.
  + *
  + * @author     Thomas Mahler & David Dixon-Peugh
  + * @author <a href="mailto:mattbaird@yahoo.com">Matthew Baird</a>
  + * @author <a href="mailto:armin@codeAuLait.de">Armin Waibel</a>
  + * @version $Id$
  + *
  + */
  +public class TransactionImpl
  +        implements Transaction, MaterializationListener, Configurable, HasBroker
  +{
  +    private Logger log = LoggerFactory.getLogger(TransactionImpl.class);
  +    private Hashtable myNrm = null;
  +    private boolean useWriteLocks;
  +    private boolean useImplicitLocking;
  +    private boolean useBatchMode;
  +    private String txGUID;
  +    protected PersistenceBroker broker = null;
  +    private HashMap registeredForLock = new HashMap();
  +    private OJBTxManager txManager;
  +    /**
  +     * The status of the current transaction, as specified by the
  +     * javax.transaction package.
  +     * See {@link javax.transaction.Status} for list of valid values.
  +     */
  +    private int m_txStatus = Status.STATUS_NO_TRANSACTION;
  +
  +    /**
  +     * the internal table containing all Objects "touched" by this tx and their
  +     * respective transactional state
  +     */
  +    private ObjectEnvelopeTable objectEnvelopeTable = null;
  +
  +    /**
  +     * reference to the currently opened database
  +     */
  +    private DatabaseImpl curDB;
  +    /**
  +     * The tx may me listening to a number of IndirectionHandlers.
  +     * on abort or commit these Handlers must be informed to remove
  +     * tx from their List of Listeners.
  +     */
  +    private ArrayList registeredIndirectionHandlers = new ArrayList();
  +    /**
  +     * list of proxy objects that were locked, but haven't been materialized yet.
  +     * This is necessary so the locks can be released on closing the transaction
  +     */
  +    private ArrayList unmaterializedLocks = new ArrayList();
  +
  +    /**
  +     * Creates new Transaction
  +     * @param theCurrentDB - create a transaction that is associated with the database.
  +     */
  +    public TransactionImpl(DatabaseImpl theCurrentDB)
  +    {
  +        txManager = TxManagerFactory.instance();
  +        // assign a globally uniqe id to this tx
  +        txGUID = new GUID().toString();
  +        curDB = theCurrentDB;
  +    }
  +
       /**
        * Returns the associated database
        */
  @@ -170,971 +172,998 @@
           return this.curDB;
       }
   
  -    protected int getStatus()
  -    {
  -        return m_txStatus;
  -    }
  -
  -    private void checkForDB()
  -    {
  -        if (curDB == null || !curDB.isOpen())
  -        {
  -            log.error("Transaction without a associated open Database.");
  -            throw new TransactionAbortedException(
  -                    "No open database found. Open the database before handling transactions");
  -        }
  -    }
  -
  -    /**
  -     * Determine whether the transaction is open or not. A transaction is open if
  -     * a call has been made to <code>begin</code> , but a subsequent call to
  -     * either <code>commit</code> or <code>abort</code> has not been made.
  -     * @return    True if the transaction is open, otherwise false.
  -     */
  -    public boolean isOpen()
  -    {
  -        return (getStatus() == Status.STATUS_ACTIVE ||
  -                getStatus() == Status.STATUS_MARKED_ROLLBACK ||
  -                getStatus() == Status.STATUS_PREPARED ||
  -                getStatus() == Status.STATUS_PREPARING ||
  -                getStatus() == Status.STATUS_COMMITTING);
  -    }
  -
  -    private void checkOpen()
  -    {
  -        if (!isOpen())
  -        {
  -            throw new TransactionNotInProgressException(
  -                    "Transaction was not open, call tx.begin() before perform action, current status is: " +
  -                    TxUtil.getStatusString(getStatus()));
  -        }
  -    }
  -
  -
  -    /**
  -     * Attach the caller's thread to this <code>Transaction</code> and detach the
  -     * thread from any former <code>Transaction</code> the thread may have been
  -     * associated with.
  -     */
  -    public void join()
  -    {
  -        checkOpen();
  -        txManager.deregisterTx(this);
  -        txManager.registerTx(this);
  -    }
  -
  -    /**
  -     * Upgrade the lock on the given object to the given lock mode. The call has
  -     * no effect if the object's current lock is already at or above that level of
  -     * lock mode.
  -     *
  -     * @param  obj       object to acquire a lock on.
  -     * @param  lockMode  lock mode to acquire. The lock modes
  -     * are <code>READ</code> , <code>UPGRADE</code> , and <code>WRITE</code> .
  -     *
  -     * @exception  LockNotGrantedException    Description of Exception
  -     */
  -    public void lock(Object obj, int lockMode) throws LockNotGrantedException
  -    {
  -        ClassDescriptor cld = this.getBroker().getClassDescriptor(obj.getClass());
  -        if (!cld.isAcceptLocks())
  -        {
  -        		if (log.isDebugEnabled())
  -                 log.debug("skipping lock on class: " + cld.getClassNameOfObject() + " object " + obj.toString());
  -            return;
  -        }
  -        else
  -        {
  -            if (log.isDebugEnabled())
  -                log.debug("proceeding with lock on class: " + cld.getClassNameOfObject() + " object " + obj.toString());
  -        }
  -    	
  -        if (log.isDebugEnabled()) log.debug("lock object was called on tx " + this);
  -        checkOpen();
  -
  -        //first assign all foreign keys for non-proxies/virtualproxy
  -        if (!(obj instanceof Proxy) && !(obj instanceof VirtualProxy))
  -        {
  -            assignReferenceFKs(
  -                    obj,
  -                    this.getBroker().getClassDescriptor(obj.getClass()).getObjectReferenceDescriptors());
  -        }
  -
  -        LockManager lm = LockManagerFactory.getLockManager();
  -        if (lockMode == Transaction.READ)
  -        {
  -            if (!lm.readLock(this, obj))
  -            {
  -                throw new LockNotGrantedException("Can not lock " + obj + " for READ");
  -            }
  -        }
  -        else if (lockMode == Transaction.WRITE)
  -        {
  -            if (!lm.writeLock(this, obj))
  -            {
  -                throw new LockNotGrantedException("Can not lock " + obj + " for WRITE");
  -            }
  -        }
  -        else if (lockMode == Transaction.UPGRADE)
  -        {
  -            if (!lm.upgradeLock(this, obj))
  -            {
  -                throw new LockNotGrantedException("Can not lock " + obj + " for UPGRADE");
  -            }
  -        }
  -        try
  -        {
  -            register(obj, lockMode);
  -        }
  -        catch (Throwable t)
  -        {
  -            log.error("Locking obj " + obj + " with lock mode " + lockMode + " failed", t);
  -            lm.releaseLock(this, obj);
  -            throw new LockNotGrantedException(t.getMessage());
  -        }
  -    }
  -
  -    /**
  -     * Detach the caller's thread from this <code>Transaction</code> , but do not
  -     * attach the thread to another <code>Transaction</code> .
  -     */
  -    public void leave()
  -    {
  -        checkOpen();
  -        txManager.deregisterTx(this);
  -    }
  -
  -    /**
  -     * Do the Commits, but don't release the locks.
  -     * I don't know what we should do if we are in a checkpoint and
  -     * we need to abort.
  -     */
  -    private synchronized void doCommitOnObjects() throws org.odmg.TransactionAbortedException
  -    {
  -        ObjectEnvelope item;
  -        // Notify objects of impending commits.
  -        Enumeration enum = objectEnvelopeTable.elements();
  -        while (enum.hasMoreElements())
  -        {
  -            item = (ObjectEnvelope) enum.nextElement();
  -            item.beforeCommit();
  -        }
  -        // Now perfom the real work
  -        objectEnvelopeTable.commit();
  -        // Now, we notify everything the commit is done.
  -        enum = objectEnvelopeTable.elements();
  -        while (enum.hasMoreElements())
  -        {
  -            item = (ObjectEnvelope) enum.nextElement();
  -            item.afterCommit();
  -        }
  -        registeredForLock = new HashMap();
  -    }
  -
  -    /**
  -     * Do the Aborts, but don't release the locks.
  -     * Do the aborts on the NamedRootsMap first, then
  -     * abort the other stuff.
  -     */
  -    protected synchronized void doAbort()
  -    {
  -        ObjectEnvelope item;
  -        Enumeration objectsToAbort = objectEnvelopeTable.elements();
  -        // Notify objects of impending aborts.
  -        while (objectsToAbort.hasMoreElements())
  -        {
  -            item = (ObjectEnvelope) objectsToAbort.nextElement();
  -            item.beforeAbort();
  -        }
  -        // Now, we abort everything. . .
  -        objectEnvelopeTable.rollback();
  -        // Now, we notify everything the abort is done.
  -        objectsToAbort = objectEnvelopeTable.elements();
  -        while (objectsToAbort.hasMoreElements())
  -        {
  -            item = (ObjectEnvelope) objectsToAbort.nextElement();
  -            item.afterAbort();
  -        }
  -    }
  -
  -    /**
  -     * Close a transaction and do all the cleanup associated with it.
  -     */
  -    protected synchronized void doClose()
  -    {
  -        if (!isOpen())
  -        {
  -            throw new IllegalStateException("persist.missingEnd. Tx Status: " +
  -                    TxUtil.getStatusString(getStatus()));
  -        }
  -
  -        try
  -        {
  -            // clear the temporary used named roots map
  -            // we should do that, because same tx instance
  -            // could be used several times
  -            myNrm.clear();
  -
  -            Enumeration enum = objectEnvelopeTable.elements();
  -            while (enum.hasMoreElements())
  -            {
  -                Object obj = ((ObjectEnvelope) enum.nextElement()).getObject();
  -                removeLock(obj, Transaction.WRITE);
  -            }
  -
  -            //remove locks for objects which haven't been materialized yet
  -            for (Iterator it = unmaterializedLocks.iterator(); it.hasNext();)
  -            {
  -                removeLock(it.next(), Transaction.WRITE);
  -            }
  -            unmaterializedLocks.clear();
  -
  -            // this tx is no longer interested in materialization callbacks
  -            unRegisterFromAllIndirectionHandlers();
  -        }
  -        finally
  -        {
  -            /**
  -             * MBAIRD: Be nice and close the table to release all refs
  -             */
  -            try
  -            {
  -                objectEnvelopeTable.close();
  -                objectEnvelopeTable = null;
  -            }
  -            catch (Exception e)
  -            {
  -                if (log.isDebugEnabled())
  -                {
  -                    log.debug("error closing object envelope table : " + e.getMessage());
  -                    e.printStackTrace();
  -                }
  -            }
  -            if (log.isDebugEnabled())
  -                log.debug("Close Transaction and release current PB " + broker + " on tx " + this);
  -            // remove current thread from LocalTxManager
  -            // to avoid problems for succeeding calls of the same thread
  -            txManager.deregisterTx(this);
  -            if (broker != null)
  -            {
  -                broker.close();
  -                broker = null;
  -            }
  -        }
  -    }
  -
  -    /**
  -     * Commit the transaction, but reopen the transaction, retaining all locks.
  -     * Calling <code>checkpoint</code> commits persistent object modifications
  -     * made within the transaction since the last checkpoint to the database. The
  -     * transaction retains all locks it held on those objects at the time the
  -     * checkpoint was invoked.
  -     */
  -    public void checkpoint()
  -    {
  -        if (log.isDebugEnabled()) log.debug("Checkpoint was called, commit changes hold locks on tx " + this);
  -        checkOpen();
  -        try
  -        {
  -            doCommitOnObjects();
  -        }
  -        catch (Throwable t)
  -        {
  -            try
  -            {
  -                doAbort();
  -            }
  -            finally
  -            {
  -                doClose();
  -                m_txStatus = Status.STATUS_ROLLEDBACK;
  -            }
  -            if (t instanceof TransactionAbortedException)
  -            {
  -                throw (TransactionAbortedException) t;
  -            }
  -            else
  -            {
  -                log.error(t);
  -                throw new TransactionAbortedException(t.getMessage());
  -            }
  -        }
  -    }
  -
  -    /**
  -     * Upgrade the lock on the given object to the given lock mode. Method <code>
  -     * tryLock</code> is the same as <code>lock</code> except it returns a boolean
  -     * indicating whether the lock was granted instead of generating an exception.
  -     * @param  obj          Description of Parameter
  -     * @param  lockMode     Description of Parameter
  -     * @return              Description of the Returned Value
  -     * </code>, <code>UPGRADE</code> , and <code>WRITE</code> .
  -     * @return true          if the lock has been acquired, otherwise false.
  -     */
  -    public boolean tryLock(Object obj, int lockMode)
  -    {
  -        if (log.isDebugEnabled()) log.debug("Try to lock object was called on tx " + this);
  -        checkOpen();
  -        try
  -        {
  -            lock(obj, lockMode);
  -            return true;
  -        }
  -        catch (LockNotGrantedException ex)
  -        {
  -            return false;
  -        }
  -    }
  -
  -    /**
  -     * removeLock removes the transactions lock from the Object.
  -     */
  -    private void removeLock(Object obj, int lockType)
  -    {
  -        LockManagerFactory.getLockManager().releaseLock(this, obj);
  -    }
  -
  -    /**
  -     * Commit and close the transaction. Calling <code>commit</code> commits to
  -     * the database all persistent object modifications within the transaction and
  -     * releases any locks held by the transaction. A persistent object
  -     * modification is an update of any field of an existing persistent object, or
  -     * an update or creation of a new named object in the database. If a
  -     * persistent object modification results in a reference from an existing
  -     * persistent object to a transient object, the transient object is moved to
  -     * the database, and all references to it updated accordingly. Note that the
  -     * act of moving a transient object to the database may create still more
  -     * persistent references to transient objects, so its referents must be
  -     * examined and moved as well. This process continues until the database
  -     * contains no references to transient objects, a condition that is guaranteed
  -     * as part of transaction commit. Committing a transaction does not remove
  -     * from memory transient objects created during the transaction.
  -     *
  -     * The updateObjectList contains a list of all objects for which this transaction
  -     * has write privledge to.  We need to update these objects.
  -     */
  -    public void commit()
  -    {
  -        checkOpen();
  -        try
  -        {
  -            prepare();
  -            // Never commit transaction that has been marked for rollback
  -            if (m_txStatus == Status.STATUS_MARKED_ROLLBACK)
  -                throw new TransactionAbortedException("persist.markedRollback");
  -            if (m_txStatus != Status.STATUS_PREPARED)
  -                throw new IllegalStateException("persist.missingPrepare");
  -
  -            m_txStatus = Status.STATUS_COMMITTING;
  -            if (log.isDebugEnabled()) log.debug("Commit transaction " + this + ", commit on broker " + broker);
  -            getBroker().commitTransaction();
  -            doClose();
  -            m_txStatus = Status.STATUS_COMMITTED;
  -        }
  -        catch (TransactionAbortedException ex)
  -        {
  -            m_txStatus = Status.STATUS_MARKED_ROLLBACK;
  -            if (log.isDebugEnabled()) log.debug("Commit fails, do abort this tx", ex);
  -            try
  -            {
  -                doAbort();
  -            }
  -            finally
  -            {
  -                doClose();
  -            }
  -            throw ex;
  -        }
  -    }
  -
  -    /**
  -     * Prepare does the actual work of moving the changes at the object level
  -     * into storage (the underlying rdbms for instance). prepare Can be called multiple times, and
  -     * does not release locks.
  -     * @return True if the transaction can commit, false if the
  -     * transaction is read only.
  -     * @throws TransactionAbortedException if the transaction has been aborted
  -     * for any reason.
  -     * @throws  IllegalStateException Method called if transaction is
  -     *  not in the proper state to perform this operation
  -     * @throws TransactionNotInProgressException if the transaction is closed.
  -     */
  -    protected boolean prepare() throws TransactionAbortedException
  -    {
  -        if (m_txStatus == Status.STATUS_MARKED_ROLLBACK)
  -            throw new TransactionAbortedException("persist.markedRollback");
  -        if (m_txStatus != Status.STATUS_ACTIVE)
  -            throw new IllegalStateException("persist.noTransaction");
  -        try
  -        {
  -            m_txStatus = Status.STATUS_PREPARING;
  -            doCommitOnObjects();
  -            m_txStatus = Status.STATUS_PREPARED;
  -        }
  -        catch (TransactionAbortedException e)
  -        {
  -            log.error("Could not prepare for commit: " + e.getMessage());
  -            m_txStatus = Status.STATUS_MARKED_ROLLBACK;
  -            throw e;
  -        }
  -        return true;
  -    }
  -
  -    /**
  -     * Abort and close the transaction. Calling abort abandons all persistent
  -     * object modifications and releases the associated locks. Aborting a
  -     * transaction does not restore the state of modified transient objects
  -     */
  -    public void abort()
  -    {
  -        if (m_txStatus != Status.STATUS_ACTIVE && m_txStatus != Status.STATUS_PREPARED &&
  -                m_txStatus != Status.STATUS_MARKED_ROLLBACK)
  -            throw new IllegalStateException("persist.noTransaction");
  -        log.info("Abort transaction was called on tx " + this + ", associated PB was " + broker);
  -        try
  -        {
  -            doAbort();
  -            PersistenceBroker broker = getBroker();
  -            if (broker.isInTransaction())
  -            {
  -                broker.abortTransaction();
  -            }
  -        }
  -        finally
  -        {
  -            doClose();
  -            m_txStatus = Status.STATUS_ROLLEDBACK;
  -        }
  -    }
  -
  -    /**
  -     * Start a transaction. Calling <code>begin</code> multiple times on the same
  -     * transaction object, without an intervening call to <code>commit</code> or
  -     * <code>abort</code> , causes the exception <code>
  -     * TransactionInProgressException</code> to be thrown on the second and
  -     * subsequent calls. Operations executed before a transaction has been opened,
  -     * or before reopening after a transaction is aborted or committed, have
  -     * undefined results; these may throw a <code>
  -     * TransactionNotInProgressException</code> exception.
  -     */
  -    public synchronized void begin()
  -    {
  -        /**
  -         * Is the associated database non-null and open? ODMG 3.0 says it must be.
  -         */
  -        if ((curDB == null) || !curDB.isOpen())
  -        {
  -            throw new DatabaseClosedException("Database is not open. Must have an open DB to begin the Tx.");
  -        }
  -        if (isOpen())
  -        {
  -            log.error("Transaction is already open");
  -            throw new org.odmg.TransactionInProgressException("Impossible to call begin on already opened tx");
  -        }
  -        // initialize the ObjectEnvelope table
  -        objectEnvelopeTable = new ObjectEnvelopeTable(this);
  -        // initialize the temporary hashtable
  -        myNrm = new Hashtable();
  -        // register transaction
  -        txManager.registerTx(this);
  -        // mark tx as active (open)
  -        m_txStatus = Status.STATUS_ACTIVE;
  -        if (log.isDebugEnabled()) log.debug("Begin transaction was called on tx " + this + ", with associated PB " + broker);
  -    }
  -
  -    public String getGUID()
  -    {
  -        return txGUID;
  -    }
  -
  -    /**
  -     * marks an object for deletion
  -     * @param  anObject Object to be marked
  -     */
  -    public void markDelete(Object anObject)
  -    {
  -        ObjectEnvelope otw = objectEnvelopeTable.get(anObject);
  -        otw.setModificationState(otw.getModificationState().markDelete());
  -    }
  -
  -    /**
  -     * Get object by identity. First lookup among objects registered in the
  -     * transaction, then in persistent storage.
  -     * @param id The identity
  -     * @return The object
  -     * @throws PersistenceBrokerException
  -     */
  -    public Object getObjectByIdentity(Identity id)
  -            throws PersistenceBrokerException
  -    {
  -        ObjectEnvelope envelope = objectEnvelopeTable.getByIdentity(id);
  -
  -        if (envelope != null)
  -        {
  -            return (envelope.needsDelete() ? null : envelope.getObject());
  -        }
  -        else
  -        {
  -            return broker.getObjectByIdentity(id);
  -        }
  -    }
  -
  -    /**
  -     * Checks if the object with the given identity has been deleted
  -     * within the transaction.
  -     * @param id The identity
  -     * @return true if the object has been deleted
  -     * @throws PersistenceBrokerException
  -     */
  -    public boolean isDeleted(Identity id)
  -    {
  -        ObjectEnvelope envelope = objectEnvelopeTable.getByIdentity(id);
  -
  -        return (envelope == null ? false : envelope.needsDelete());
  -    }
  -
  -    /**
  -     * registers the object with this transaction recursively with all associations.
  -     * OJB implicitely acquires read locks on registered objects.
  -     */
  -    private synchronized void register(Object newTxObject, int lockMode)
  -            throws LockNotGrantedException, PersistenceBrokerException, IllegalAccessException
  -    {
  -        Object objectToRegister = newTxObject;
  -        IndirectionHandler handler = null;
  -
  -        // Proxies must be treated specially
  -        if (newTxObject instanceof VirtualProxy)
  -        {
  -            handler = VirtualProxy.getIndirectionHandler((VirtualProxy) newTxObject);
  -        }
  -        else if (newTxObject instanceof Proxy)
  -        {
  -            handler = (IndirectionHandler) Proxy.getInvocationHandler(newTxObject);
  -        }
  -
  -        /*
  -        if the object is a Proxy there are two options:
  -        1. The proxies real subject has already been materialized:
  -           we take this real subject as the object to register and proceed
  -           as if it were a ordinary object.
  -        2. The real subject has not been materialized: Then there is nothing
  -           to be registered now!
  -           Of course we might just materialize the real subject to have something
  -           to register. But this would make proxies useless for ODMG as proxies would
  -           get materialized even if their real subjects were not used by the
  -           client app.
  -           Thus we register the current transaction as a Listener to the IndirectionHandler
  -           of the Proxy.
  -           Only when the IndirectionHandler performs the materialization of the real subject
  -           at some later point in time it invokes callbacks on all it's listeners.
  -           Using this callback we can defer the registering until it's really needed.
  -        */
  -        if (handler != null)
  -        {
  -            if (handler.alreadyMaterialized())
  -            {
  -                objectToRegister = handler.getRealSubject();
  -            }
  -            else
  -            {
  -                registerToIndirectionHandler(handler);
  -                registerUnmaterializedLocks(newTxObject);
  -                return;
  -            }
  -        }
  -
  -        // no Proxy:
  -        ObjectEnvelope envelope = objectEnvelopeTable.getByIdentity(new Identity(objectToRegister, getBroker()));
  -        if ((envelope == null) || envelope.needsDelete())
  -        {
  -            // if OJB is configured to use only implicit readlocks, change the lockmode
  -            int assLockMode = lockMode;
  -            if (!useWriteLocks)
  -            {
  -                assLockMode = Transaction.READ;
  -            }
  -
  -            ClassDescriptor cld = null;
  -            cld = this.getBroker().getClassDescriptor(objectToRegister.getClass());
  -            // 1. register associated objects
  -            if (useImplicitLocking)
  -            {
  -                lockReferences(cld, objectToRegister, assLockMode);
  -            }
  -            // 2. register object itself
  -            objectEnvelopeTable.put(objectToRegister, new ObjectEnvelope(objectToRegister, this));
  -
  -            // 3. register objects in collection attributes
  -            if (useImplicitLocking)
  -            {
  -                lockCollections(cld, objectToRegister, assLockMode);
  -            }
  -        }
  -        else
  -        {
  -            // Object already registered, do nothing!
  -        }
  -    }
  -
  -    private void assertFkAssignment(Object obj, Object ref, ObjectReferenceDescriptor rds)
  -    {
  -        try
  -        {
  -            if ((!(obj instanceof VirtualProxy))
  -                    && (!(obj instanceof Proxy))
  -                    && (ref != null)
  -                    && (!(ref instanceof VirtualProxy)))
  -            {
  -                Identity refOID = new Identity(ref, getBroker());
  -                Object[] refPkValues = refOID.getPrimaryKeyValues();
  -
  -                ClassDescriptor objCld = this.getBroker().getClassDescriptor(obj.getClass());
  -                org.apache.ojb.broker.metadata.FieldDescriptor[] objFkFields = rds.getForeignKeyFieldDescriptors(objCld);
  -                /**
  -                 * MBAIRD:
  -                 * objFkFields could end up being null in case of non-mapped indirection table of m:n relationship
  -                 *
  -                 */
  -                if (objFkFields != null)
  -                {
  -                    org.apache.ojb.broker.metadata.FieldDescriptor fld = null;
  -                    for (int i = 0; i < objFkFields.length; i++)
  -                    {
  -                        fld = objFkFields[i];
  -                        fld.getPersistentField().set(obj, refPkValues[i]);
  -                    }
  -                }
  -            }
  -        }
  -        catch (Throwable t)
  -        {
  -            throw new PersistenceBrokerException(t);
  -        }
  -    }
  -
  -    /**
  -     * 	assigns all foreign key attributes of the Object obj.
  -     *  used during store(obj, boolean);
  -     */
  -    private void assignReferenceFKs(Object obj, Vector vecRds) throws PersistenceBrokerException
  -    {
  -        try
  -        {
  -            // get all members of obj that are references and assign FKs
  -            Iterator i = vecRds.iterator();
  -            while (i.hasNext())
  -            {
  -                ObjectReferenceDescriptor rds = (ObjectReferenceDescriptor) i.next();
  -                Object ref = rds.getPersistentField().get(obj);
  -                assertFkAssignment(obj, ref, rds);
  -            }
  -        }
  -        catch (Throwable t)
  -        {
  -            throw new PersistenceBrokerException(t);
  -        }
  -    }
  -
  -    private void lockCollections(ClassDescriptor cld, Object newTxObject, int lockMode)
  -            throws PersistenceBrokerException
  -    {
  -        Iterator i;
  -        i = cld.getCollectionDescriptors().iterator();
  -        while (i.hasNext())
  -        {
  -            CollectionDescriptor cds = (CollectionDescriptor) i.next();
  -            Object col = cds.getPersistentField().get(newTxObject);
  -            if (col != null)
  -            {
  -                Iterator colIterator;
  -                if (col instanceof ManageableCollection)
  -                {
  -                    colIterator = ((ManageableCollection) col).ojbIterator();
  -                }
  -                else if (col instanceof Collection)
  -                {
  -                    colIterator = ((Collection) col).iterator();
  -                }
  -                else if (col.getClass().isArray())
  -                {
  -                    colIterator = new ArrayIterator(col);
  -                }
  -                else
  -                {
  -                    throw new RuntimeException(
  -                            col.getClass()
  -                            + " can not be managed by OJB, use Array, Collection or ManageableCollection instead !");
  -                }
  -
  -                // get foreign info for collection elements
  -                ClassDescriptor itemCld = this.getBroker().getClassDescriptor(cds.getItemClass());
  -                Object[] objPkValues = cld.getKeyValues(newTxObject);
  -                FieldDescriptor[] itemFkFields = cds.getForeignKeyFieldDescriptors(itemCld);
  -                /**
  -                 * itemFkFields will be null in the case of many to many relationships.
  -                 */
  -                if (itemFkFields != null)
  -                {
  -                    while (colIterator.hasNext())
  -                    {
  -                        Object item = colIterator.next();
  -                        if (Proxy.isProxyClass(item.getClass()))
  -                        {
  -                            IndirectionHandler handler = (IndirectionHandler) Proxy.getInvocationHandler(item);
  -                            if (!handler.alreadyMaterialized())
  -                            {
  -                                continue;
  -                            }
  -                            else
  -                            {
  -                                item = handler.getRealSubject();
  -                            }
  -                        }
  -                        if (item instanceof VirtualProxy)
  -                        {
  -                            VirtualProxy proxy = (VirtualProxy) item;
  -                            if (!proxy.alreadyMaterialized())
  -                            {
  -                                continue;
  -                            }
  -                            else
  -                            {
  -                                item = proxy.getRealSubject();
  -                            }
  -                        }
  -                        //if itemCld refers to an interface the foreignKeyFieldDescriptors
  -                        //have to be computed again for each concrete class
  -                        if (itemCld.isInterface())
  -                        {
  -                            ClassDescriptor concreteItemCld = getBroker().getClassDescriptor(item.getClass());
  -                            itemFkFields = cds.getForeignKeyFieldDescriptors(concreteItemCld);
  -                        }
  -                        // provide all items in collection attributes
  -                        // with foreign key information before locking them!
  -                        for (int j = 0; j < itemFkFields.length; j++)
  -                        {
  -                            FieldDescriptor fld = itemFkFields[j];
  -                            fld.getPersistentField().set(item, objPkValues[j]);
  -                        }
  -                        lock(item, lockMode);
  -                    }
  -                }
  -                else
  -                {
  -                    //objects of m:n-relations have to be locked as well
  -                    while (colIterator.hasNext())
  -                    {
  -                        Object item = colIterator.next();
  -                        lock(item, lockMode);
  -                    }
  -                }
  -            }
  -        }
  -    }
  -
  -    /**
  -     * we only use the registeredForLock map if the object is not a proxy. During the
  -     * reference locking, we will materialize objects and they will enter the registered for
  -     * lock map.
  -     */
  -    private void lockReferences(ClassDescriptor cld, Object newTxObject, int lockMode)
  -            throws PersistenceBrokerException
  -    {
  -        if ((newTxObject != null)
  -                && !(newTxObject instanceof VirtualProxy)
  -                && !(newTxObject instanceof Proxy))
  -            registeredForLock.put(newTxObject, newTxObject);
  -        Iterator i = cld.getObjectReferenceDescriptors().iterator();
  -        while (i.hasNext())
  -        {
  -            ObjectReferenceDescriptor rds = (ObjectReferenceDescriptor) i.next();
  -            Object refObj = rds.getPersistentField().get(newTxObject);
  -            if (refObj != null)
  -            {
  -                if ((refObj instanceof VirtualProxy) || (refObj instanceof Proxy))
  -                    lock(refObj, lockMode);
  -                else if (!registeredForLock.containsKey(refObj))
  -                {
  -                    lock(refObj, lockMode);
  -                }
  -            }
  -        }
  -    }
  -
  -    /**
  -     * lookup an identity from the transactions temporary nrm table.
  -     * @param name - the name to lookup.
  -     * @return Identity - the found Identity or null if name not defined.
  -     */
  -    Identity getNrmEntry(String name)
  -    {
  -        return (Identity) myNrm.get(name);
  -    }
  -
  -    /**
  -     * make a binding name/identity to the transactions temporary nrm table.
  -     * @param key - the identifying name
  -     * @param value the Identity to store
  -     */
  -    void putNrmEntry(String key, Identity value)
  -    {
  -        myNrm.put(key, value);
  -    }
  -
  -    /**
  -     * unbind an entry from the transactions temporary nrm table.
  -     * @param key - the identifying string whose entry is to be deleted.
  -     */
  -    boolean unbindNrmEntry(String key)
  -    {
  -        // remove from envelopeTable to prevent commit of old entry on tx commit!
  -        Identity oid = (Identity) myNrm.get(key);
  -        if (oid != null)
  -        {
  -            objectEnvelopeTable.remove(oid);
  -        }
  -
  -        // remove from transient NRM
  -        if (myNrm.remove(key) == null)
  -            return false;
  -        else
  -            return true;
  -    }
  -
  -    /**
  -     *  this callback is invoked before an Object is materialized
  -     *  within an IndirectionHandler.
  -     *  @param handler the invoking handler
  -     *  @param oid the identity of the object to be materialized
  -     */
  -    public void beforeMaterialization(IndirectionHandler handler, Identity oid)
  -    {
  -        //noop
  -    }
  -
  -    /**
  -     *  this callback is invoked after an Object is materialized
  -     *  within an IndirectionHandler.
  -     *  this callback allows to defer registration of objects until
  -     *  it's really neccessary.
  -     *  @param handler the invoking handler
  -     *  @param materializedObject the materialized Object
  -     */
  -    public void afterMaterialization(IndirectionHandler handler, Object materializedObject)
  -    {
  -        if (log.isDebugEnabled())
  -            log.debug("deferred registration: " + new Identity(materializedObject, getBroker()).toString());
  -        try
  -        {
  -            register(materializedObject, READ);
  -        }
  -        catch (Throwable t)
  -        {
  -            log.error("Register materialized object with this tx failed", t);
  -            throw new LockNotGrantedException(t.getMessage());
  -        }
  -        unregisterFromIndirectionHandler(handler);
  -    }
  -
  -    protected synchronized void unRegisterFromAllIndirectionHandlers()
  -    {
  -        // unregistering manipulates the registeredIndirectionHandlers vector
  -        // we have to loop through this vector to avoid index proplems.
  -        for (int i = registeredIndirectionHandlers.size() - 1; i >= 0; i--)
  -        {
  -            unregisterFromIndirectionHandler((IndirectionHandler) registeredIndirectionHandlers.get(i));
  -        }
  -    }
  -
  -    protected synchronized void unregisterFromIndirectionHandler(IndirectionHandler handler)
  -    {
  -        handler.removeListener(this);
  -        registeredIndirectionHandlers.remove(handler);
  -    }
  -
  -    protected synchronized void registerToIndirectionHandler(IndirectionHandler handler)
  -    {
  -        handler.addListener(this);
  -        registeredIndirectionHandlers.add(handler);
  -    }
  -
  -    /**
  -     * register proxy objects that were locked but haven't been materialized yet
  -     * so they can be unlocked when closing the transaction
  -     */
  -    protected void registerUnmaterializedLocks(Object obj)
  -    {
  -        unmaterializedLocks.add(obj);
  -    }
  -
  -    /**
  -     * Gets the broker associated with the transaction.
  -     * MBAIRD: only return the associated broker if the transaction is open,
  -     * if it's closed, throw a TransactionNotInProgressException. If we allow
  -     * brokers to be reaquired by an already closed transaction, there is a
  -     * very good chance the broker will be leaked as the doClose() method of
  -     * transactionImpl will never be called and thus the broker will never
  -     * be closed and returned to the pool.
  -     * @return Returns a PersistenceBroker
  -     * @throws TransactionNotInProgressException is the transaction is not open;
  -     */
  -    public PersistenceBroker getBroker()
  -    {
  -        if (broker == null)
  -        {
  -            if (this.isOpen())
  -            {
  -                try
  -                {
  -                    checkForDB();
  -                    broker = PersistenceBrokerFactory.createPersistenceBroker(curDB.getPBKey());
  -                }
  -                catch (PBFactoryException e)
  -                {
  -                    log.error("Cannot obtain PersistenceBroker from PersistenceBrokerFactory, " +
  -                            "found PBKey was " + curDB.getPBKey(), e);
  -                    throw new PersistenceBrokerException(e);
  -                }
  -            }
  -            else
  -            {
  -                throw new TransactionNotInProgressException(
  -                        "Cannot obtain a broker from a transaction that is not open. TX Status: " +
  -                        TxUtil.getStatusString(getStatus()));
  -            }
  -        }
  -        return broker;
  -    }
  -
  -    /*
  -     * @see Configurable#configure(Configuration)
  -     */
  -    public void configure(Configuration config) throws ConfigurationException
  -    {
  -        useWriteLocks = ((OdmgConfiguration) config).lockAssociationAsWrites();
  -        useImplicitLocking = ((OdmgConfiguration) config).useImplicitLocking();
  -    }
  -
  -// arminw: commented out unused methods
  -//    private void internalBegin()
  -//    {
  -//
  -//    }
  -//
  -//    private void internalCommit()
  -//    {
  -//
  -//    }
  -//
  -//    private void internalClose()
  -//    {
  -//
  -//    }
  -//
  -//    private void internalPrepare()
  -//    {
  -//
  -//    }
  -
  -}
  +    protected int getStatus()
  +    {
  +        return m_txStatus;
  +    }
  +
  +    private void checkForDB()
  +    {
  +        if (curDB == null || !curDB.isOpen())
  +        {
  +            log.error("Transaction without a associated open Database.");
  +            throw new TransactionAbortedException(
  +                    "No open database found. Open the database before handling transactions");
  +        }
  +    }
  +
  +    /**
  +     * Determine whether the transaction is open or not. A transaction is open if
  +     * a call has been made to <code>begin</code> , but a subsequent call to
  +     * either <code>commit</code> or <code>abort</code> has not been made.
  +     * @return    True if the transaction is open, otherwise false.
  +     */
  +    public boolean isOpen()
  +    {
  +        return (getStatus() == Status.STATUS_ACTIVE ||
  +                getStatus() == Status.STATUS_MARKED_ROLLBACK ||
  +                getStatus() == Status.STATUS_PREPARED ||
  +                getStatus() == Status.STATUS_PREPARING ||
  +                getStatus() == Status.STATUS_COMMITTING);
  +    }
  +
  +    private void checkOpen()
  +    {
  +        if (!isOpen())
  +        {
  +            throw new TransactionNotInProgressException(
  +                    "Transaction was not open, call tx.begin() before perform action, current status is: " +
  +                    TxUtil.getStatusString(getStatus()));
  +        }
  +    }
  +
  +
  +    /**
  +     * Attach the caller's thread to this <code>Transaction</code> and detach the
  +     * thread from any former <code>Transaction</code> the thread may have been
  +     * associated with.
  +     */
  +    public void join()
  +    {
  +        checkOpen();
  +        txManager.deregisterTx(this);
  +        txManager.registerTx(this);
  +    }
  +
  +    /**
  +     * Upgrade the lock on the given object to the given lock mode. The call has
  +     * no effect if the object's current lock is already at or above that level of
  +     * lock mode.
  +     *
  +     * @param  obj       object to acquire a lock on.
  +     * @param  lockMode  lock mode to acquire. The lock modes
  +     * are <code>READ</code> , <code>UPGRADE</code> , and <code>WRITE</code> .
  +     *
  +     * @exception  LockNotGrantedException    Description of Exception
  +     */
  +    public void lock(Object obj, int lockMode) throws LockNotGrantedException
  +    {
  +        ClassDescriptor cld = this.getBroker().getClassDescriptor(obj.getClass());
  +        if (!cld.isAcceptLocks())
  +        {
  +        		if (log.isDebugEnabled())
  +                 log.debug("skipping lock on class: " + cld.getClassNameOfObject() + " object " + obj.toString());
  +            return;
  +        }
  +        else
  +        {
  +            if (log.isDebugEnabled())
  +                log.debug("proceeding with lock on class: " + cld.getClassNameOfObject() + " object " + obj.toString());
  +        }
  +    	
  +        if (log.isDebugEnabled()) log.debug("lock object was called on tx " + this);
  +        checkOpen();
  +
  +        //first assign all foreign keys for non-proxies/virtualproxy
  +        if (!(obj instanceof Proxy) && !(obj instanceof VirtualProxy))
  +        {
  +            assignReferenceFKs(
  +                    obj,
  +                    this.getBroker().getClassDescriptor(obj.getClass()).getObjectReferenceDescriptors());
  +        }
  +
  +        LockManager lm = LockManagerFactory.getLockManager();
  +        if (lockMode == Transaction.READ)
  +        {
  +            if (!lm.readLock(this, obj))
  +            {
  +                throw new LockNotGrantedException("Can not lock " + obj + " for READ");
  +            }
  +        }
  +        else if (lockMode == Transaction.WRITE)
  +        {
  +            if (!lm.writeLock(this, obj))
  +            {
  +                throw new LockNotGrantedException("Can not lock " + obj + " for WRITE");
  +            }
  +        }
  +        else if (lockMode == Transaction.UPGRADE)
  +        {
  +            if (!lm.upgradeLock(this, obj))
  +            {
  +                throw new LockNotGrantedException("Can not lock " + obj + " for UPGRADE");
  +            }
  +        }
  +        try
  +        {
  +            register(obj, lockMode);
  +        }
  +        catch (Throwable t)
  +        {
  +            log.error("Locking obj " + obj + " with lock mode " + lockMode + " failed", t);
  +            lm.releaseLock(this, obj);
  +            throw new LockNotGrantedException(t.getMessage());
  +        }
  +    }
  +
  +    /**
  +     * Detach the caller's thread from this <code>Transaction</code> , but do not
  +     * attach the thread to another <code>Transaction</code> .
  +     */
  +    public void leave()
  +    {
  +        checkOpen();
  +        txManager.deregisterTx(this);
  +    }
  +
  +    /**
  +     * Do the Commits, but don't release the locks.
  +     * I don't know what we should do if we are in a checkpoint and
  +     * we need to abort.
  +     */
  +    private synchronized void doCommitOnObjects() throws org.odmg.TransactionAbortedException
  +    {
  +        ObjectEnvelope item;
  +        ConnectionManagerIF connMan = null;
  +
  +        // Notify objects of impending commits.
  +        Enumeration enum = objectEnvelopeTable.elements();
  +        while (enum.hasMoreElements())
  +        {
  +            item = (ObjectEnvelope) enum.nextElement();
  +            item.beforeCommit();
  +        }
  +        
  +        // Do we need to turn on the batch mode?
  +        if (useBatchMode)
  +        {
  +            connMan = getBroker().getConnectionManager();
  +            connMan.setBatchMode(true);
  +        }
  +
  +        // Now perfom the real work
  +        objectEnvelopeTable.commit();
  +
  +        // if if use batch mode, it's time to execute the batch
  +        if (useBatchMode)
  +        {
  +            try
  +            {
  +                connMan.executeBatch();
  +            }
  +            catch (Exception ex)
  +            {
  +                throw new TransactionAbortedException(ex.toString());
  +            }
  +        }
  +
  +        // Now, we notify everything the commit is done.
  +        enum = objectEnvelopeTable.elements();
  +        while (enum.hasMoreElements())
  +        {
  +            item = (ObjectEnvelope) enum.nextElement();
  +            item.afterCommit();
  +        }
  +        registeredForLock = new HashMap();
  +    }
  +
  +    /**
  +     * Do the Aborts, but don't release the locks.
  +     * Do the aborts on the NamedRootsMap first, then
  +     * abort the other stuff.
  +     */
  +    protected synchronized void doAbort()
  +    {
  +        ObjectEnvelope item;
  +        Enumeration objectsToAbort = objectEnvelopeTable.elements();
  +        // Notify objects of impending aborts.
  +        while (objectsToAbort.hasMoreElements())
  +        {
  +            item = (ObjectEnvelope) objectsToAbort.nextElement();
  +            item.beforeAbort();
  +        }
  +        // Now, we abort everything. . .
  +        objectEnvelopeTable.rollback();
  +        // Now, we notify everything the abort is done.
  +        objectsToAbort = objectEnvelopeTable.elements();
  +        while (objectsToAbort.hasMoreElements())
  +        {
  +            item = (ObjectEnvelope) objectsToAbort.nextElement();
  +            item.afterAbort();
  +        }
  +    }
  +
  +    /**
  +     * Close a transaction and do all the cleanup associated with it.
  +     */
  +    protected synchronized void doClose()
  +    {
  +        if (!isOpen())
  +        {
  +            throw new IllegalStateException("persist.missingEnd. Tx Status: " +
  +                    TxUtil.getStatusString(getStatus()));
  +        }
  +
  +        try
  +        {
  +            // clear the temporary used named roots map
  +            // we should do that, because same tx instance
  +            // could be used several times
  +            myNrm.clear();
  +
  +            Enumeration enum = objectEnvelopeTable.elements();
  +            while (enum.hasMoreElements())
  +            {
  +                Object obj = ((ObjectEnvelope) enum.nextElement()).getObject();
  +                removeLock(obj, Transaction.WRITE);
  +            }
  +
  +            //remove locks for objects which haven't been materialized yet
  +            for (Iterator it = unmaterializedLocks.iterator(); it.hasNext();)
  +            {
  +                removeLock(it.next(), Transaction.WRITE);
  +            }
  +            unmaterializedLocks.clear();
  +
  +            // this tx is no longer interested in materialization callbacks
  +            unRegisterFromAllIndirectionHandlers();
  +        }
  +        finally
  +        {
  +            /**
  +             * MBAIRD: Be nice and close the table to release all refs
  +             */
  +            try
  +            {
  +                objectEnvelopeTable.close();
  +                objectEnvelopeTable = null;
  +            }
  +            catch (Exception e)
  +            {
  +                if (log.isDebugEnabled())
  +                {
  +                    log.debug("error closing object envelope table : " + e.getMessage());
  +                    e.printStackTrace();
  +                }
  +            }
  +            if (log.isDebugEnabled())
  +                log.debug("Close Transaction and release current PB " + broker + " on tx " + this);
  +            // remove current thread from LocalTxManager
  +            // to avoid problems for succeeding calls of the same thread
  +            txManager.deregisterTx(this);
  +            if (broker != null)
  +            {
  +                broker.close();
  +                broker = null;
  +            }
  +        }
  +    }
  +
  +    /**
  +     * Commit the transaction, but reopen the transaction, retaining all locks.
  +     * Calling <code>checkpoint</code> commits persistent object modifications
  +     * made within the transaction since the last checkpoint to the database. The
  +     * transaction retains all locks it held on those objects at the time the
  +     * checkpoint was invoked.
  +     */
  +    public void checkpoint()
  +    {
  +        if (log.isDebugEnabled()) log.debug("Checkpoint was called, commit changes hold locks on tx " + this);
  +        checkOpen();
  +        try
  +        {
  +            doCommitOnObjects();
  +        }
  +        catch (Throwable t)
  +        {
  +            try
  +            {
  +                doAbort();
  +            }
  +            finally
  +            {
  +                doClose();
  +                m_txStatus = Status.STATUS_ROLLEDBACK;
  +            }
  +            if (t instanceof TransactionAbortedException)
  +            {
  +                throw (TransactionAbortedException) t;
  +            }
  +            else
  +            {
  +                log.error(t);
  +                throw new TransactionAbortedException(t.getMessage());
  +            }
  +        }
  +    }
  +
  +    /**
  +     * Upgrade the lock on the given object to the given lock mode. Method <code>
  +     * tryLock</code> is the same as <code>lock</code> except it returns a boolean
  +     * indicating whether the lock was granted instead of generating an exception.
  +     * @param  obj          Description of Parameter
  +     * @param  lockMode     Description of Parameter
  +     * @return              Description of the Returned Value
  +     * </code>, <code>UPGRADE</code> , and <code>WRITE</code> .
  +     * @return true          if the lock has been acquired, otherwise false.
  +     */
  +    public boolean tryLock(Object obj, int lockMode)
  +    {
  +        if (log.isDebugEnabled()) log.debug("Try to lock object was called on tx " + this);
  +        checkOpen();
  +        try
  +        {
  +            lock(obj, lockMode);
  +            return true;
  +        }
  +        catch (LockNotGrantedException ex)
  +        {
  +            return false;
  +        }
  +    }
  +
  +    /**
  +     * removeLock removes the transactions lock from the Object.
  +     */
  +    private void removeLock(Object obj, int lockType)
  +    {
  +        LockManagerFactory.getLockManager().releaseLock(this, obj);
  +    }
  +
  +    /**
  +     * Commit and close the transaction. Calling <code>commit</code> commits to
  +     * the database all persistent object modifications within the transaction and
  +     * releases any locks held by the transaction. A persistent object
  +     * modification is an update of any field of an existing persistent object, or
  +     * an update or creation of a new named object in the database. If a
  +     * persistent object modification results in a reference from an existing
  +     * persistent object to a transient object, the transient object is moved to
  +     * the database, and all references to it updated accordingly. Note that the
  +     * act of moving a transient object to the database may create still more
  +     * persistent references to transient objects, so its referents must be
  +     * examined and moved as well. This process continues until the database
  +     * contains no references to transient objects, a condition that is guaranteed
  +     * as part of transaction commit. Committing a transaction does not remove
  +     * from memory transient objects created during the transaction.
  +     *
  +     * The updateObjectList contains a list of all objects for which this transaction
  +     * has write privledge to.  We need to update these objects.
  +     */
  +    public void commit()
  +    {
  +        checkOpen();
  +        try
  +        {
  +            prepare();
  +            // Never commit transaction that has been marked for rollback
  +            if (m_txStatus == Status.STATUS_MARKED_ROLLBACK)
  +                throw new TransactionAbortedException("persist.markedRollback");
  +            if (m_txStatus != Status.STATUS_PREPARED)
  +                throw new IllegalStateException("persist.missingPrepare");
  +
  +            m_txStatus = Status.STATUS_COMMITTING;
  +            if (log.isDebugEnabled()) log.debug("Commit transaction " + this + ", commit on broker " + broker);
  +            getBroker().commitTransaction();
  +            doClose();
  +            m_txStatus = Status.STATUS_COMMITTED;
  +        }
  +        catch (TransactionAbortedException ex)
  +        {
  +            m_txStatus = Status.STATUS_MARKED_ROLLBACK;
  +            if (log.isDebugEnabled()) log.debug("Commit fails, do abort this tx", ex);
  +            try
  +            {
  +                doAbort();
  +            }
  +            finally
  +            {
  +                doClose();
  +            }
  +            throw ex;
  +        }
  +    }
  +
  +    /**
  +     * Prepare does the actual work of moving the changes at the object level
  +     * into storage (the underlying rdbms for instance). prepare Can be called multiple times, and
  +     * does not release locks.
  +     * @return True if the transaction can commit, false if the
  +     * transaction is read only.
  +     * @throws TransactionAbortedException if the transaction has been aborted
  +     * for any reason.
  +     * @throws  IllegalStateException Method called if transaction is
  +     *  not in the proper state to perform this operation
  +     * @throws TransactionNotInProgressException if the transaction is closed.
  +     */
  +    protected boolean prepare() throws TransactionAbortedException
  +    {
  +        if (m_txStatus == Status.STATUS_MARKED_ROLLBACK)
  +            throw new TransactionAbortedException("persist.markedRollback");
  +        if (m_txStatus != Status.STATUS_ACTIVE)
  +            throw new IllegalStateException("persist.noTransaction");
  +        try
  +        {
  +            m_txStatus = Status.STATUS_PREPARING;
  +            doCommitOnObjects();
  +            m_txStatus = Status.STATUS_PREPARED;
  +        }
  +        catch (TransactionAbortedException e)
  +        {
  +            log.error("Could not prepare for commit: " + e.getMessage());
  +            m_txStatus = Status.STATUS_MARKED_ROLLBACK;
  +            throw e;
  +        }
  +        return true;
  +    }
  +
  +    /**
  +     * Abort and close the transaction. Calling abort abandons all persistent
  +     * object modifications and releases the associated locks. Aborting a
  +     * transaction does not restore the state of modified transient objects
  +     */
  +    public void abort()
  +    {
  +        if (m_txStatus != Status.STATUS_ACTIVE && m_txStatus != Status.STATUS_PREPARED &&
  +                m_txStatus != Status.STATUS_MARKED_ROLLBACK)
  +            throw new IllegalStateException("persist.noTransaction");
  +        log.info("Abort transaction was called on tx " + this + ", associated PB was " + broker);
  +        try
  +        {
  +            doAbort();
  +            PersistenceBroker broker = getBroker();
  +            if (broker.isInTransaction())
  +            {
  +                broker.abortTransaction();
  +            }
  +        }
  +        finally
  +        {
  +            doClose();
  +            m_txStatus = Status.STATUS_ROLLEDBACK;
  +        }
  +    }
  +
  +    /**
  +     * Start a transaction. Calling <code>begin</code> multiple times on the same
  +     * transaction object, without an intervening call to <code>commit</code> or
  +     * <code>abort</code> , causes the exception <code>
  +     * TransactionInProgressException</code> to be thrown on the second and
  +     * subsequent calls. Operations executed before a transaction has been opened,
  +     * or before reopening after a transaction is aborted or committed, have
  +     * undefined results; these may throw a <code>
  +     * TransactionNotInProgressException</code> exception.
  +     */
  +    public synchronized void begin()
  +    {
  +        /**
  +         * Is the associated database non-null and open? ODMG 3.0 says it must be.
  +         */
  +        if ((curDB == null) || !curDB.isOpen())
  +        {
  +            throw new DatabaseClosedException("Database is not open. Must have an open DB to begin the Tx.");
  +        }
  +        if (isOpen())
  +        {
  +            log.error("Transaction is already open");
  +            throw new org.odmg.TransactionInProgressException("Impossible to call begin on already opened tx");
  +        }
  +        // initialize the ObjectEnvelope table
  +        objectEnvelopeTable = new ObjectEnvelopeTable(this);
  +        // initialize the temporary hashtable
  +        myNrm = new Hashtable();
  +        // register transaction
  +        txManager.registerTx(this);
  +        // mark tx as active (open)
  +        m_txStatus = Status.STATUS_ACTIVE;
  +        if (log.isDebugEnabled()) log.debug("Begin transaction was called on tx " + this + ", with associated PB " + broker);
  +    }
  +
  +    public String getGUID()
  +    {
  +        return txGUID;
  +    }
  +
  +    /**
  +     * marks an object for deletion
  +     * @param  anObject Object to be marked
  +     */
  +    public void markDelete(Object anObject)
  +    {
  +        ObjectEnvelope otw = objectEnvelopeTable.get(anObject);
  +        otw.setModificationState(otw.getModificationState().markDelete());
  +    }
  +
  +    /**
  +     * Get object by identity. First lookup among objects registered in the
  +     * transaction, then in persistent storage.
  +     * @param id The identity
  +     * @return The object
  +     * @throws PersistenceBrokerException
  +     */
  +    public Object getObjectByIdentity(Identity id)
  +            throws PersistenceBrokerException
  +    {
  +        ObjectEnvelope envelope = objectEnvelopeTable.getByIdentity(id);
  +
  +        if (envelope != null)
  +        {
  +            return (envelope.needsDelete() ? null : envelope.getObject());
  +        }
  +        else
  +        {
  +            return broker.getObjectByIdentity(id);
  +        }
  +    }
  +
  +    /**
  +     * Checks if the object with the given identity has been deleted
  +     * within the transaction.
  +     * @param id The identity
  +     * @return true if the object has been deleted
  +     * @throws PersistenceBrokerException
  +     */
  +    public boolean isDeleted(Identity id)
  +    {
  +        ObjectEnvelope envelope = objectEnvelopeTable.getByIdentity(id);
  +
  +        return (envelope == null ? false : envelope.needsDelete());
  +    }
  +
  +    /**
  +     * registers the object with this transaction recursively with all associations.
  +     * OJB implicitely acquires read locks on registered objects.
  +     */
  +    private synchronized void register(Object newTxObject, int lockMode)
  +            throws LockNotGrantedException, PersistenceBrokerException, IllegalAccessException
  +    {
  +        Object objectToRegister = newTxObject;
  +        IndirectionHandler handler = null;
  +
  +        // Proxies must be treated specially
  +        if (newTxObject instanceof VirtualProxy)
  +        {
  +            handler = VirtualProxy.getIndirectionHandler((VirtualProxy) newTxObject);
  +        }
  +        else if (newTxObject instanceof Proxy)
  +        {
  +            handler = (IndirectionHandler) Proxy.getInvocationHandler(newTxObject);
  +        }
  +
  +        /*
  +        if the object is a Proxy there are two options:
  +        1. The proxies real subject has already been materialized:
  +           we take this real subject as the object to register and proceed
  +           as if it were a ordinary object.
  +        2. The real subject has not been materialized: Then there is nothing
  +           to be registered now!
  +           Of course we might just materialize the real subject to have something
  +           to register. But this would make proxies useless for ODMG as proxies would
  +           get materialized even if their real subjects were not used by the
  +           client app.
  +           Thus we register the current transaction as a Listener to the IndirectionHandler
  +           of the Proxy.
  +           Only when the IndirectionHandler performs the materialization of the real subject
  +           at some later point in time it invokes callbacks on all it's listeners.
  +           Using this callback we can defer the registering until it's really needed.
  +        */
  +        if (handler != null)
  +        {
  +            if (handler.alreadyMaterialized())
  +            {
  +                objectToRegister = handler.getRealSubject();
  +            }
  +            else
  +            {
  +                registerToIndirectionHandler(handler);
  +                registerUnmaterializedLocks(newTxObject);
  +                return;
  +            }
  +        }
  +
  +        // no Proxy:
  +        ObjectEnvelope envelope = objectEnvelopeTable.getByIdentity(new Identity(objectToRegister, getBroker()));
  +        if ((envelope == null) || envelope.needsDelete())
  +        {
  +            // if OJB is configured to use only implicit readlocks, change the lockmode
  +            int assLockMode = lockMode;
  +            if (!useWriteLocks)
  +            {
  +                assLockMode = Transaction.READ;
  +            }
  +
  +            ClassDescriptor cld = null;
  +            cld = this.getBroker().getClassDescriptor(objectToRegister.getClass());
  +            // 1. register associated objects
  +            if (useImplicitLocking)
  +            {
  +                lockReferences(cld, objectToRegister, assLockMode);
  +            }
  +            // 2. register object itself
  +            objectEnvelopeTable.put(objectToRegister, new ObjectEnvelope(objectToRegister, this));
  +
  +            // 3. register objects in collection attributes
  +            if (useImplicitLocking)
  +            {
  +                lockCollections(cld, objectToRegister, assLockMode);
  +            }
  +        }
  +        else
  +        {
  +            // Object already registered, do nothing!
  +        }
  +    }
  +
  +    private void assertFkAssignment(Object obj, Object ref, ObjectReferenceDescriptor rds)
  +    {
  +        try
  +        {
  +            if ((!(obj instanceof VirtualProxy))
  +                    && (!(obj instanceof Proxy))
  +                    && (ref != null)
  +                    && (!(ref instanceof VirtualProxy)))
  +            {
  +                Identity refOID = new Identity(ref, getBroker());
  +                Object[] refPkValues = refOID.getPrimaryKeyValues();
  +
  +                ClassDescriptor objCld = this.getBroker().getClassDescriptor(obj.getClass());
  +                org.apache.ojb.broker.metadata.FieldDescriptor[] objFkFields = rds.getForeignKeyFieldDescriptors(objCld);
  +                /**
  +                 * MBAIRD:
  +                 * objFkFields could end up being null in case of non-mapped indirection table of m:n relationship
  +                 *
  +                 */
  +                if (objFkFields != null)
  +                {
  +                    org.apache.ojb.broker.metadata.FieldDescriptor fld = null;
  +                    for (int i = 0; i < objFkFields.length; i++)
  +                    {
  +                        fld = objFkFields[i];
  +                        fld.getPersistentField().set(obj, refPkValues[i]);
  +                    }
  +                }
  +            }
  +        }
  +        catch (Throwable t)
  +        {
  +            throw new PersistenceBrokerException(t);
  +        }
  +    }
  +
  +    /**
  +     * 	assigns all foreign key attributes of the Object obj.
  +     *  used during store(obj, boolean);
  +     */
  +    private void assignReferenceFKs(Object obj, Vector vecRds) throws PersistenceBrokerException
  +    {
  +        try
  +        {
  +            // get all members of obj that are references and assign FKs
  +            Iterator i = vecRds.iterator();
  +            while (i.hasNext())
  +            {
  +                ObjectReferenceDescriptor rds = (ObjectReferenceDescriptor) i.next();
  +                Object ref = rds.getPersistentField().get(obj);
  +                assertFkAssignment(obj, ref, rds);
  +            }
  +        }
  +        catch (Throwable t)
  +        {
  +            throw new PersistenceBrokerException(t);
  +        }
  +    }
  +
  +    private void lockCollections(ClassDescriptor cld, Object newTxObject, int lockMode)
  +            throws PersistenceBrokerException
  +    {
  +        Iterator i;
  +        i = cld.getCollectionDescriptors().iterator();
  +        while (i.hasNext())
  +        {
  +            CollectionDescriptor cds = (CollectionDescriptor) i.next();
  +            Object col = cds.getPersistentField().get(newTxObject);
  +            if (col != null)
  +            {
  +                Iterator colIterator;
  +                if (col instanceof ManageableCollection)
  +                {
  +                    colIterator = ((ManageableCollection) col).ojbIterator();
  +                }
  +                else if (col instanceof Collection)
  +                {
  +                    colIterator = ((Collection) col).iterator();
  +                }
  +                else if (col.getClass().isArray())
  +                {
  +                    colIterator = new ArrayIterator(col);
  +                }
  +                else
  +                {
  +                    throw new RuntimeException(
  +                            col.getClass()
  +                            + " can not be managed by OJB, use Array, Collection or ManageableCollection instead !");
  +                }
  +
  +                // get foreign info for collection elements
  +                ClassDescriptor itemCld = this.getBroker().getClassDescriptor(cds.getItemClass());
  +                Object[] objPkValues = cld.getKeyValues(newTxObject);
  +                FieldDescriptor[] itemFkFields = cds.getForeignKeyFieldDescriptors(itemCld);
  +                /**
  +                 * itemFkFields will be null in the case of many to many relationships.
  +                 */
  +                if (itemFkFields != null)
  +                {
  +                    while (colIterator.hasNext())
  +                    {
  +                        Object item = colIterator.next();
  +                        if (Proxy.isProxyClass(item.getClass()))
  +                        {
  +                            IndirectionHandler handler = (IndirectionHandler) Proxy.getInvocationHandler(item);
  +                            if (!handler.alreadyMaterialized())
  +                            {
  +                                continue;
  +                            }
  +                            else
  +                            {
  +                                item = handler.getRealSubject();
  +                            }
  +                        }
  +                        if (item instanceof VirtualProxy)
  +                        {
  +                            VirtualProxy proxy = (VirtualProxy) item;
  +                            if (!proxy.alreadyMaterialized())
  +                            {
  +                                continue;
  +                            }
  +                            else
  +                            {
  +                                item = proxy.getRealSubject();
  +                            }
  +                        }
  +                        //if itemCld refers to an interface the foreignKeyFieldDescriptors
  +                        //have to be computed again for each concrete class
  +                        if (itemCld.isInterface())
  +                        {
  +                            ClassDescriptor concreteItemCld = getBroker().getClassDescriptor(item.getClass());
  +                            itemFkFields = cds.getForeignKeyFieldDescriptors(concreteItemCld);
  +                        }
  +                        // provide all items in collection attributes
  +                        // with foreign key information before locking them!
  +                        for (int j = 0; j < itemFkFields.length; j++)
  +                        {
  +                            FieldDescriptor fld = itemFkFields[j];
  +                            fld.getPersistentField().set(item, objPkValues[j]);
  +                        }
  +                        lock(item, lockMode);
  +                    }
  +                }
  +                else
  +                {
  +                    //objects of m:n-relations have to be locked as well
  +                    while (colIterator.hasNext())
  +                    {
  +                        Object item = colIterator.next();
  +                        lock(item, lockMode);
  +                    }
  +                }
  +            }
  +        }
  +    }
  +
  +    /**
  +     * we only use the registeredForLock map if the object is not a proxy. During the
  +     * reference locking, we will materialize objects and they will enter the registered for
  +     * lock map.
  +     */
  +    private void lockReferences(ClassDescriptor cld, Object newTxObject, int lockMode)
  +            throws PersistenceBrokerException
  +    {
  +        if ((newTxObject != null)
  +                && !(newTxObject instanceof VirtualProxy)
  +                && !(newTxObject instanceof Proxy))
  +            registeredForLock.put(newTxObject, newTxObject);
  +        Iterator i = cld.getObjectReferenceDescriptors().iterator();
  +        while (i.hasNext())
  +        {
  +            ObjectReferenceDescriptor rds = (ObjectReferenceDescriptor) i.next();
  +            Object refObj = rds.getPersistentField().get(newTxObject);
  +            if (refObj != null)
  +            {
  +                if ((refObj instanceof VirtualProxy) || (refObj instanceof Proxy))
  +                    lock(refObj, lockMode);
  +                else if (!registeredForLock.containsKey(refObj))
  +                {
  +                    lock(refObj, lockMode);
  +                }
  +            }
  +        }
  +    }
  +
  +    /**
  +     * lookup an identity from the transactions temporary nrm table.
  +     * @param name - the name to lookup.
  +     * @return Identity - the found Identity or null if name not defined.
  +     */
  +    Identity getNrmEntry(String name)
  +    {
  +        return (Identity) myNrm.get(name);
  +    }
  +
  +    /**
  +     * make a binding name/identity to the transactions temporary nrm table.
  +     * @param key - the identifying name
  +     * @param value the Identity to store
  +     */
  +    void putNrmEntry(String key, Identity value)
  +    {
  +        myNrm.put(key, value);
  +    }
  +
  +    /**
  +     * unbind an entry from the transactions temporary nrm table.
  +     * @param key - the identifying string whose entry is to be deleted.
  +     */
  +    boolean unbindNrmEntry(String key)
  +    {
  +        // remove from envelopeTable to prevent commit of old entry on tx commit!
  +        Identity oid = (Identity) myNrm.get(key);
  +        if (oid != null)
  +        {
  +            objectEnvelopeTable.remove(oid);
  +        }
  +
  +        // remove from transient NRM
  +        if (myNrm.remove(key) == null)
  +            return false;
  +        else
  +            return true;
  +    }
  +
  +    /**
  +     *  this callback is invoked before an Object is materialized
  +     *  within an IndirectionHandler.
  +     *  @param handler the invoking handler
  +     *  @param oid the identity of the object to be materialized
  +     */
  +    public void beforeMaterialization(IndirectionHandler handler, Identity oid)
  +    {
  +        //noop
  +    }
  +
  +    /**
  +     *  this callback is invoked after an Object is materialized
  +     *  within an IndirectionHandler.
  +     *  this callback allows to defer registration of objects until
  +     *  it's really neccessary.
  +     *  @param handler the invoking handler
  +     *  @param materializedObject the materialized Object
  +     */
  +    public void afterMaterialization(IndirectionHandler handler, Object materializedObject)
  +    {
  +        if (log.isDebugEnabled())
  +            log.debug("deferred registration: " + new Identity(materializedObject, getBroker()).toString());
  +        try
  +        {
  +            register(materializedObject, READ);
  +        }
  +        catch (Throwable t)
  +        {
  +            log.error("Register materialized object with this tx failed", t);
  +            throw new LockNotGrantedException(t.getMessage());
  +        }
  +        unregisterFromIndirectionHandler(handler);
  +    }
  +
  +    protected synchronized void unRegisterFromAllIndirectionHandlers()
  +    {
  +        // unregistering manipulates the registeredIndirectionHandlers vector
  +        // we have to loop through this vector to avoid index proplems.
  +        for (int i = registeredIndirectionHandlers.size() - 1; i >= 0; i--)
  +        {
  +            unregisterFromIndirectionHandler((IndirectionHandler) registeredIndirectionHandlers.get(i));
  +        }
  +    }
  +
  +    protected synchronized void unregisterFromIndirectionHandler(IndirectionHandler handler)
  +    {
  +        handler.removeListener(this);
  +        registeredIndirectionHandlers.remove(handler);
  +    }
  +
  +    protected synchronized void registerToIndirectionHandler(IndirectionHandler handler)
  +    {
  +        handler.addListener(this);
  +        registeredIndirectionHandlers.add(handler);
  +    }
  +
  +    /**
  +     * register proxy objects that were locked but haven't been materialized yet
  +     * so they can be unlocked when closing the transaction
  +     */
  +    protected void registerUnmaterializedLocks(Object obj)
  +    {
  +        unmaterializedLocks.add(obj);
  +    }
  +
  +    /**
  +     * Gets the broker associated with the transaction.
  +     * MBAIRD: only return the associated broker if the transaction is open,
  +     * if it's closed, throw a TransactionNotInProgressException. If we allow
  +     * brokers to be reaquired by an already closed transaction, there is a
  +     * very good chance the broker will be leaked as the doClose() method of
  +     * transactionImpl will never be called and thus the broker will never
  +     * be closed and returned to the pool.
  +     * @return Returns a PersistenceBroker
  +     * @throws TransactionNotInProgressException is the transaction is not open;
  +     */
  +    public PersistenceBroker getBroker()
  +    {
  +        if (broker == null)
  +        {
  +            if (this.isOpen())
  +            {
  +                try
  +                {
  +                    checkForDB();
  +                    broker = PersistenceBrokerFactory.createPersistenceBroker(curDB.getPBKey());
  +                }
  +                catch (PBFactoryException e)
  +                {
  +                    log.error("Cannot obtain PersistenceBroker from PersistenceBrokerFactory, " +
  +                            "found PBKey was " + curDB.getPBKey(), e);
  +                    throw new PersistenceBrokerException(e);
  +                }
  +            }
  +            else
  +            {
  +                throw new TransactionNotInProgressException(
  +                        "Cannot obtain a broker from a transaction that is not open. TX Status: " +
  +                        TxUtil.getStatusString(getStatus()));
  +            }
  +        }
  +        return broker;
  +    }
  +
  +    /*
  +     * @see Configurable#configure(Configuration)
  +     */
  +    public void configure(Configuration config) throws ConfigurationException
  +    {
  +        OdmgConfiguration odmgConfig = (OdmgConfiguration) config;
  +
  +        useWriteLocks = odmgConfig.lockAssociationAsWrites();
  +        useImplicitLocking = odmgConfig.useImplicitLocking();
  +        useBatchMode = odmgConfig.useBatchMode();
  +    }
  +
  +// arminw: commented out unused methods
  +//    private void internalBegin()
  +//    {
  +//
  +//    }
  +//
  +//    private void internalCommit()
  +//    {
  +//
  +//    }
  +//
  +//    private void internalClose()
  +//    {
  +//
  +//    }
  +//
  +//    private void internalPrepare()
  +//    {
  +//
  +//    }
  +
  +}
  
  
  

Mime
View raw message