db-ojb-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From t...@apache.org
Subject cvs commit: jakarta-ojb/src/java/org/apache/ojb/odmg TransactionImpl.java
Date Sat, 30 Nov 2002 17:36:28 GMT
thma        2002/11/30 09:36:28

  Modified:    src/java/org/apache/ojb/odmg TransactionImpl.java
  Log:
  add accept locks attribute to class-descriptor
  
  Revision  Changes    Path
  1.27      +1132 -1119jakarta-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.26
  retrieving revision 1.27
  diff -u -r1.26 -r1.27
  --- TransactionImpl.java	28 Nov 2002 17:14:18 -0000	1.26
  +++ TransactionImpl.java	30 Nov 2002 17:36:28 -0000	1.27
  @@ -1,167 +1,167 @@
  -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.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;
  +    }
  +
       /**
        * Returns the associated database
        */
  @@ -170,958 +170,971 @@
           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
  -    {
  -        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;
  +        // 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()
  +//    {
  +//
  +//    }
  +
  +}
  
  
  

Mime
View raw message