You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openjpa.apache.org by de...@apache.org on 2009/12/14 17:55:05 UTC

svn commit: r890402 [2/3] - in /openjpa/branches/1.1.x: openjpa-kernel/src/main/java/org/apache/openjpa/kernel/ openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/generationtype/ openjpa-persistence-jdbc/src/test/java/org/apache/open...

Modified: openjpa/branches/1.1.x/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/BrokerImpl.java
URL: http://svn.apache.org/viewvc/openjpa/branches/1.1.x/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/BrokerImpl.java?rev=890402&r1=890401&r2=890402&view=diff
==============================================================================
--- openjpa/branches/1.1.x/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/BrokerImpl.java (original)
+++ openjpa/branches/1.1.x/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/BrokerImpl.java Mon Dec 14 16:55:04 2009
@@ -1,4755 +1,4771 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.    
- */
-package org.apache.openjpa.kernel;
-
-import java.io.IOException;
-import java.io.ObjectInputStream;
-import java.io.ObjectOutputStream;
-import java.io.Serializable;
-import java.lang.reflect.Modifier;
-import java.security.AccessController;
-import java.util.AbstractCollection;
-import java.util.ArrayList;
-import java.util.BitSet;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import javax.transaction.Status;
-import javax.transaction.Synchronization;
-
-import org.apache.commons.collections.iterators.IteratorChain;
-import org.apache.commons.collections.map.IdentityMap;
-import org.apache.commons.collections.map.LinkedMap;
-import org.apache.commons.collections.set.MapBackedSet;
-import org.apache.openjpa.conf.Compatibility;
-import org.apache.openjpa.conf.OpenJPAConfiguration;
-import org.apache.openjpa.datacache.DataCache;
-import org.apache.openjpa.ee.ManagedRuntime;
-import org.apache.openjpa.enhance.PCRegistry;
-import org.apache.openjpa.enhance.PersistenceCapable;
-import org.apache.openjpa.event.LifecycleEvent;
-import org.apache.openjpa.event.LifecycleEventManager;
-import org.apache.openjpa.event.RemoteCommitEventManager;
-import org.apache.openjpa.event.TransactionEvent;
-import org.apache.openjpa.event.TransactionEventManager;
-import org.apache.openjpa.kernel.exps.ExpressionParser;
-import org.apache.openjpa.lib.log.Log;
-import org.apache.openjpa.lib.util.J2DoPrivHelper;
-import org.apache.openjpa.lib.util.Localizer;
-import org.apache.openjpa.lib.util.ReferenceHashMap;
-import org.apache.openjpa.lib.util.ReferenceHashSet;
-import org.apache.openjpa.lib.util.ReferenceMap;
-import java.util.concurrent.locks.ReentrantLock;
-import org.apache.openjpa.meta.ClassMetaData;
-import org.apache.openjpa.meta.FieldMetaData;
-import org.apache.openjpa.meta.MetaDataRepository;
-import org.apache.openjpa.meta.SequenceMetaData;
-import org.apache.openjpa.meta.ValueMetaData;
-import org.apache.openjpa.meta.ValueStrategies;
-import org.apache.openjpa.util.ApplicationIds;
-import org.apache.openjpa.util.CallbackException;
-import org.apache.openjpa.util.Exceptions;
-import org.apache.openjpa.util.GeneralException;
-import org.apache.openjpa.util.ImplHelper;
-import org.apache.openjpa.util.InternalException;
-import org.apache.openjpa.util.InvalidStateException;
-import org.apache.openjpa.util.NoTransactionException;
-import org.apache.openjpa.util.ObjectExistsException;
-import org.apache.openjpa.util.ObjectId;
-import org.apache.openjpa.util.ObjectNotFoundException;
-import org.apache.openjpa.util.OpenJPAException;
-import org.apache.openjpa.util.OptimisticException;
-import org.apache.openjpa.util.RuntimeExceptionTranslator;
-import org.apache.openjpa.util.StoreException;
-import org.apache.openjpa.util.UnsupportedException;
-import org.apache.openjpa.util.UserException;
-
-/**
- * Concrete {@link Broker}. The broker handles object-level behavior,
- * but leaves all interaction with the data store to a {@link StoreManager}
- * that must be supplied at initialization.
- *
- * @author Abe White
- */
-public class BrokerImpl
-    implements Broker, FindCallbacks, Cloneable, Serializable {
-
-    /**
-     * Incremental flush.
-     */
-    protected static final int FLUSH_INC = 0;
-
-    /**
-     * Flush in preparation of commit.
-     */
-    protected static final int FLUSH_COMMIT = 1;
-
-    /**
-     * Flush to check consistency of cache, then immediately rollback changes.
-     */
-    protected static final int FLUSH_ROLLBACK = 2;
-
-    /**
-     * Run persistence-by-reachability and other flush-time operations without
-     * accessing the database.
-     */
-    protected static final int FLUSH_LOGICAL = 3;
-
-    static final int STATUS_INIT = 0;
-    static final int STATUS_TRANSIENT = 1;
-    static final int STATUS_OID_ASSIGN = 2;
-    static final int STATUS_COMMIT_NEW = 3;
-
-    private static final int FLAG_ACTIVE = 2 << 0;
-    private static final int FLAG_STORE_ACTIVE = 2 << 1;
-    private static final int FLAG_CLOSE_INVOKED = 2 << 2;
-    private static final int FLAG_PRESTORING = 2 << 3;
-    private static final int FLAG_DEREFDELETING = 2 << 4;
-    private static final int FLAG_FLUSHING = 2 << 5;
-    private static final int FLAG_STORE_FLUSHING = 2 << 6;
-    private static final int FLAG_FLUSHED = 2 << 7;
-    private static final int FLAG_FLUSH_REQUIRED = 2 << 8;
-    private static final int FLAG_REMOTE_LISTENER = 2 << 9;
-    private static final int FLAG_RETAINED_CONN = 2 << 10;
-    private static final int FLAG_TRANS_ENDING = 2 << 11;
-
-    private static final Object[] EMPTY_OBJECTS = new Object[0];
-
-    private static final Localizer _loc =
-        Localizer.forPackage(BrokerImpl.class);
-
-    //	the store manager in use; this may be a decorator such as a
-    //	data cache store manager around the native store manager
-    private transient DelegatingStoreManager _store = null;
-
-    private FetchConfiguration _fc = null;
-    private String _user = null;
-    private String _pass = null;
-
-    // these must be rebuilt by the facade layer during its deserialization
-    private transient Log _log = null;
-    private transient Compatibility _compat = null;
-    private transient ManagedRuntime _runtime = null;
-    private transient LockManager _lm = null;
-    private transient InverseManager _im = null;
-    private transient ReentrantLock _lock = null;
-    private transient OpCallbacks _call = null;
-    private transient RuntimeExceptionTranslator _extrans = null;
-
-    // ref to producing factory and configuration
-    private transient AbstractBrokerFactory _factory = null;
-    private transient OpenJPAConfiguration _conf = null;
-
-    // cache class loader associated with the broker
-    private transient ClassLoader _loader = null;
-
-    // user state
-    private Synchronization _sync = null;
-    private Map _userObjects = null;
-
-    // managed object caches
-    private ManagedCache _cache = null;
-    private TransactionalCache _transCache = null;
-    private Set _transAdditions = null;
-    private Set _derefCache = null;
-    private Set _derefAdditions = null;
-
-    // these are used for method-internal state only
-    private transient Map _loading = null;
-    private transient Set _operating = null;
-
-    private Set _persistedClss = null;
-    private Set _updatedClss = null;
-    private Set _deletedClss = null;
-    private Set _pending = null;
-    private int findAllDepth = 0;
-
-    // track instances that become transactional after the first savepoint
-    // (the first uses the transactional cache)
-    private Set _savepointCache = null;
-    private LinkedMap _savepoints = null;
-    private transient SavepointManager _spm = null;
-
-    // track open queries and extents so we can free their resources on close
-    private transient ReferenceHashSet _queries = null;
-    private transient ReferenceHashSet _extents = null;
-
-    // track operation stack depth. Transient because operations cannot
-    // span serialization.
-    private transient int _operationCount = 0;
-
-    // options
-    private boolean _nontransRead = false;
-    private boolean _nontransWrite = false;
-    private boolean _retainState = false;
-    private int _autoClear = CLEAR_DATASTORE;
-    private int _restoreState = RESTORE_IMMUTABLE;
-    private boolean _optimistic = false;
-    private boolean _ignoreChanges = false;
-    private boolean _multithreaded = false;
-    private boolean _managed = false;
-    private boolean _syncManaged = false;
-    private int _connRetainMode = CONN_RETAIN_DEMAND;
-    private boolean _evictDataCache = false;
-    private boolean _populateDataCache = true;
-    private boolean _largeTransaction = false;
-    private int _autoDetach = 0;
-    private int _detachState = DETACH_LOADED;
-    private boolean _detachedNew = true;
-    private boolean _orderDirty = false;
-
-    // status
-    private int _flags = 0;
-
-    // this is not in status because it should not be serialized
-    private transient boolean _isSerializing = false;
-
-    // transient because closed brokers can't be serialized
-    private transient boolean _closed = false;
-    private transient RuntimeException _closedException = null;
-
-    // event managers
-    private TransactionEventManager _transEventManager = null;
-    private int _transCallbackMode = 0;
-    private LifecycleEventManager _lifeEventManager = null;
-    private int _lifeCallbackMode = 0;
-
-    private transient boolean _initializeWasInvoked = false;
-    private LinkedList _fcs;
-
-    /**
-     * Set the persistence manager's authentication. This is the first
-     * method called after construction.
-     *
-     * @param user the username this broker represents; used when pooling
-     * brokers to make sure that a request to the factory for
-     * a connection with an explicit user is delegated to a suitable broker
-     * @param pass the password for the above user
-     */
-    public void setAuthentication(String user, String pass) {
-        _user = user;
-        _pass = pass;
-    }
-
-    /**
-     * Initialize the persistence manager. This method is called
-     * automatically by the factory before use.
-     *
-     * @param factory the factory used to create this broker
-     * @param sm a concrete StoreManager implementation to
-     * handle interaction with the data store
-     * @param managed the transaction mode
-     * @param connMode the connection retain mode
-     * @param fromDeserialization whether this call happened because of a
-     * deserialization or creation of a new BrokerImpl.
-     */
-    public void initialize(AbstractBrokerFactory factory,
-        DelegatingStoreManager sm, boolean managed, int connMode,
-        boolean fromDeserialization) {
-        _initializeWasInvoked = true;
-        _loader = (ClassLoader) AccessController.doPrivileged(
-            J2DoPrivHelper.getContextClassLoaderAction());
-        if (!fromDeserialization)
-            _conf = factory.getConfiguration();
-        _compat = _conf.getCompatibilityInstance();
-        _factory = factory;
-        _log = _conf.getLog(OpenJPAConfiguration.LOG_RUNTIME);
-        if (!fromDeserialization)
-            _cache = new ManagedCache(this);
-        initializeOperatingSet();
-        _connRetainMode = connMode;
-        _managed = managed;
-        if (managed)
-            _runtime = _conf.getManagedRuntimeInstance();
-        else
-            _runtime = new LocalManagedRuntime(this);
-
-        if (!fromDeserialization) {
-            _lifeEventManager = new LifecycleEventManager();
-            _transEventManager = new TransactionEventManager();
-            int cmode = _conf.getMetaDataRepositoryInstance().
-                getMetaDataFactory().getDefaults().getCallbackMode();
-            setLifecycleListenerCallbackMode(cmode);
-            setTransactionListenerCallbackMode(cmode);
-
-            // setup default options
-            _factory.configureBroker(this);
-        }
-
-        // make sure to do this after configuring broker so that store manager
-        // can look to broker configuration; we set both store and lock managers
-        // before initializing them because they may each try to access the
-        // other in thier initialization
-        _store = sm;
-        _lm = _conf.newLockManagerInstance();
-        _im = _conf.newInverseManagerInstance();
-        _spm = _conf.getSavepointManagerInstance();
-        _store.setContext(this);
-        _lm.setContext(this);
-
-        if (_connRetainMode == CONN_RETAIN_ALWAYS)
-            retainConnection();
-        if (!fromDeserialization) {
-            _fc = _store.newFetchConfiguration();
-            _fc.setContext(this);
-        }
-
-        // synch with the global transaction in progress, if any
-        if (_factory.syncWithManagedTransaction(this, false))
-            beginInternal();
-    }
-
-    private void initializeOperatingSet() {
-        _operating = MapBackedSet.decorate(new IdentityMap());
-    }
-    
-    /**
-     * Gets the unmodifiable set of instances being operated.
-     */
-    protected Set getOperatingSet() {
-    	return Collections.unmodifiableSet(_operating);
-    }
-
-    public Object clone()
-        throws CloneNotSupportedException {
-        if (_initializeWasInvoked)
-            throw new CloneNotSupportedException();
-        else {
-            return super.clone();
-        }
-    }
-
-    /**
-     * Create a {@link Map} to be used for the primary managed object cache.
-     * Maps oids to state managers. By default, this creates a
-     * {@link ReferenceMap} with soft values.
-     */
-    protected Map newManagedObjectCache() {
-        return new ReferenceHashMap(ReferenceMap.HARD, ReferenceMap.SOFT);
-    }
-
-    //////////////////////////////////
-    // Implementation of StoreContext
-    //////////////////////////////////
-
-    public Broker getBroker() {
-        return this;
-    }
-
-    //////////////
-    // Properties
-    //////////////
-
-    public void setImplicitBehavior(OpCallbacks call,
-        RuntimeExceptionTranslator ex) {
-        if (_call == null)
-            _call = call;
-        if (_extrans == null)
-            _extrans = ex;
-    }
-
-    RuntimeExceptionTranslator getInstanceExceptionTranslator() {
-        return (_operationCount == 0) ? _extrans : null;
-    }
-
-    public BrokerFactory getBrokerFactory() {
-        return _factory;
-    }
-
-    public OpenJPAConfiguration getConfiguration() {
-        return _conf;
-    }
-
-    public FetchConfiguration getFetchConfiguration() {
-        return _fc;
-    }
-
-    public FetchConfiguration pushFetchConfiguration() {
-        if (_fcs == null)
-            _fcs = new LinkedList();
-        _fcs.add(_fc);
-        _fc = (FetchConfiguration) _fc.clone();
-        return _fc;
-    }
-
-    public void popFetchConfiguration() {
-        if (_fcs == null || _fcs.isEmpty())
-            throw new UserException(_loc.get("fetch-configuration-stack-empty"));
-        _fc = (FetchConfiguration) _fcs.removeLast();
-    }
-
-    public int getConnectionRetainMode() {
-        return _connRetainMode;
-    }
-
-    public boolean isManaged() {
-        return _managed;
-    }
-
-    public ManagedRuntime getManagedRuntime() {
-        return _runtime;
-    }
-
-    public ClassLoader getClassLoader() {
-        return _loader;
-    }
-
-    public DelegatingStoreManager getStoreManager() {
-        return _store;
-    }
-
-    public LockManager getLockManager() {
-        return _lm;
-    }
-
-    public InverseManager getInverseManager() {
-        return _im;
-    }
-
-    public String getConnectionUserName() {
-        return _user;
-    }
-
-    public String getConnectionPassword() {
-        return _pass;
-    }
-
-    public boolean getMultithreaded() {
-        return _multithreaded;
-    }
-
-    public void setMultithreaded(boolean multithreaded) {
-        assertOpen();
-        _multithreaded = multithreaded;
-        if (multithreaded && _lock == null)
-            _lock = new ReentrantLock();
-        else if (!multithreaded)
-            _lock = null;
-    }
-
-    public boolean getIgnoreChanges() {
-        return _ignoreChanges;
-    }
-
-    public void setIgnoreChanges(boolean val) {
-        assertOpen();
-        _ignoreChanges = val;
-    }
-
-    public boolean getNontransactionalRead() {
-        return _nontransRead;
-    }
-
-    public void setNontransactionalRead(boolean val) {
-        assertOpen();
-        if ((_flags & FLAG_PRESTORING) != 0)
-            throw new UserException(_loc.get("illegal-op-in-prestore"));
-
-        // make sure the runtime supports it
-        if (val && !_conf.supportedOptions().contains
-            (_conf.OPTION_NONTRANS_READ))
-            throw new UnsupportedException(_loc.get
-                ("nontrans-read-not-supported"));
-
-        _nontransRead = val;
-    }
-
-    public boolean getNontransactionalWrite() {
-        return _nontransWrite;
-    }
-
-    public void setNontransactionalWrite(boolean val) {
-        assertOpen();
-        if ((_flags & FLAG_PRESTORING) != 0)
-            throw new UserException(_loc.get("illegal-op-in-prestore"));
-
-        _nontransWrite = val;
-    }
-
-    public boolean getOptimistic() {
-        return _optimistic;
-    }
-
-    public void setOptimistic(boolean val) {
-        assertOpen();
-        if ((_flags & FLAG_ACTIVE) != 0)
-            throw new InvalidStateException(_loc.get("trans-active",
-                "Optimistic"));
-
-        // make sure the runtime supports it
-        if (val && !_conf.supportedOptions().contains(_conf.OPTION_OPTIMISTIC))
-            throw new UnsupportedException(_loc.get
-                ("optimistic-not-supported"));
-
-        _optimistic = val;
-    }
-
-    public int getRestoreState() {
-        return _restoreState;
-    }
-
-    public void setRestoreState(int val) {
-        assertOpen();
-        if ((_flags & FLAG_ACTIVE) != 0)
-            throw new InvalidStateException(_loc.get("trans-active",
-                "Restore"));
-
-        _restoreState = val;
-    }
-
-    public boolean getRetainState() {
-        return _retainState;
-    }
-
-    public void setRetainState(boolean val) {
-        assertOpen();
-        if ((_flags & FLAG_PRESTORING) != 0)
-            throw new UserException(_loc.get("illegal-op-in-prestore"));
-        _retainState = val;
-    }
-
-    public int getAutoClear() {
-        return _autoClear;
-    }
-
-    public void setAutoClear(int val) {
-        assertOpen();
-        _autoClear = val;
-    }
-
-    public int getAutoDetach() {
-        return _autoDetach;
-    }
-
-    public void setAutoDetach(int detachFlags) {
-        assertOpen();
-        _autoDetach = detachFlags;
-    }
-
-    public void setAutoDetach(int detachFlag, boolean on) {
-        assertOpen();
-        if (on)
-            _autoDetach |= detachFlag;
-        else
-            _autoDetach &= ~detachFlag;
-    }
-
-    public int getDetachState() {
-        return _detachState;
-    }
-
-    public void setDetachState(int mode) {
-        assertOpen();
-        _detachState = mode;
-    }
-
-    public boolean isDetachedNew() {
-        return _detachedNew;
-    }
-
-    public void setDetachedNew(boolean isNew) {
-        assertOpen();
-        _detachedNew = isNew;
-    }
-
-    public boolean getSyncWithManagedTransactions() {
-        return _syncManaged;
-    }
-
-    public void setSyncWithManagedTransactions(boolean sync) {
-        assertOpen();
-        _syncManaged = sync;
-    }
-
-    public boolean getEvictFromDataCache() {
-        return _evictDataCache;
-    }
-
-    public void setEvictFromDataCache(boolean evict) {
-        assertOpen();
-        _evictDataCache = evict;
-    }
-
-    public boolean getPopulateDataCache() {
-        return _populateDataCache;
-    }
-
-    public void setPopulateDataCache(boolean cache) {
-        assertOpen();
-        _populateDataCache = cache;
-    }
-
-    public boolean isTrackChangesByType() {
-        return _largeTransaction;
-    }
-
-    public void setTrackChangesByType(boolean largeTransaction) {
-        assertOpen();
-        _largeTransaction = largeTransaction;
-    }
-
-    public Object getUserObject(Object key) {
-        beginOperation(false);
-        try {
-            return (_userObjects == null) ? null : _userObjects.get(key);
-        } finally {
-            endOperation();
-        }
-    }
-
-    public Object putUserObject(Object key, Object val) {
-        beginOperation(false);
-        try {
-            if (val == null)
-                return (_userObjects == null) ? null : _userObjects.remove(key);
-
-            if (_userObjects == null)
-                _userObjects = new HashMap();
-            return _userObjects.put(key, val);
-        } finally {
-            endOperation();
-        }
-    }
-
-    //////////
-    // Events
-    //////////
-
-    public void addLifecycleListener(Object listener, Class[] classes) {
-        beginOperation(false);
-        try {
-            _lifeEventManager.addListener(listener, classes);
-        } finally {
-            endOperation();
-        }
-    }
-
-    public void removeLifecycleListener(Object listener) {
-        beginOperation(false);
-        try {
-            _lifeEventManager.removeListener(listener);
-        } finally {
-            endOperation();
-        }
-    }
-
-    public int getLifecycleListenerCallbackMode() {
-        return _lifeCallbackMode;
-    }
-
-    public void setLifecycleListenerCallbackMode(int mode) {
-        beginOperation(false);
-        try {
-            _lifeCallbackMode = mode;
-            _lifeEventManager.setFailFast((mode & CALLBACK_FAIL_FAST) != 0);
-        } finally {
-            endOperation();
-        }
-    }
-
-    /**
-     * Give state managers access to the lifecycle event manager.
-     */
-    public LifecycleEventManager getLifecycleEventManager() {
-        return _lifeEventManager;
-    }
-
-    /**
-     * Fire given lifecycle event, handling any exceptions appropriately.
-     *
-     * @return whether events are being processed at this time
-     */
-    boolean fireLifecycleEvent(Object src, Object related, ClassMetaData meta,
-        int eventType) {
-        if (_lifeEventManager == null)
-            return false;
-
-        lock();
-        Exception[] exs;
-        try {
-            exs = _lifeEventManager.fireEvent(src, related, meta, eventType);
-        } finally {
-            unlock();
-        } 
-        handleCallbackExceptions(exs, _lifeCallbackMode);
-        return true;
-    }
-
-    /**
-     * Take actions on callback exceptions depending on callback mode.
-     */
-    private void handleCallbackExceptions(Exception[] exceps, int mode) {
-        if (exceps.length == 0 || (mode & CALLBACK_IGNORE) != 0)
-            return;
-
-        OpenJPAException ce;
-        if (exceps.length == 1)
-            ce = new CallbackException(exceps[0]);
-        else 
-            ce = new CallbackException(_loc.get("callback-err")).
-                setNestedThrowables(exceps);
-        if ((mode & CALLBACK_ROLLBACK) != 0 && (_flags & FLAG_ACTIVE) != 0) {
-            ce.setFatal(true);
-            setRollbackOnlyInternal(ce);
-        }
-        if ((mode & CALLBACK_LOG) != 0 && _log.isWarnEnabled())
-            _log.warn(ce);
-        if ((mode & CALLBACK_RETHROW) != 0)
-            throw ce;
-    }
-
-    public void addTransactionListener(Object tl) {
-        beginOperation(false);
-        try {
-            _transEventManager.addListener(tl);
-            if (tl instanceof RemoteCommitEventManager)
-                _flags |= FLAG_REMOTE_LISTENER;
-        } finally {
-            endOperation();
-        }
-    }
-
-    public void removeTransactionListener(Object tl) {
-        beginOperation(false);
-        try {
-            if (_transEventManager.removeListener(tl)
-                && (tl instanceof RemoteCommitEventManager))
-                _flags &= ~FLAG_REMOTE_LISTENER;
-        } finally {
-            endOperation();
-        }
-    }
-
-    public int getTransactionListenerCallbackMode() {
-        return _transCallbackMode;
-    }
-
-    public void setTransactionListenerCallbackMode(int mode) {
-        beginOperation(false);
-        try {
-            _transCallbackMode = mode;
-            _transEventManager.setFailFast((mode & CALLBACK_FAIL_FAST) != 0);
-        } finally {
-            endOperation();
-        }
-    }
-
-    /**
-     * Fire given transaction event, handling any exceptions appropriately.
-     */
-    private void fireTransactionEvent(TransactionEvent trans) {
-        if (_transEventManager != null)
-            handleCallbackExceptions(_transEventManager.fireEvent(trans),
-                _transCallbackMode);
-    }
-
-    ///////////
-    // Lookups
-    ///////////
-
-    public Object find(Object oid, boolean validate, FindCallbacks call) {
-        int flags = OID_COPY | OID_ALLOW_NEW | OID_NODELETED;
-        if (!validate)
-            flags |= OID_NOVALIDATE;
-        return find(oid, _fc, null, null, flags, call);
-    }
-
-    public Object find(Object oid, FetchConfiguration fetch, BitSet exclude,
-        Object edata, int flags) {
-        return find(oid, fetch, exclude, edata, flags, null);
-    }
-
-    /**
-     * Internal finder.
-     */
-    protected Object find(Object oid, FetchConfiguration fetch, BitSet exclude,
-        Object edata, int flags, FindCallbacks call) {
-        if (call == null)
-            call = this;
-        oid = call.processArgument(oid);
-        if (oid == null) {
-            if ((flags & OID_NOVALIDATE) == 0)
-                throw new ObjectNotFoundException(_loc.get("null-oid"));
-            return call.processReturn(oid, null);
-        }
-        if (fetch == null)
-            fetch = _fc;
-
-        beginOperation(true);
-        try {
-            assertNontransactionalRead();
-
-            // cached instance?
-            StateManagerImpl sm = getStateManagerImplById(oid,
-                (flags & OID_ALLOW_NEW) != 0 || hasFlushed());
-            if (sm != null) {
-                if (!requiresLoad(sm, true, fetch, edata, flags))
-                    return call.processReturn(oid, sm);
-
-                if (!sm.isLoading()) {
-                    // make sure all the configured fields are loaded; do this
-                    // after making instance transactional for locking
-                    if (!sm.isTransactional() && useTransactionalState(fetch))
-                        sm.transactional();
-                    boolean loaded;
-                    try {
-                        loaded = sm.load(fetch, StateManagerImpl.LOAD_FGS, 
-                            exclude, edata, false);
-                    } catch (ObjectNotFoundException onfe) {
-                        if ((flags & OID_NODELETED) != 0
-                            || (flags & OID_NOVALIDATE) != 0)
-                            throw onfe;
-                        return call.processReturn(oid, null);
-                    }
-
-                    // if no data needed to be loaded and the user wants to
-                    // validate, just make sure the object exists
-                    if (!loaded && (flags & OID_NOVALIDATE) == 0
-                        && _compat.getValidateTrueChecksStore()
-                        && !sm.isTransactional()
-                        && !_store.exists(sm, edata)) {
-                        if ((flags & OID_NODELETED) == 0)
-                            return call.processReturn(oid, null);
-                        throw new ObjectNotFoundException(_loc.get
-                            ("del-instance", sm.getManagedInstance(), oid)).
-                            setFailedObject(sm.getManagedInstance());
-                    }
-                }
-
-                // since the object was cached, we may need to upgrade lock
-                // if current level is higher than level of initial load
-                if ((_flags & FLAG_ACTIVE) != 0) {
-                    int level = fetch.getReadLockLevel();
-                    _lm.lock(sm, level, fetch.getLockTimeout(), edata);
-                    sm.readLocked(level, fetch.getWriteLockLevel());
-                }
-                return call.processReturn(oid, sm);
-            }
-
-            // if there's no cached sm for a new/transient id type, we
-            // it definitely doesn't exist
-            if (oid instanceof StateManagerId)
-                return call.processReturn(oid, null);
-
-            // initialize a new state manager for the datastore instance
-            sm = newStateManagerImpl(oid, (flags & OID_COPY) != 0);
-            boolean load = requiresLoad(sm, false, fetch, edata, flags);
-            sm = initialize(sm, load, fetch, edata);
-            if (sm == null) {
-                if ((flags & OID_NOVALIDATE) != 0)
-                    throw new ObjectNotFoundException(oid);
-                return call.processReturn(oid, null);
-            }
-
-            // make sure all configured fields were loaded
-            if (load) {
-                try {
-                    sm.load(fetch, StateManagerImpl.LOAD_FGS, exclude,
-                        edata, false);
-                } catch (ObjectNotFoundException onfe) {
-                    if ((flags & OID_NODELETED) != 0
-                        || (flags & OID_NOVALIDATE) != 0)
-                        throw onfe;
-                    return call.processReturn(oid, null);
-                }
-            }
-            return call.processReturn(oid, sm);
-        } catch (OpenJPAException ke) {
-            throw ke;
-        } catch (RuntimeException re) {
-            throw new GeneralException(re);
-        } finally {
-            endOperation();
-        }
-    }
-
-    /**
-     * Initialize a newly-constructed state manager.
-     */
-    protected StateManagerImpl initialize(StateManagerImpl sm, boolean load,
-        FetchConfiguration fetch, Object edata) {
-        if (!load) {
-            sm.initialize(sm.getMetaData().getDescribedType(),
-                PCState.HOLLOW);
-        } else {
-            PCState state = (useTransactionalState(fetch))
-                ? PCState.PCLEAN : PCState.PNONTRANS;
-            sm.setLoading(true);
-            try {
-                if (!_store.initialize(sm, state, fetch, edata))
-                    return null;
-            } finally {
-                sm.setLoading(false);
-            }
-        }
-        return sm;
-    }
-
-    public Object[] findAll(Collection oids, boolean validate,
-        FindCallbacks call) {
-        int flags = OID_COPY | OID_ALLOW_NEW | OID_NODELETED;
-        if (!validate)
-            flags |= OID_NOVALIDATE;
-        return findAll(oids, _fc, null, null, flags, call);
-    }
-
-    public Object[] findAll(Collection oids, FetchConfiguration fetch,
-        BitSet exclude, Object edata, int flags) {
-        return findAll(oids, fetch, exclude, edata, flags, null);
-    }
-
-    /**
-     * Internal finder.
-     */
-    protected Object[] findAll(Collection oids, FetchConfiguration fetch,
-        BitSet exclude, Object edata, int flags, FindCallbacks call) {
-        findAllDepth ++;
-
-        // throw any exceptions for null oids up immediately
-        if (oids == null)
-            throw new NullPointerException("oids == null");
-        if ((flags & OID_NOVALIDATE) != 0 && oids.contains(null))
-            throw new UserException(_loc.get("null-oids"));
-
-        // we have to use a map of oid->sm rather than a simple
-        // array, so that we make sure not to create multiple sms for equivalent
-        // oids if the user has duplicates in the given array
-        if (_loading == null)
-            _loading = new HashMap((int) (oids.size() * 1.33 + 1));
-
-        if (call == null)
-            call = this;
-        if (fetch == null)
-            fetch = _fc;
-
-        beginOperation(true);
-        try {
-            assertNontransactionalRead();
-
-            // collection of state managers to pass to store manager
-            List load = null;
-            StateManagerImpl sm;
-            boolean initialized;
-            boolean transState = useTransactionalState(fetch);
-            Object obj, oid;
-            int idx = 0;
-            for (Iterator itr = oids.iterator(); itr.hasNext(); idx++) {
-                // if we've already seen this oid, skip repeats
-                obj = itr.next();
-                oid = call.processArgument(obj);
-                if (oid == null || _loading.containsKey(obj))
-                    continue;
-
-                // if we don't have a cached instance or it is not transactional
-                // and is hollow or we need to validate, load it
-                sm = getStateManagerImplById(oid, (flags & OID_ALLOW_NEW) != 0
-                    || hasFlushed());
-                initialized = sm != null;
-                if (!initialized)
-                    sm = newStateManagerImpl(oid, (flags & OID_COPY) != 0);
-
-                _loading.put(obj, sm);
-                if (requiresLoad(sm, initialized, fetch, edata, flags)) {
-                    transState = transState || useTransactionalState(fetch);
-                    if (initialized && !sm.isTransactional() && transState)
-                        sm.transactional();
-                    if (load == null)
-                        load = new ArrayList(oids.size() - idx);
-                    load.add(sm);
-                } else if (!initialized)
-                    sm.initialize(sm.getMetaData().getDescribedType(),
-                        PCState.HOLLOW);
-            }
-
-            // pass all state managers in need of loading or validation to the
-            // store manager
-            if (load != null) {
-                PCState state = (transState) ? PCState.PCLEAN
-                    : PCState.PNONTRANS;
-                Collection failed = _store.loadAll(load, state,
-                    StoreManager.FORCE_LOAD_NONE, fetch, edata);
-
-                // set failed instances to null
-                if (failed != null && !failed.isEmpty()) {
-                    if ((flags & OID_NOVALIDATE) != 0)
-                        throw newObjectNotFoundException(failed);
-                    for (Iterator itr = failed.iterator(); itr.hasNext();)
-                        _loading.put(itr.next(), null);
-                }
-            }
-
-            // create results array; make sure all configured fields are
-            // loaded in each instance
-            Object[] results = new Object[oids.size()];
-            boolean active = (_flags & FLAG_ACTIVE) != 0;
-            int level = fetch.getReadLockLevel();
-            idx = 0;
-            for (Iterator itr = oids.iterator(); itr.hasNext(); idx++) {
-                oid = itr.next();
-                sm = (StateManagerImpl) _loading.get(oid);
-                if (sm != null && requiresLoad(sm, true, fetch, edata, flags)) {
-                    try {
-                        sm.load(fetch, StateManagerImpl.LOAD_FGS,
-                        	exclude, edata, false);
-                        if (active) {
-                            _lm.lock(sm, level, fetch.getLockTimeout(), edata);
-                            sm.readLocked(level, fetch.getWriteLockLevel());
-                        }
-                    }
-                    catch (ObjectNotFoundException onfe) {
-                        if ((flags & OID_NODELETED) != 0
-                            || (flags & OID_NOVALIDATE) != 0)
-                            throw onfe;
-                        sm = null;
-                    }
-                }
-                results[idx] = call.processReturn(oid, sm);
-            }
-            return results;
-        } catch (OpenJPAException ke) {
-            throw ke;
-        } catch (RuntimeException re) {
-            throw new GeneralException(re);
-        } finally {
-            findAllDepth--;
-            if (findAllDepth == 0)
-                _loading = null;
-            endOperation();
-        }
-    }
-
-    private boolean hasFlushed() {
-        return (_flags & FLAG_FLUSHED) != 0;
-    }
-
-    /**
-     * Return whether the given instance needs loading before being returned
-     * to the user.
-     */
-    private boolean requiresLoad(OpenJPAStateManager sm, boolean initialized,
-        FetchConfiguration fetch, Object edata, int flags) {
-        if (!fetch.requiresLoad())
-            return false;
-        if ((flags & OID_NOVALIDATE) == 0)
-            return true;
-        if (edata != null) // take advantage of existing result
-            return true;
-        if (initialized && sm.getPCState() != PCState.HOLLOW)
-            return false;
-        if (!initialized && sm.getMetaData().getPCSubclasses().length > 0)
-            return true;
-        return !_compat.getValidateFalseReturnsHollow();
-    }
-
-    /**
-     * Return whether to use a transactional state.
-     */
-    private boolean useTransactionalState(FetchConfiguration fetch) {
-        return (_flags & FLAG_ACTIVE) != 0 && (!_optimistic
-            || _autoClear == CLEAR_ALL
-            || fetch.getReadLockLevel() != LOCK_NONE);
-    }
-
-    public Object findCached(Object oid, FindCallbacks call) {
-        if (call == null)
-            call = this;
-        oid = call.processArgument(oid);
-        if (oid == null)
-            return call.processReturn(oid, null);
-
-        beginOperation(true);
-        try {
-            StateManagerImpl sm = getStateManagerImplById(oid, true);
-            return call.processReturn(oid, sm);
-        } finally {
-            endOperation();
-        }
-    }
-
-    public Class getObjectIdType(Class cls) {
-        if (cls == null)
-            return null;
-
-        beginOperation(false);
-        try {
-            ClassMetaData meta = _conf.getMetaDataRepositoryInstance().
-                getMetaData(cls, _loader, false);
-            if (meta == null
-                || meta.getIdentityType() == ClassMetaData.ID_UNKNOWN)
-                return null;
-            if (meta.getIdentityType() == ClassMetaData.ID_APPLICATION)
-                return meta.getObjectIdType();
-
-            return _store.getDataStoreIdType(meta);
-        } catch (OpenJPAException ke) {
-            throw ke;
-        } catch (RuntimeException re) {
-            throw new GeneralException(re);
-        } finally {
-            endOperation();
-        }
-    }
-
-    public Object newObjectId(Class cls, Object val) {
-        if (val == null)
-            return null;
-
-        beginOperation(false);
-        try {
-            ClassMetaData meta = _conf.getMetaDataRepositoryInstance().
-                getMetaData(cls, _loader, true);
-            switch (meta.getIdentityType()) {
-            case ClassMetaData.ID_DATASTORE:
-                // delegate to store manager for datastore ids
-                if (val instanceof String
-                    && ((String) val).startsWith(StateManagerId.STRING_PREFIX))
-                    return new StateManagerId((String) val);
-                return _store.newDataStoreId(val, meta);
-            case ClassMetaData.ID_APPLICATION:
-                if (ImplHelper.isAssignable(meta.getObjectIdType(), 
-                    val.getClass())) {
-                    if (!meta.isOpenJPAIdentity() 
-                        && meta.isObjectIdTypeShared())
-                        return new ObjectId(cls, val);
-                    return val;
-                }
-
-                // stringified app id?
-                if (val instanceof String 
-                    && !_conf.getCompatibilityInstance().
-                        getStrictIdentityValues()
-                    && !Modifier.isAbstract(cls.getModifiers()))
-                    return PCRegistry.newObjectId(cls, (String) val);
-
-                Object[] arr = (val instanceof Object[]) ? (Object[]) val
-                    : new Object[]{ val };
-                return ApplicationIds.fromPKValues(arr, meta);
-            default:
-                throw new UserException(_loc.get("meta-unknownid", cls));
-            }
-        } catch (IllegalArgumentException iae) {
-            throw new UserException(_loc.get("bad-id-value", val, 
-                val.getClass().getName(), cls)).setCause(iae);
-        } catch (OpenJPAException ke) {
-            throw ke;
-        } catch (ClassCastException cce) {
-            throw new UserException(_loc.get("bad-id-value", val,
-                val.getClass().getName(), cls)).setCause(cce);
-        } catch (RuntimeException re) {
-            throw new GeneralException(re);
-        } finally {
-            endOperation();
-        }
-    }
-
-    /**
-     * Create a new state manager for the given oid.
-     */
-    private StateManagerImpl newStateManagerImpl(Object oid, boolean copy) {
-        // see if we're in the process of loading this oid in a loadAll call
-        StateManagerImpl sm;
-        if (_loading != null) {
-            sm = (StateManagerImpl) _loading.get(oid);
-            if (sm != null && sm.getPersistenceCapable() == null)
-                return sm;
-        }
-
-        // find metadata for the oid
-        Class pcType = _store.getManagedType(oid);
-        MetaDataRepository repos = _conf.getMetaDataRepositoryInstance();
-        ClassMetaData meta;
-        if (pcType != null)
-            meta = repos.getMetaData(pcType, _loader, true);
-        else
-            meta = repos.getMetaData(oid, _loader, true);
-
-        // copy the oid if needed
-        if (copy && _compat.getCopyObjectIds()) {
-            if (meta.getIdentityType() == ClassMetaData.ID_APPLICATION)
-                oid = ApplicationIds.copy(oid, meta);
-            else if (meta.getIdentityType() == ClassMetaData.ID_UNKNOWN)
-                throw new UserException(_loc.get("meta-unknownid", meta));
-            else
-                oid = _store.copyDataStoreId(oid, meta);
-        }
-
-        sm = newStateManagerImpl(oid, meta);
-        sm.setObjectId(oid);
-        return sm;
-    }
-
-    /**
-     * Create a state manager for the given oid and metadata.
-     */
-    protected StateManagerImpl newStateManagerImpl(Object oid,
-        ClassMetaData meta) {
-        return new StateManagerImpl(oid, meta, this);
-    }
-
-    ///////////////
-    // Transaction
-    ///////////////
-
-    public void begin() {
-        beginOperation(true);
-        try {
-            if ((_flags & FLAG_ACTIVE) != 0)
-                throw new InvalidStateException(_loc.get("active"));
-            _factory.syncWithManagedTransaction(this, true);
-            beginInternal();
-        } finally {
-            endOperation();
-        }
-    }
-
-    /**
-     * Notify the store manager of a transaction.
-     */
-    private void beginInternal() {
-        try {
-            beginStoreManagerTransaction(_optimistic);
-            _flags |= FLAG_ACTIVE;
-
-            // start locking
-            if (!_optimistic) {
-                _fc.setReadLockLevel(_conf.getReadLockLevelConstant());
-                _fc.setWriteLockLevel(_conf.getWriteLockLevelConstant());
-                _fc.setLockTimeout(_conf.getLockTimeout());
-            }
-            _lm.beginTransaction();
-
-            if (_transEventManager.hasBeginListeners())
-                fireTransactionEvent(new TransactionEvent(this,
-                    TransactionEvent.AFTER_BEGIN, null, null, null, null));
-        } catch (OpenJPAException ke) {
-            // if we already started the transaction, don't let it commit
-            if ((_flags & FLAG_ACTIVE) != 0)
-                setRollbackOnlyInternal(ke);
-            throw ke.setFatal(true);
-        } catch (RuntimeException re) {
-            // if we already started the transaction, don't let it commit
-            if ((_flags & FLAG_ACTIVE) != 0)
-                setRollbackOnlyInternal(re);
-            throw new StoreException(re).setFatal(true);
-        }
-
-        if (_pending != null) {
-            StateManagerImpl sm;
-            for (Iterator it = _pending.iterator(); it.hasNext();) {
-                sm = (StateManagerImpl) it.next();
-                sm.transactional();
-                if (sm.isDirty())
-                    setDirty(sm, true);
-            }
-            _pending = null;
-        }
-    }
-
-    public void beginStore() {
-        beginOperation(true);
-        try {
-            assertTransactionOperation();
-            if ((_flags & FLAG_STORE_ACTIVE) == 0)
-                beginStoreManagerTransaction(false);
-        } catch (OpenJPAException ke) {
-            throw ke;
-        } catch (RuntimeException re) {
-            throw new StoreException(re);
-        } finally {
-            endOperation();
-        }
-    }
-
-    /**
-     * Begin a store manager transaction.
-     */
-    private void beginStoreManagerTransaction(boolean optimistic) {
-        if (!optimistic) {
-            retainConnection();
-            _store.begin();
-            _flags |= FLAG_STORE_ACTIVE;
-        } else {
-            if (_connRetainMode == CONN_RETAIN_TRANS)
-                retainConnection();
-            _store.beginOptimistic();
-        }
-    }
-
-    /**
-     * End the current store manager transaction. Throws an
-     * exception to signal a forced rollback after failed commit, otherwise
-     * returns any exception encountered during the end process.
-     */
-    private RuntimeException endStoreManagerTransaction(boolean rollback) {
-        boolean forcedRollback = false;
-        boolean releaseConn = false;
-        RuntimeException err = null;
-        try {
-            if ((_flags & FLAG_STORE_ACTIVE) != 0) {
-                releaseConn = _connRetainMode != CONN_RETAIN_ALWAYS;
-                if (rollback)
-                    _store.rollback();
-                else
-                    _store.commit();
-            } else {
-                releaseConn = _connRetainMode == CONN_RETAIN_TRANS;
-                _store.rollbackOptimistic();
-            }
-        }
-        catch (RuntimeException re) {
-            if (!rollback) {
-                forcedRollback = true;
-                try { _store.rollback(); } catch (RuntimeException re2) {}
-            }
-            err = re;
-        } finally {
-            _flags &= ~FLAG_STORE_ACTIVE;
-        }
-
-        if (releaseConn) {
-            try {
-                releaseConnection();
-            } catch (RuntimeException re) {
-                if (err == null)
-                    err = re;
-            }
-        }
-
-        if (forcedRollback)
-            throw err;
-        return err;
-    }
-
-    public void commit() {
-        beginOperation(false);
-        try {
-            assertTransactionOperation();
-
-            javax.transaction.Transaction trans =
-                _runtime.getTransactionManager().getTransaction();
-            if (trans == null)
-                throw new InvalidStateException(_loc.get("null-trans"));
-
-            // this commit on the transaction will cause our
-            // beforeCompletion method to be invoked
-            trans.commit();
-        } catch (OpenJPAException ke) {
-            if (_log.isTraceEnabled())
-                _log.trace(_loc.get("end-trans-error"), ke);
-            throw ke;
-        } catch (Exception e) {
-            if (_log.isTraceEnabled())
-                _log.trace(_loc.get("end-trans-error"), e);
-            throw new StoreException(e);
-        } finally {
-            endOperation();
-        }
-    }
-
-    public void rollback() {
-        beginOperation(false);
-        try {
-            assertTransactionOperation();
-
-            javax.transaction.Transaction trans =
-                _runtime.getTransactionManager().getTransaction();
-            if (trans != null)
-                trans.rollback();
-        } catch (OpenJPAException ke) {
-            if (_log.isTraceEnabled())
-                _log.trace(_loc.get("end-trans-error"), ke);
-            throw ke;
-        } catch (Exception e) {
-            if (_log.isTraceEnabled())
-                _log.trace(_loc.get("end-trans-error"), e);
-            throw new StoreException(e);
-        } finally {
-            endOperation();
-        }
-    }
-
-    public boolean syncWithManagedTransaction() {
-        assertOpen();
-        lock();
-        try {
-            if ((_flags & FLAG_ACTIVE) != 0)
-                return true;
-            if (!_managed)
-                throw new InvalidStateException(_loc.get("trans-not-managed"));
-            if (_factory.syncWithManagedTransaction(this, false)) {
-                beginInternal();
-                return true;
-            }
-            return false;
-        } finally {
-            unlock();
-        }
-    }
-
-    public void commitAndResume() {
-        endAndResume(true);
-    }
-
-    public void rollbackAndResume() {
-        endAndResume(false);
-    }
-
-    private void endAndResume(boolean commit) {
-        beginOperation(false);
-        try {
-            if (commit)
-                commit();
-            else
-                rollback();
-            begin();
-        } finally {
-            endOperation();
-        }
-    }
-
-    public boolean getRollbackOnly() {
-        beginOperation(true);
-        try {
-            if ((_flags & FLAG_ACTIVE) == 0)
-                return false;
-
-            javax.transaction.Transaction trans =
-                _runtime.getTransactionManager().getTransaction();
-            if (trans == null)
-                return false;
-            return trans.getStatus() == Status.STATUS_MARKED_ROLLBACK;
-        } catch (OpenJPAException ke) {
-            throw ke;
-        } catch (Exception e) {
-            throw new GeneralException(e);
-        } finally {
-            endOperation();
-        }
-    }
-
-    public Throwable getRollbackCause() {
-        beginOperation(true);
-        try {
-            if ((_flags & FLAG_ACTIVE) == 0)
-                return null;
-
-            javax.transaction.Transaction trans =
-                _runtime.getTransactionManager().getTransaction();
-            if (trans == null)
-                return null;
-            if (trans.getStatus() == Status.STATUS_MARKED_ROLLBACK)
-                return _runtime.getRollbackCause();
-
-            return null;
-        } catch (OpenJPAException ke) {
-            throw ke;
-        } catch (Exception e) {
-            throw new GeneralException(e);
-        } finally {
-            endOperation();
-        }
-    }
-
-    public void setRollbackOnly() {
-        setRollbackOnly(new UserException());
-    }
-
-    public void setRollbackOnly(Throwable cause) {
-        beginOperation(true);
-        try {
-            assertTransactionOperation();
-            setRollbackOnlyInternal(cause);
-        } finally {
-            endOperation();
-        }
-    }
-
-    /**
-     * Mark the current transaction as rollback-only.
-     */
-    private void setRollbackOnlyInternal(Throwable cause) {
-        try {
-            javax.transaction.Transaction trans =
-                _runtime.getTransactionManager().getTransaction();
-            if (trans == null)
-                throw new InvalidStateException(_loc.get("null-trans"));
-            // ensure tran is in a valid state to accept the setRollbackOnly
-            int tranStatus = trans.getStatus();
-            if ((tranStatus != Status.STATUS_NO_TRANSACTION)
-                    && (tranStatus != Status.STATUS_ROLLEDBACK)
-                    && (tranStatus != Status.STATUS_COMMITTED))
-                _runtime.setRollbackOnly(cause);
-            else if (_log.isTraceEnabled())
-                _log.trace(_loc.get("invalid-tran-status", new Integer(
-                        tranStatus), "setRollbackOnly"));
-        } catch (OpenJPAException ke) {
-            throw ke;
-        } catch (Exception e) {
-            throw new GeneralException(e);
-        }
-    }
-
-    public void setSavepoint(String name) {
-        beginOperation(true);
-        try {
-            assertActiveTransaction();
-            if (_savepoints != null && _savepoints.containsKey(name))
-                throw new UserException(_loc.get("savepoint-exists", name));
-
-            if (hasFlushed() && !_spm.supportsIncrementalFlush())
-                throw new UnsupportedException(_loc.get
-                    ("savepoint-flush-not-supported"));
-
-            OpenJPASavepoint save = _spm.newSavepoint(name, this);
-            if (_savepoints == null || _savepoints.isEmpty()) {
-                save.save(getTransactionalStates());
-                _savepoints = new LinkedMap();
-            } else {
-                if (_savepointCache == null)
-                    save.save(Collections.EMPTY_LIST);
-                else {
-                    save.save(_savepointCache);
-                    _savepointCache.clear();
-                }
-            }
-            _savepoints.put(name, save);
-        } catch (OpenJPAException ke) {
-            throw ke;
-        } catch (Exception e) {
-            throw new GeneralException(e);
-        } finally {
-            endOperation();
-        }
-    }
-
-    public void releaseSavepoint() {
-        beginOperation(false);
-        try {
-            if (_savepoints == null || _savepoints.isEmpty())
-                throw new UserException(_loc.get("no-lastsavepoint"));
-            releaseSavepoint((String) _savepoints.get
-                (_savepoints.size() - 1));
-        } finally {
-            endOperation();
-        }
-    }
-
-    public void releaseSavepoint(String savepoint) {
-        beginOperation(false);
-        try {
-            assertActiveTransaction();
-
-            int index = (_savepoints == null) ? -1
-                : _savepoints.indexOf(savepoint);
-            if (index < 0)
-                throw new UserException(_loc.get("no-savepoint", savepoint));
-
-            // clear old in reverse
-            OpenJPASavepoint save;
-            while (_savepoints.size() > index + 1) {
-                save = (OpenJPASavepoint) _savepoints.remove
-                    (_savepoints.size() - 1);
-                save.release(false);
-            }
-
-            save = (OpenJPASavepoint) _savepoints.remove(index);
-            save.release(true);
-            if (_savepointCache != null)
-                _savepointCache.clear();
-        } catch (OpenJPAException ke) {
-            throw ke;
-        } catch (Exception e) {
-            throw new GeneralException(e);
-        } finally {
-            endOperation();
-        }
-    }
-
-    public void rollbackToSavepoint() {
-        beginOperation(false);
-        try {
-            if (_savepoints == null || _savepoints.isEmpty())
-                throw new UserException(_loc.get("no-lastsavepoint"));
-            rollbackToSavepoint((String) _savepoints.get
-                (_savepoints.size() - 1));
-        } finally {
-            endOperation();
-        }
-    }
-
-    public void rollbackToSavepoint(String savepoint) {
-        beginOperation(false);
-        try {
-            assertActiveTransaction();
-
-            int index = (_savepoints == null) ? -1
-                : _savepoints.indexOf(savepoint);
-            if (index < 0)
-                throw new UserException(_loc.get("no-savepoint", savepoint));
-
-            // clear old in reverse
-            OpenJPASavepoint save;
-            while (_savepoints.size() > index + 1) {
-                save = (OpenJPASavepoint) _savepoints.remove
-                    (_savepoints.size() - 1);
-                save.release(false);
-            }
-
-            save = (OpenJPASavepoint) _savepoints.remove(index);
-            Collection saved = save.rollback(_savepoints.values());
-            if (_savepointCache != null)
-                _savepointCache.clear();
-            if (hasTransactionalObjects()) {
-                // build up a new collection of states
-                TransactionalCache oldTransCache = _transCache;
-                TransactionalCache newTransCache = new TransactionalCache
-                    (_orderDirty);
-                _transCache = null;
-
-                // currently there is the assumption that incremental
-                // flush is either a) not allowed, or b) required
-                // pre-savepoint.  this solves a number of issues including
-                // storing flushed states as well as OID handling.
-                // if future plugins do not follow this, we need to cache
-                // more info per state
-                SavepointFieldManager fm;
-                StateManagerImpl sm;
-                for (Iterator itr = saved.iterator(); itr.hasNext();) {
-                    fm = (SavepointFieldManager) itr.next();
-                    sm = fm.getStateManager();
-                    sm.rollbackToSavepoint(fm);
-                    oldTransCache.remove(sm);
-                    if (sm.isDirty())
-                        newTransCache.addDirty(sm);
-                    else
-                        newTransCache.addClean(sm);
-                }
-                for (Iterator itr = oldTransCache.iterator(); itr.hasNext();) {
-                    sm = (StateManagerImpl) itr.next();
-                    sm.rollback();
-                    removeFromTransaction(sm);
-                }
-                _transCache = newTransCache;
-            }
-        }
-        catch (OpenJPAException ke) {
-            throw ke;
-        } catch (Exception e) {
-            throw new GeneralException(e);
-        } finally {
-            endOperation();
-        }
-    }
-
-    public void flush() {
-        beginOperation(true);
-        try {
-            // return silently if no trans is active, or if this is a reentrant
-            // call, which can happen if the store manager tries to get an
-            // auto-inc oid during flush
-            if ((_flags & FLAG_ACTIVE) == 0
-                || (_flags & FLAG_STORE_FLUSHING) != 0)
-                return;
-
-            // make sure the runtime supports it
-            if (!_conf.supportedOptions().contains(_conf.OPTION_INC_FLUSH))
-                throw new UnsupportedException(_loc.get
-                    ("incremental-flush-not-supported"));
-            if (_savepoints != null && !_savepoints.isEmpty()
-                && !_spm.supportsIncrementalFlush())
-                throw new UnsupportedException(_loc.get
-                    ("savepoint-flush-not-supported"));
-
-            try {
-                flushSafe(FLUSH_INC);
-                _flags |= FLAG_FLUSHED;
-            } catch (OpenJPAException ke) {
-                // rollback on flush error; objects may be in inconsistent state
-                setRollbackOnly(ke);
-                throw ke.setFatal(true);
-            } catch (RuntimeException re) {
-                // rollback on flush error; objects may be in inconsistent state
-                setRollbackOnly(re);
-                throw new StoreException(re).setFatal(true);
-            }
-        }
-        finally {
-            endOperation();
-        }
-    }
-
-    public void preFlush() {
-        beginOperation(true);
-        try {
-            if ((_flags & FLAG_ACTIVE) != 0)
-                flushSafe(FLUSH_LOGICAL);
-        } finally {
-            endOperation();
-        }
-    }
-
-    public void validateChanges() {
-        beginOperation(true);
-        try {
-            // if no trans, just return; if active datastore trans, flush
-            if ((_flags & FLAG_ACTIVE) == 0)
-                return;
-            if ((_flags & FLAG_STORE_ACTIVE) != 0) {
-                flush();
-                return;
-            }
-
-            // make sure the runtime supports inc flush
-            if (!_conf.supportedOptions().contains(_conf.OPTION_INC_FLUSH))
-                throw new UnsupportedException(_loc.get
-                    ("incremental-flush-not-supported"));
-
-            try {
-                flushSafe(FLUSH_ROLLBACK);
-            } catch (OpenJPAException ke) {
-                throw ke;
-            } catch (RuntimeException re) {
-                throw new StoreException(re);
-            }
-        }
-        finally {
-            endOperation();
-        }
-    }
-
-    public boolean isActive() {
-        beginOperation(true);
-        try {
-            return (_flags & FLAG_ACTIVE) != 0;
-        } finally {
-            endOperation();
-        }
-    }
-
-    public boolean isStoreActive() {
-        // we need to lock here, because we might be in the middle of an
-        // atomic transaction process (e.g., commitAndResume)
-        beginOperation(true);
-        try {
-            return (_flags & FLAG_STORE_ACTIVE) != 0;
-        } finally {
-            endOperation();
-        }
-    }
-
-    /**
-     * Return whether the current transaction is ending, i.e. in the 2nd phase
-     * of a commit or rollback
-     */
-    boolean isTransactionEnding() {
-        return (_flags & FLAG_TRANS_ENDING) != 0;
-    }
-
-    public boolean beginOperation(boolean syncTrans) {
-        lock();
-        try {
-            assertOpen();
-
-            if (syncTrans && _operationCount == 0 && _syncManaged
-                && (_flags & FLAG_ACTIVE) == 0)
-                syncWithManagedTransaction();
-            return _operationCount++ == 1;
-        } catch (OpenJPAException ke) {
-            unlock();
-            throw ke;
-        } catch (RuntimeException re) {
-            unlock();
-            throw new GeneralException(re);
-        }
-    }
-
-    /**
-     * Mark the operation over. If outermost caller of stack, returns true
-     * and will detach managed instances if necessary.
-     */
-    public boolean endOperation() {
-        try {
-            if (_operationCount == 1 && (_autoDetach & DETACH_NONTXREAD) != 0
-                && (_flags & FLAG_ACTIVE) == 0) {
-                detachAllInternal(null);
-            }
-            if (_operationCount < 1)
-                throw new InternalException(_loc.get("multi-threaded-access"));
-            return _operationCount == 1;
-        } catch (OpenJPAException ke) {
-            throw ke;
-        } catch (RuntimeException re) {
-            throw new GeneralException(re);
-        } finally {
-            _operationCount--;
-            if (_operationCount == 0)
-                initializeOperatingSet();
-            unlock();
-        }
-    }
-
-    public Synchronization getSynchronization() {
-        return _sync;
-    }
-
-    public void setSynchronization(Synchronization sync) {
-        assertOpen();
-        _sync = sync;
-    }
-
-    ///////////////////////////////////////////////
-    // Implementation of Synchronization interface
-    ///////////////////////////////////////////////
-
-    public void beforeCompletion() {
-        beginOperation(false);
-        try {
-            // user-supplied synchronization
-            if (_sync != null)
-                _sync.beforeCompletion();
-
-            flushSafe(FLUSH_COMMIT);
-        } catch (OpenJPAException ke) {
-            if (_log.isTraceEnabled())
-                _log.trace(_loc.get("end-trans-error"), ke);
-            throw translateManagedCompletionException(ke);
-        } catch (RuntimeException re) {
-            if (_log.isTraceEnabled())
-                _log.trace(_loc.get("end-trans-error"), re);
-            throw translateManagedCompletionException(new StoreException(re));
-        } finally {
-            endOperation();
-        }
-    }
-
-    public void afterCompletion(int status) {
-        beginOperation(false);
-        try {
-            assertActiveTransaction();
-
-            _flags |= FLAG_TRANS_ENDING;
-            endTransaction(status);
-            if (_sync != null)
-                _sync.afterCompletion(status);
-
-            if ((_autoDetach & DETACH_COMMIT) != 0)
-                detachAllInternal(null);
-            else if (status == Status.STATUS_ROLLEDBACK 
-                && (_autoDetach & DETACH_ROLLBACK) != 0) {
-                detachAllInternal(null);
-            }
-
-            // in an ee context, it's possible that the user tried to close
-            // us but we didn't actually close because we were waiting on this
-            // transaction; if that's true, then close now
-            if ((_flags & FLAG_CLOSE_INVOKED) != 0
-                && _compat.getCloseOnManagedCommit())
-                free();
-        } catch (OpenJPAException ke) {
-            if (_log.isTraceEnabled())
-                _log.trace(_loc.get("end-trans-error"), ke);
-            throw translateManagedCompletionException(ke);
-        } catch (RuntimeException re) {
-            if (_log.isTraceEnabled())
-                _log.trace(_loc.get("end-trans-error"), re);
-            throw translateManagedCompletionException(new StoreException(re));
-        } finally {
-            _flags &= ~FLAG_ACTIVE;
-            _flags &= ~FLAG_FLUSHED;
-            _flags &= ~FLAG_TRANS_ENDING;
-
-            // event manager nulled if freed broker
-            if (_transEventManager != null 
-                && _transEventManager.hasEndListeners()) {
-                fireTransactionEvent(new TransactionEvent(this,
-                    status == Status.STATUS_COMMITTED
-                        ? TransactionEvent.AFTER_COMMIT_COMPLETE
-                        : TransactionEvent.AFTER_ROLLBACK_COMPLETE,
-                    null, null, null, null));
-            }
-
-            endOperation();
-        }
-    }
-
-    /**
-     * If we're in a managed transaction, use our implicit behavior exception
-     * translator to translate before/afterCompletion callback errors.
-     */
-    private RuntimeException translateManagedCompletionException
-        (RuntimeException re) {
-        return (!_managed || _extrans == null) ? re : _extrans.translate(re);
-    }
-
-    /**
-     * Flush safely, catching reentrant calls.
-     */
-    private void flushSafe(int reason) {
-        if ((_flags & FLAG_FLUSHING) != 0)
-            throw new InvalidStateException(_loc.get("reentrant-flush"));
-
-        _flags |= FLAG_FLUSHING;
-        try {
-            flush(reason);
-        } finally {
-            _flags &= ~FLAG_FLUSHING;
-        }
-    }
-
-    /**
-     * Flush the transactional state to the data store. Subclasses that
-     * customize commit behavior should override this method. The method
-     * assumes that the persistence manager is locked, is not closed,
-     * and has an active transaction.
-     *
-     * @param reason one of {@link #FLUSH_INC}, {@link #FLUSH_COMMIT},
-     * {@link #FLUSH_ROLLBACK}, or {@link #FLUSH_LOGICAL}
-     * @since 0.2.5
-     */
-    protected void flush(int reason) {
-        // this will enlist proxied states as necessary so we know whether we
-        // have anything to flush
-        Collection transactional = getTransactionalStates();
-
-        // do we actually have to flush?  only if our flags say so, or if
-        // we have transaction listeners that need to be invoked for commit
-        // (no need to invoke them on inc flush if nothing is dirty).  we
-        // special case the remote commit listener used by the datacache cause
-        // we know it doesn't require the commit event when nothing changes
-        boolean flush = (_flags & FLAG_FLUSH_REQUIRED) != 0;
-        boolean listeners = (_transEventManager.hasFlushListeners()
-            || _transEventManager.hasEndListeners())
-            && ((_flags & FLAG_REMOTE_LISTENER) == 0
-            || _transEventManager.getListeners().size() > 1);
-        if (!flush && (reason != FLUSH_COMMIT || !listeners))
-            return;
-
-        Collection mobjs = null;
-        _flags |= FLAG_PRESTORING;
-        try {
-            if (flush) {
-                // call pre store on all currently transactional objs
-                for (Iterator itr = transactional.iterator(); itr.hasNext();)
-                    ((StateManagerImpl) itr.next()).beforeFlush(reason, _call);
-                flushAdditions(transactional, reason);
-            }
-
-            // hopefully now all dependent instances that are going to end
-            // up referenced have been marked as such; delete unrefed
-            // dependents
-            _flags |= FLAG_DEREFDELETING;
-            if (flush && _derefCache != null && !_derefCache.isEmpty()) {
-                for (Iterator itr = _derefCache.iterator(); itr.hasNext();)
-                    deleteDeref((StateManagerImpl) itr.next());
-                flushAdditions(transactional, reason);
-            }
-
-            if (reason != FLUSH_LOGICAL) {
-                // if no datastore transaction, start one; even if we don't
-                // think we'll need to flush at this point, our transaction
-                // listeners might introduce some dirty objects or interact
-                // directly with the database
-                if ((_flags & FLAG_STORE_ACTIVE) == 0)
-                    beginStoreManagerTransaction(false);
-
-                if ((_transEventManager.hasFlushListeners()
-                    || _transEventManager.hasEndListeners())
-                    && (flush || reason == FLUSH_COMMIT)) {
-                    // fire events
-                    mobjs = new ManagedObjectCollection(transactional);
-                    if (reason == FLUSH_COMMIT
-                        && _transEventManager.hasEndListeners()) {
-                        fireTransactionEvent(new TransactionEvent(this, 
-                            TransactionEvent.BEFORE_COMMIT, mobjs,
-                            _persistedClss, _updatedClss, _deletedClss));
-
-                        flushAdditions(transactional, reason);
-                        flush = (_flags & FLAG_FLUSH_REQUIRED) != 0;
-                    }
-
-                    if (flush && _transEventManager.hasFlushListeners()) {
-                        fireTransactionEvent(new TransactionEvent(this, 
-                            TransactionEvent.BEFORE_FLUSH, mobjs,
-                            _persistedClss, _updatedClss, _deletedClss));
-                        flushAdditions(transactional, reason);
-                    }
-                }
-            }
-        }
-        finally {
-            _flags &= ~FLAG_PRESTORING;
-            _flags &= ~FLAG_DEREFDELETING;
-            _transAdditions = null;
-            _derefAdditions = null;
-
-            // also clear derefed set; the deletes have been recorded
-            if (_derefCache != null)
-                _derefCache = null;
-        }
-
-        // flush to store manager
-        List exceps = null;
-        try {
-            if (flush && reason != FLUSH_LOGICAL) {
-                _flags |= FLAG_STORE_FLUSHING;
-                exceps = add(exceps,
-                    newFlushException(_store.flush(transactional)));
-            }
-        } finally {
-            _flags &= ~FLAG_STORE_FLUSHING;
-
-            if (reason == FLUSH_ROLLBACK)
-                exceps = add(exceps, endStoreManagerTransaction(true));
-            else if (reason != FLUSH_LOGICAL)
-                _flags &= ~FLAG_FLUSH_REQUIRED;
-
-            // mark states as flushed
-            if (flush) {
-                StateManagerImpl sm;
-                for (Iterator itr = transactional.iterator(); itr.hasNext();) {
-                    sm = (StateManagerImpl) itr.next();
-                    try {
-                        // the state may have become transient, such as if
-                        // it is embedded and the owner has been deleted during
-                        // this flush process; bug #1100
-                        if (sm.getPCState() == PCState.TRANSIENT)
-                            continue;
-
-                        sm.afterFlush(reason);
-                        if (reason == FLUSH_INC) {
-                            // if not about to clear trans cache for commit 
-                            // anyway, re-cache dirty objects with default soft
-                            // refs; we don't need hard refs now that the 
-                            // changes have been flushed
-                            sm.proxyFields(true, false);
-                            _transCache.flushed(sm);
-                        }
-                    } catch (Exception e) {
-                        exceps = add(exceps, e);
-                    }
-                }
-            }
-        }
-
-        // throw any exceptions to shortcut listeners on fail
-        throwNestedExceptions(exceps, true);
-
-        if (flush && reason != FLUSH_ROLLBACK && reason != FLUSH_LOGICAL
-            && _transEventManager.hasFlushListeners()) {
-            fireTransactionEvent(new TransactionEvent(this,
-                TransactionEvent.AFTER_FLUSH, mobjs, _persistedClss,
-                _updatedClss, _deletedClss));
-        }
-    }
-
-    /**
-     * Flush newly-transactional objects.
-     */
-    private void flushAdditions(Collection transactional, int reason) {
-        boolean loop;
-        do {
-            // flush new transactional instances; note logical or
-            loop = flushTransAdditions(transactional, reason)
-                | deleteDerefAdditions(_derefCache);
-        } while (loop);
-    }
-
-    /**
-     * Flush transactional additions.
-     */
-    private boolean flushTransAdditions(Collection transactional, int reason) {
-        if (_transAdditions == null || _transAdditions.isEmpty())
-            return false;
-
-        // keep local transactional list copy up to date
-        transactional.addAll(_transAdditions);
-
-        // copy the change set, then clear it for the next iteration
-        StateManagerImpl[] states = (StateManagerImpl[]) _transAdditions.
-            toArray(new StateManagerImpl[_transAdditions.size()]);
-        _transAdditions = null;
-
-        for (int i = 0; i < states.length; i++)
-            states[i].beforeFlush(reason, _call);
-        return true;
-    }
-
-    /**
-     * Delete new dereferenced objects.
-     */
-    private boolean deleteDerefAdditions(Collection derefs) {
-        if (_derefAdditions == null || _derefAdditions.isEmpty())
-            return false;
-
-        // remember these additions in case one becomes derefed again later
-        derefs.addAll(_derefAdditions);
-
-        StateManagerImpl[] states = (StateManagerImpl[]) _derefAdditions.
-            toArray(new StateManagerImpl[_derefAdditions.size()]);
-        _derefAdditions = null;
-
-        for (int i = 0; i < states.length; i++)
-            deleteDeref(states[i]);
-        return true;
-    }
-
-    /**
-     * Delete a dereferenced dependent.
-     */
-    private void deleteDeref(StateManagerImpl sm) {
-        int action = processArgument(OpCallbacks.OP_DELETE,
-            sm.getManagedInstance(), sm, null);
-        if ((action & OpCallbacks.ACT_RUN) != 0)
-            sm.delete();
-        if ((action & OpCallbacks.ACT_CASCADE) != 0)
-            sm.cascadeDelete(_call);
-    }
-
-    /**
-     * Determine the action to take based on the user's given callbacks and
-     * our implicit behavior.
-     */
-    private int processArgument(int op, Object obj, OpenJPAStateManager sm,
-        OpCallbacks call) {
-        if (call != null)
-            return call.processArgument(op, obj, sm);
-        if (_call != null)
-            return _call.processArgument(op, obj, sm);
-        return OpCallbacks.ACT_RUN | OpCallbacks.ACT_CASCADE;
-    }
-
-    /**
-     * Throw the proper exception based on the given set of flush errors, or
-     * do nothing if no errors occurred.
-     */
-    private OpenJPAException newFlushException(Collection exceps) {
-        if (exceps == null || exceps.isEmpty())
-            return null;
-
-        Throwable[] t = (Throwable[]) exceps.toArray
-            (new Throwable[exceps.size()]);
-        List failed = new ArrayList(t.length);
-
-        // create fatal exception with nested exceptions for all the failed
-        // objects; if all OL exceptions, throw a top-level OL exception
-        boolean opt = true;
-        for (int i = 0; opt && i < t.length; i++) {
-            opt = t[i] instanceof OptimisticException;
-            if (opt) {
-                Object f = ((OptimisticException) t[i]).getFailedObject();
-                if (f != null)
-                    failed.add(f);
-            }
-        }
-        if (opt && !failed.isEmpty())
-            return new OptimisticException(failed, t);
-        if (opt)
-            return new OptimisticException(t);
-        return new StoreException(_loc.get("rolled-back")).
-            setNestedThrowables(t).setFatal(true);
-    }
-
-    /**
-     * End the current transaction, making appropriate state transitions.
-     */
-    protected void endTransaction(int status) {
-        // if a data store transaction was in progress, do the
-        // appropriate transaction change
-        boolean rollback = status != Status.STATUS_COMMITTED;
-        List exceps = null;
-
-        try {
-            exceps = add(exceps, endStoreManagerTransaction(rollback));
-        } catch (RuntimeException re) {
-            rollback = true;
-            exceps = add(exceps, re);
-        }
-
-        // go back to default none lock level
-        _fc.setReadLockLevel(LOCK_NONE);
-        _fc.setWriteLockLevel(LOCK_NONE);
-        _fc.setLockTimeout(-1);
-
-        Collection transStates;
-        if (hasTransactionalObjects())
-            transStates = _transCache;
-        else
-            transStates = Collections.EMPTY_LIST;
-
-        // fire after rollback/commit event
-        Collection mobjs = null;
-        if (_transEventManager.hasEndListeners()) {
-            mobjs = new ManagedObjectCollection(transStates);
-            int eventType = (rollback) ? TransactionEvent.AFTER_ROLLBACK
-                : TransactionEvent.AFTER_COMMIT;
-            fireTransactionEvent(new TransactionEvent(this, eventType, mobjs, 
-                _persistedClss, _updatedClss, _deletedClss));
-        }
-
-        // null transactional caches now so that all the removeFromTransaction
-        // calls as we transition each object don't have to do any work; don't
-        // clear trans cache object because we still need the transStates
-        // reference to it below
-        _transCache = null;
-        if (_persistedClss != null)
-            _persistedClss = null;
-        if (_updatedClss != null)
-            _updatedClss = null;
-        if (_deletedClss != null)
-            _deletedClss = null;
-
-        // new cache would get cleared anyway during transitions, but doing so
-        // immediately saves us some lookups
-        _cache.clearNew();
-
-        // tell all derefed instances they're no longer derefed; we can't
-        // rely on rollback and commit calls below cause some instances might
-        // not be transactional
-        if (_derefCache != null && !_derefCache.isEmpty()) {
-            for (Iterator itr = _derefCache.iterator(); itr.hasNext();)
-                ((StateManagerImpl) itr.next()).setDereferencedDependent
-                    (false, false);
-            _derefCache = null;
-        }
-
-        // peform commit or rollback state transitions on each instance
-        StateManagerImpl sm;
-        for (Iterator itr = transStates.iterator(); itr.hasNext();) {
-            sm = (StateManagerImpl) itr.next();
-            try {
-                if (rollback) {
-                    // tell objects that may have been derefed then flushed
-                    // (and therefore deleted) to un-deref
-                    sm.setDereferencedDependent(false, false);
-                    sm.rollback();
-                } else
-                    sm.commit();
-            } catch (RuntimeException re) {
-                exceps = add(exceps, re);
-            }
-        }
-
-        // notify the lock manager to clean up and release remaining locks
-        _lm.endTransaction();
-
-        // clear old savepoints in reverse
-        OpenJPASavepoint save;
-        while (_savepoints != null && _savepoints.size() > 0) {
-            save =
-                (OpenJPASavepoint) _savepoints.remove(_savepoints.size() - 1);
-            save.release(false);
-        }
-        _savepoints = null;
-        _savepointCache = null;
-
-        // fire after state change event
-        if (_transEventManager.hasEndListeners())
-            fireTransactionEvent(new TransactionEvent(this, TransactionEvent.
-                AFTER_STATE_TRANSITIONS, mobjs, null, null, null));
-
-        // now clear trans cache; keep cleared version rather than
-        // null to avoid having to re-create the set later; more efficient
-        if (transStates != Collections.EMPTY_LIST) {
-            _transCache = (TransactionalCache) transStates;
-            _transCache.clear();
-        }
-
-        throwNestedExceptions(exceps, true);
-    }
-
-    ////////////////////
-    // Object lifecycle
-    ////////////////////
-
-    public void persist(Object obj, OpCallbacks call) {
-        persist(obj, null, true, call);
-    }
-
-    public OpenJPAStateManager persist(Object obj, Object id,
-        OpCallbacks call) {
-        return persist(obj, id, true, call);
-    }
-
-    public void persistAll(Collection objs, OpCallbacks call) {
-        persistAll(objs, true, call);
-    }
-
-    /**
-     * Persist the given objects.  Indicate whether this was an explicit persist
-     * (PNEW) or a provisonal persist (PNEWPROVISIONAL).
-     */
-    public void persistAll(Collection objs, boolean explicit, 
-        OpCallbacks call) {
-        if (objs.isEmpty())
-            return;
-
-        beginOperation(true);
-        List exceps = null;
-        try {
-            assertWriteOperation();
-
-            for (Iterator itr = objs.iterator(); itr.hasNext();) {
-                try {
-                    persist(itr.next(), explicit, call);
-                } catch (UserException ue) {
-                    exceps = add(exceps, ue);
-                }
-            }
-        } finally {
-            endOperation();
-        }
-        throwNestedExceptions(exceps, false);
-    }
-
-    /**
-     * If the given element is not null, add it to the given list,
-     * creating the list if necessary.
-     */
-    private List add(List l, Object o) {
-        if (o == null)
-            return l;
-        if (l == null)
-            l = new LinkedList();
-        l.add(o);
-        return l;
-    }
-
-    /**
-     * Throw an exception wrapping the given nested exceptions.
-     */
-    private void throwNestedExceptions(List exceps, boolean datastore) {
-        if (exceps == null || exceps.isEmpty())
-            return;
-        if (datastore && exceps.size() == 1)
-            throw (RuntimeException) exceps.get(0);
-
-        boolean fatal = false;
-        Throwable[] t = (Throwable[]) exceps.toArray
-            (new Throwable[exceps.size()]);
-        for (int i = 0; i < t.length; i++) {
-            if (t[i] instanceof OpenJPAException
-                && ((OpenJPAException) t[i]).isFatal())
-                fatal = true;
-        }
-        OpenJPAException err;
-        if (datastore)
-            err = new StoreException(_loc.get("nested-exceps"));
-        else
-            err = new UserException(_loc.get("nested-exceps"));
-        throw err.setNestedThrowables(t).setFatal(fatal);
-    }
-
-    /**
-     * Persist the given object.  Indicate whether this was an explicit persist
-     * (PNEW) or a provisonal persist (PNEWPROVISIONAL)
-     */
-    public void persist(Object obj, boolean explicit, OpCallbacks call) {
-        persist(obj, null, explicit, call);
-    }
-
-    /**
-     * Persist the given object.  Indicate whether this was an explicit persist
-     * (PNEW) or a provisonal persist (PNEWPROVISIONAL).
-     * See {@link Broker} for details on this method.
-     */
-    public OpenJPAStateManager persist(Object obj, Object id, boolean explicit,
-        OpCallbacks call) {
-        if (obj == null)
-            return null;
-
-        beginOperation(true);
-        try {
-            assertWriteOperation();
-
-            StateManagerImpl sm = getStateManagerImpl(obj, true);
-            if (!_operating.add(obj))
-                return sm;
-
-            int action = processArgument(OpCallbacks.OP_PERSIST, obj, sm, call);
-            if (action == OpCallbacks.ACT_NONE)
-                return sm;
-
-            // ACT_CASCADE
-            if ((action & OpCallbacks.ACT_RUN) == 0) {
-                if (sm != null)
-                    sm.cascadePersist(call);
-                else
-                    cascadeTransient(OpCallbacks.OP_PERSIST, obj, call,
-                        "persist");
-                return sm;
-            }
-
-            // ACT_RUN
-            PersistenceCapable pc;
-            if (sm != null) {
-                if (sm.isDetached())
-                    throw new ObjectExistsException(_loc.get
-                        ("persist-detached", Exceptions.toString(obj))).
-                        setFailedObject(obj);
-
-                if (!sm.isEmbedded()) {
-                    sm.persist();
-                    _cache.persist(sm);
-                    if ((action & OpCallbacks.ACT_CASCADE) != 0)
-                        sm.cascadePersist(call);
-                    return sm;
-                }
-
-                // an embedded field; notify the owner that the value has
-                // changed by becoming independently persistent
-                sm.getOwner().dirty(sm.getOwnerIndex());
-                _cache.persist(sm);
-                pc = sm.getPersistenceCapable();
-            } else {
-                pc = assertPersistenceCapable(obj);
-                if (pc.pcIsDetached() == Boolean.TRUE)
-                    throw new ObjectExistsException(_loc.get
-                        ("persist-detached", Exceptions.toString(obj))).
-                        setFailedObject(obj);
-            }
-
-            ClassMetaData meta = _conf.getMetaDataRepositoryInstance().
-                getMetaData(obj.getClass(), _loader, true);
-            fireLifecycleEvent(obj, null, meta, LifecycleEvent.BEFORE_PERSIST);
-
-            // create id for instance
-            if (id == null) {

[... 7089 lines stripped ...]