/*
 * 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;
        handleCallbackExceptions(_lifeEventManager.fireEvent(src, related, 
            meta, eventType), _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) {
                if (meta.getIdentityType() == ClassMetaData.ID_APPLICATION)
                    id = ApplicationIds.create(pc, meta);
                else if (meta.getIdentityType() == ClassMetaData.ID_UNKNOWN)
                    throw new UserException(_loc.get("meta-unknownid", meta));
                else
                    id = StateManagerId.newInstance(this);
            }

            // make sure we don't already have the instance cached
            checkForDuplicateId(id, obj);

            // if had embedded sm, null it
            if (sm != null)
                pc.pcReplaceStateManager(null);

            // create new sm
            sm = new StateManagerImpl(id, meta, this);
            if ((_flags & FLAG_ACTIVE) != 0) {
                if (explicit)
                    sm.initialize(pc, PCState.PNEW);
                else
                    sm.initialize(pc, PCState.PNEWPROVISIONAL);
            } else
                sm.initialize(pc, PCState.PNONTRANSNEW);
            if ((action & OpCallbacks.ACT_CASCADE) != 0)
                sm.cascadePersist(call);
            return sm;
        } catch (OpenJPAException ke) {
            throw ke;
        } catch (RuntimeException re) {
            throw new GeneralException(re);
        } finally {
            endOperation();
        }
    }

    /**
     * Temporarily manage the given instance in order to cascade the given
     * operation through it.
     */
    private void cascadeTransient(int op, Object obj, OpCallbacks call,
        String errOp) {
        PersistenceCapable pc = assertPersistenceCapable(obj);

        // if using detached state manager, don't replace
        if (pc.pcGetStateManager() != null)
            throw newDetachedException(obj, errOp);

        ClassMetaData meta = _conf.getMetaDataRepositoryInstance().
            getMetaData(obj.getClass(), _loader, true);
        StateManagerImpl sm = new StateManagerImpl(StateManagerId.
            newInstance(this), meta, this);
        sm.initialize(pc, PCState.TLOADED);
        try {
            switch (op) {
                case OpCallbacks.OP_PERSIST:
                    sm.cascadePersist(call);
                    break;
                case OpCallbacks.OP_DELETE:
                    sm.cascadeDelete(call);
                    break;
                case OpCallbacks.OP_REFRESH:
                    sm.gatherCascadeRefresh(call);
                    break;
                default:
                    throw new InternalException(String.valueOf(op));
            }
        }
        finally {
            sm.release(true);
        }
    }

    public void deleteAll(Collection objs, OpCallbacks call) {
        beginOperation(true);
        try {
            assertWriteOperation();

            List exceps = null;
            Object obj;
            for (Iterator itr = objs.iterator(); itr.hasNext();) {
                try {
                    obj = itr.next();
                    if (obj != null)
                        delete(obj, getStateManagerImpl(obj, true), call);
                } catch (UserException ue) {
                    exceps = add(exceps, ue);
                }
            }
            throwNestedExceptions(exceps, false);
        } finally {
            endOperation();
        }
    }

    public void delete(Object obj, OpCallbacks call) {
        if (obj == null)
            return;

        beginOperation(true);
        try {
            assertWriteOperation();
            delete(obj, getStateManagerImpl(obj, true), call);
        } catch (OpenJPAException ke) {
            throw ke;
        } catch (RuntimeException re) {
            throw new GeneralException(re);
        } finally {
            endOperation();
        }
    }

    /**
     * Internal delete.
     */
    void delete(Object obj, StateManagerImpl sm, OpCallbacks call) {
        if (!_operating.add(obj))
            return;

        int action = processArgument(OpCallbacks.OP_DELETE, obj, sm, call);
        if (action == OpCallbacks.ACT_NONE)
            return;

        // ACT_CASCADE
        if ((action & OpCallbacks.ACT_RUN) == 0) {
            if (sm != null)
                sm.cascadeDelete(call);
            else
                cascadeTransient(OpCallbacks.OP_DELETE, obj, call, "delete");
            return;
        }

        // ACT_RUN
        if (sm != null) {
            if (sm.isDetached())
                throw newDetachedException(obj, "delete");
            if ((action & OpCallbacks.ACT_CASCADE) != 0)
                sm.cascadeDelete(call);
            sm.delete();
        } else if (assertPersistenceCapable(obj).pcIsDetached() == Boolean.TRUE)
            throw newDetachedException(obj, "delete");
    }

    /**
     * Throw an exception indicating that the current action can't be
     * performed on a detached object.
     */
    private OpenJPAException newDetachedException(Object obj,
        String operation) {
        throw new UserException(_loc.get("bad-detached-op", operation,
            Exceptions.toString(obj))).setFailedObject(obj);
    }

    public void releaseAll(Collection objs, OpCallbacks call) {
        beginOperation(false);
        try {
            List exceps = null;
            for (Iterator itr = objs.iterator(); itr.hasNext();) {
                try {
                    release(itr.next(), call);
                } catch (UserException ue) {
                    exceps = add(exceps, ue);
                }
            }
            throwNestedExceptions(exceps, false);
        } finally {
            endOperation();
        }
    }

    public void release(Object obj, OpCallbacks call) {
        if (obj == null)
            return;

        beginOperation(false);
        try {
            StateManagerImpl sm = getStateManagerImpl(obj, true);
            int action = processArgument(OpCallbacks.OP_RELEASE, obj, sm, call);

            if (sm == null)
                return;
            if ((action & OpCallbacks.ACT_RUN) != 0 && sm.isPersistent()) {
                boolean pending = sm.isPendingTransactional();
                sm.release(true);
                if (pending)
                    removeFromPendingTransaction(sm);
            }
        }
        catch (OpenJPAException ke) {
            throw ke;
        } catch (RuntimeException re) {
            throw new GeneralException(re);
        } finally {
            endOperation();
        }
    }

    public OpenJPAStateManager embed(Object obj, Object id,
        OpenJPAStateManager owner, ValueMetaData ownerMeta) {
        beginOperation(true);
        try {
            StateManagerImpl orig = getStateManagerImpl(obj, true);
            if (orig != null) {
                // if already embedded, nothing to do
                if (orig.getOwner() == owner && orig.getMetaData().
                    getEmbeddingMetaData() == ownerMeta)
                    return orig;

                // otherwise make sure pc is fully loaded for when we copy its
                // data below
                orig.load(_fc, StateManagerImpl.LOAD_ALL, null, null, false);
            }

            // create new state manager with embedded metadata
            ClassMetaData meta = ownerMeta.getEmbeddedMetaData();
            if (meta == null)
                throw new InternalException(_loc.get("bad-embed", ownerMeta));

            if (id == null)
                id = StateManagerId.newInstance(this);

            StateManagerImpl sm = new StateManagerImpl(id, meta, this);
            sm.setOwner((StateManagerImpl) owner, ownerMeta);

            PersistenceCapable copy;
            PCState state;
            Class type = meta.getDescribedType();
            if (obj != null) {
                // give copy and the original instance the same state manager
                // so that we can copy fields from one to the other
                StateManagerImpl copySM;
                PersistenceCapable pc;
                if (orig == null) {
                    copySM = sm;
                    pc = assertPersistenceCapable(obj);
                    pc.pcReplaceStateManager(sm);
                } else {
                    copySM = orig;
                    pc = orig.getPersistenceCapable();
                }

                try {
                    // copy the instance.  we do this even if it doesn't already
                    // have a state manager in case it is later assigned to a
                    // PC field; at that point it's too late to copy
                    copy = PCRegistry.newInstance(type, copySM, false);
                    int[] fields = new int[meta.getFields().length];
                    for (int i = 0; i < fields.length; i++)
                        fields[i] = i;
                    copy.pcCopyFields(pc, fields);
                    state = PCState.ECOPY;
                    copy.pcReplaceStateManager(null);
                } finally {
                    // if the instance didn't have a state manager to start,
                    // revert it to being transient
                    if (orig == null)
                        pc.pcReplaceStateManager(null);
                }
            } else {
                copy = PCRegistry.newInstance(type, sm, false);
                if ((_flags & FLAG_ACTIVE) != 0 && !_optimistic)
                    state = PCState.ECLEAN;
                else
                    state = PCState.ENONTRANS;
            }

            sm.initialize(copy, state);
            return sm;
        } catch (OpenJPAException ke) {
            throw ke;
        } catch (RuntimeException re) {
            throw new GeneralException(re);
        } finally {
            endOperation();
        }
    }

    /**
     * If not already cached, create an empty copy of the given state
     * manager in the given state.
     */
    OpenJPAStateManager copy(OpenJPAStateManager copy, PCState state) {
        beginOperation(true);
        try {
            assertOpen();
            Object oid = copy.fetchObjectId();
            Class type = copy.getManagedInstance().getClass();
            if (oid == null)
                throw new InternalException();
            // cached instance?
            StateManagerImpl sm = null;
            if (!copy.isEmbedded())
                sm = getStateManagerImplById(oid, true);
            if (sm == null) {
                MetaDataRepository repos = _conf.
                    getMetaDataRepositoryInstance();
                ClassMetaData meta = repos.getMetaData(type, _loader, true);
                // construct a new state manager with all info known
                sm = new StateManagerImpl(oid, meta, this);
                sm.setObjectId(oid);
                sm.initialize(sm.getMetaData().getDescribedType(), state);
            }
            return sm;
        } finally {
            endOperation();
        }
    }
    
    public void refreshAll(Collection objs, OpCallbacks call) {
        if (objs == null || objs.isEmpty())
            return;

        beginOperation(true);
        try {
            assertNontransactionalRead();

            for (Iterator itr = objs.iterator(); itr.hasNext();) 
                gatherCascadeRefresh(itr.next(), call);
            if (_operating.isEmpty())
            	return;
            if (_operating.size() == 1)
            	refreshInternal(_operating.iterator().next(), call);
            else
            	refreshInternal(_operating, call);
        } finally {
            endOperation();
        }
    }

    public void refresh(Object obj, OpCallbacks call) {
        if (obj == null)
            return;

        beginOperation(true);
        try {
            assertNontransactionalRead();

            gatherCascadeRefresh(obj, call);
            if (_operating.isEmpty())
            	return;
            if (_operating.size() == 1)
            	refreshInternal(_operating.iterator().next(), call);
            else
            	refreshInternal(_operating, call);
        } finally {
            endOperation();
        }
    }

    /**
     * Gathers all objects reachable through cascade-refresh relations
     * into the operating set.
     */
    void gatherCascadeRefresh(Object obj, OpCallbacks call) {
        if (obj == null)
            return;
        if (!_operating.add(obj))
            return;

        StateManagerImpl sm = getStateManagerImpl(obj, false);
        int action = processArgument(OpCallbacks.OP_REFRESH, obj, sm, call);
        if ((action & OpCallbacks.ACT_CASCADE) == 0)
            return;

        if (sm != null)
            sm.gatherCascadeRefresh(call);
        else
            cascadeTransient(OpCallbacks.OP_REFRESH, obj, call, "refresh");
    }

    /**
     * This method is called with the full set of objects reachable via
     * cascade-refresh relations from the user-given instances.
     */
    protected void refreshInternal(Collection objs, OpCallbacks call) {
    	if (objs == null || objs.isEmpty())
    		return;
        List exceps = null;
        try {
            // collect instances that need a refresh
            Collection load = null;
            StateManagerImpl sm;
            Object obj;
            for (Iterator itr = objs.iterator(); itr.hasNext();) {
                obj = itr.next();
                if (obj == null)
                    continue;

                try {
                    sm = getStateManagerImpl(obj, true);
                    if ((processArgument(OpCallbacks.OP_REFRESH, obj, sm, call)
                        & OpCallbacks.ACT_RUN) == 0)
                        continue;

                    if (sm != null) {
                        if (sm.isDetached()) 
                            throw newDetachedException(obj, "refresh");
                        else if (sm.beforeRefresh(true)) {
                        	if (load == null)
                        		load = new ArrayList(objs.size());
                            load.add(sm);
                        }
                    } else if (assertPersistenceCapable(obj).pcIsDetached()
                        == Boolean.TRUE)
                        throw newDetachedException(obj, "refresh");
                } catch (OpenJPAException ke) {
                    exceps = add(exceps, ke);
                }
            }

            // refresh all
            if (load != null) {
                Collection failed = _store.loadAll(load, null,
                    StoreManager.FORCE_LOAD_REFRESH, _fc, null);
                if (failed != null && !failed.isEmpty())
                    exceps = add(exceps, newObjectNotFoundException(failed));

                // perform post-refresh transitions and make sure all fetch
                // group fields are loaded
                for (Iterator itr = load.iterator(); itr.hasNext();) {
                    sm = (StateManagerImpl) itr.next();
                    if (failed != null && failed.contains(sm.getId()))
                        continue;

                    try {
                        sm.afterRefresh();
                        sm.load(_fc, StateManagerImpl.LOAD_FGS, null, null, 
                            false);
                    } catch (OpenJPAException ke) {
                        exceps = add(exceps, ke);
                    }
                }
            }

            // now invoke postRefresh on all the instances
            for (Iterator itr = objs.iterator(); itr.hasNext();) {
                try {
                    sm = getStateManagerImpl(itr.next(), true);
                    if (sm != null && !sm.isDetached())
                        fireLifecycleEvent(sm.getManagedInstance(), null,
                            sm.getMetaData(), LifecycleEvent.AFTER_REFRESH);
                } catch (OpenJPAException ke) {
                    exceps = add(exceps, ke);
                }
            }
        } catch (OpenJPAException ke) {
            throw ke;
        } catch (RuntimeException re) {
            throw new GeneralException(re);
        }
        throwNestedExceptions(exceps, false);
    }

    /**
     * Optimization for single-object refresh.
     */
    protected void refreshInternal(Object obj, OpCallbacks call) {
        try {
            StateManagerImpl sm = getStateManagerImpl(obj, true);
            if ((processArgument(OpCallbacks.OP_REFRESH, obj, sm, call)
                & OpCallbacks.ACT_RUN) == 0)
                return;

            if (sm != null) {
                if (sm.isDetached())
                    throw newDetachedException(obj, "refresh");
                else if (sm.beforeRefresh(false)) {
                    sm.load(_fc, StateManagerImpl.LOAD_FGS, null, null, false);
                    sm.afterRefresh();
                }
                fireLifecycleEvent(sm.getManagedInstance(), null,
                    sm.getMetaData(), LifecycleEvent.AFTER_REFRESH);
            } else if (assertPersistenceCapable(obj).pcIsDetached()
                == Boolean.TRUE)
                throw newDetachedException(obj, "refresh");
        } catch (OpenJPAException ke) {
            throw ke;
        } catch (RuntimeException re) {
            throw new GeneralException(re);
        }
    }
    
    
    public void retrieveAll(Collection objs, boolean dfgOnly,
        OpCallbacks call) {
        if (objs == null || objs.isEmpty())
            return;
        if (objs.size() == 1) {
            retrieve(objs.iterator().next(), dfgOnly, call);
            return;
        }

        List exceps = null;
        beginOperation(true);
        try {
            assertOpen();
            assertNontransactionalRead();

            // collect all hollow instances for load
            Object obj;
            Collection load = null;
            StateManagerImpl sm;
            Collection sms = new ArrayList(objs.size());
            for (Iterator itr = objs.iterator(); itr.hasNext();) {
                obj = itr.next();
                if (obj == null)
                    continue;

                try {
                    sm = getStateManagerImpl(obj, true);
                    if ((processArgument(OpCallbacks.OP_RETRIEVE, obj, sm, call)
                        & OpCallbacks.ACT_RUN) == 0)
                        continue;

                    if (sm != null) {
                        if (sm.isDetached())
                            throw newDetachedException(obj, "retrieve");
                        if (sm.isPersistent()) {
                            sms.add(sm);
                            if (sm.getPCState() == PCState.HOLLOW) {
                                if (load == null)
                                    load = new ArrayList();
                                load.add(sm);
                            }
                        }
                    } else if (assertPersistenceCapable(obj).pcIsDetached()
                        == Boolean.TRUE)
                        throw newDetachedException(obj, "retrieve");
                } catch (UserException ue) {
                    exceps = add(exceps, ue);
                }
            }

            // load all hollow instances
            Collection failed = null;
            if (load != null) {
                int mode = (dfgOnly) ? _store.FORCE_LOAD_DFG
                    : _store.FORCE_LOAD_ALL;
                failed = _store.loadAll(load, null, mode, _fc, null);
                if (failed != null && !failed.isEmpty())
                    exceps = add(exceps, newObjectNotFoundException(failed));
            }

            // retrieve all non-failed instances
            for (Iterator itr = sms.iterator(); itr.hasNext();) {
                sm = (StateManagerImpl) itr.next();
                if (failed != null && failed.contains(sm.getId()))
                    continue;

                int mode = (dfgOnly) ? StateManagerImpl.LOAD_FGS
                    : StateManagerImpl.LOAD_ALL;
                try {
                    sm.beforeRead(-1);
                    sm.load(_fc, mode, null, null, false);
                } catch (OpenJPAException ke) {
                    exceps = add(exceps, ke);
                }
            }
        } catch (OpenJPAException ke) {
            throw ke;
        } catch (RuntimeException re) {
            throw new GeneralException(re);
        } finally {
            endOperation();
        }
        throwNestedExceptions(exceps, false);
    }

    public void retrieve(Object obj, boolean dfgOnly, OpCallbacks call) {
        if (obj == null)
            return;

        beginOperation(true);
        try {
            assertOpen();
            assertNontransactionalRead();

            StateManagerImpl sm = getStateManagerImpl(obj, true);
            if ((processArgument(OpCallbacks.OP_RETRIEVE, obj, sm, call)
                & OpCallbacks.ACT_RUN) == 0)
                return;

            if (sm != null) {
                if (sm.isDetached())
                    throw newDetachedException(obj, "retrieve");
                if (sm.isPersistent()) {
                    int mode = (dfgOnly) ? StateManagerImpl.LOAD_FGS
                        : StateManagerImpl.LOAD_ALL;
                    sm.beforeRead(-1);
                    sm.load(_fc, mode, null, null, false);
                }
            } else if (assertPersistenceCapable(obj).pcIsDetached()
                == Boolean.TRUE)
                throw newDetachedException(obj, "retrieve");
        } catch (OpenJPAException ke) {
            throw ke;
        } catch (RuntimeException re) {
            throw new GeneralException(re);
        } finally {
            endOperation();
        }
    }

    public void evictAll(OpCallbacks call) {
        beginOperation(false);
        try {
            // evict all PClean and PNonTrans objects
            Collection c = getManagedStates();
            StateManagerImpl sm;
            for (Iterator itr = c.iterator(); itr.hasNext();) {
                sm = (StateManagerImpl) itr.next();
                if (sm.isPersistent() && !sm.isDirty())
                    evict(sm.getManagedInstance(), call);
            }
        }
        finally {
            endOperation();
        }
    }

    public void evictAll(Collection objs, OpCallbacks call) {
        List exceps = null;
        beginOperation(false);
        try {
            for (Iterator itr = objs.iterator(); itr.hasNext();) {
                try {
                    evict(itr.next(), call);
                } catch (UserException ue) {
                    exceps = add(exceps, ue);
                }
            }
        } finally {
            endOperation();
        }
        throwNestedExceptions(exceps, false);
    }

    public void evictAll(Extent extent, OpCallbacks call) {
        if (extent == null)
            return;

        beginOperation(false);
        try {
            // evict all PClean and PNonTrans objects in extent
            Collection c = getManagedStates();
            StateManagerImpl sm;
            Class cls;
            for (Iterator itr = c.iterator(); itr.hasNext();) {
                sm = (StateManagerImpl) itr.next();
                if (sm.isPersistent() && !sm.isDirty()) {
                    cls = sm.getMetaData().getDescribedType();
                    if (cls == extent.getElementType()
                        || (extent.hasSubclasses()
                        && extent.getElementType().isAssignableFrom(cls)))
                        evict(sm.getManagedInstance(), call);
                }
            }
        } finally {
            endOperation();
        }
    }

    public void evict(Object obj, OpCallbacks call) {
        if (obj == null)
            return;

        beginOperation(false);
        try {
            StateManagerImpl sm = getStateManagerImpl(obj, true);
            if ((processArgument(OpCallbacks.OP_EVICT, obj, sm, call)
                & OpCallbacks.ACT_RUN) == 0)
                return;
            if (sm == null)
                return;

            sm.evict();
            if (_evictDataCache && sm.getObjectId() != null) {
                DataCache cache = sm.getMetaData().getDataCache();
                if (cache != null)
                    cache.remove(sm.getObjectId());
            }
        }
        catch (OpenJPAException ke) {
            throw ke;
        } catch (RuntimeException re) {
            throw new GeneralException(re);
        } finally {
            endOperation();
        }
    }

    public Object detach(Object obj, OpCallbacks call) {
        if (obj == null)
            return null;
        if (call == null)
            call = _call;

        beginOperation(true);
        try {
            return new DetachManager(this, false, call).detach(obj);
        } catch (OpenJPAException ke) {
            throw ke;
        } catch (RuntimeException re) {
            throw new GeneralException(re);
        } finally {
            endOperation();
        }
    }

    public Object[] detachAll(Collection objs, OpCallbacks call) {
        if (objs == null)
            return null;
        if (objs.isEmpty())
            return EMPTY_OBJECTS;
        if (call == null)
            call = _call;

        beginOperation(true);
        try {
            return new DetachManager(this, false, call).detachAll(objs);
        } catch (OpenJPAException ke) {
            throw ke;
        } catch (RuntimeException re) {
            throw new GeneralException(re);
        } finally {
            endOperation();
        }
    }

    public void detachAll(OpCallbacks call) {
        detachAll(call, true);
    }

    public void detachAll(OpCallbacks call, boolean flush) {
        beginOperation(true);
        try {
            // If a flush is desired (based on input parm), then check if the
            //   "dirty" flag is set before calling flush().
            if ((flush) && ((_flags & FLAG_FLUSH_REQUIRED) != 0))
                flush();
            detachAllInternal(call);
        } catch (OpenJPAException ke) {
            throw ke;
        } catch (RuntimeException re) {
            throw new GeneralException(re);
        } finally {
            endOperation();
        }
    }

    private void detachAllInternal(OpCallbacks call) {
        Collection states = getManagedStates();
        StateManagerImpl sm;
        for (Iterator itr = states.iterator(); itr.hasNext();) {
            sm = (StateManagerImpl) itr.next();
            if (!sm.isPersistent())
                itr.remove();
            else if (!sm.getMetaData().isDetachable()) {
                sm.release(true);
                itr.remove();
            }
        }
        if (states.isEmpty())
            return;

        if (call == null)
            call = _call;
        new DetachManager(this, true, call).detachAll
            (new ManagedObjectCollection(states));
    }

    public Object attach(Object obj, boolean copyNew, OpCallbacks call) {
        if (obj == null)
            return null;

        beginOperation(true);
        try {
            // make sure not to try to set rollback only if this fails
            assertWriteOperation();
            try {
                return new AttachManager(this, copyNew, call).attach(obj);
            } catch (OptimisticException oe) {
                setRollbackOnly(oe);
                throw oe.setFatal(true);
            } catch (OpenJPAException ke) {
                throw ke;
            } catch (RuntimeException re) {
                throw new GeneralException(re);
            }
        }
        finally {
            endOperation();
        }
    }

    public Object[] attachAll(Collection objs, boolean copyNew,
        OpCallbacks call) {
        if (objs == null)
            return null;
        if (objs.isEmpty())
            return EMPTY_OBJECTS;

        beginOperation(true);
        try {
            // make sure not to try to set rollback only if this fails
            assertWriteOperation();
            try {
                return new AttachManager(this, copyNew, call).attachAll(objs);
            } catch (OptimisticException oe) {
                setRollbackOnly(oe);
                throw oe.setFatal(true);
            } catch (OpenJPAException ke) {
                throw ke;
            } catch (RuntimeException re) {
                throw new GeneralException(re);
            }
        }
        finally {
            endOperation();
        }
    }

    public void nontransactionalAll(Collection objs, OpCallbacks call) {
        beginOperation(true);
        try {
            List exceps = null;
            for (Iterator itr = objs.iterator(); itr.hasNext();) {
                try {
                    nontransactional(itr.next(), call);
                } catch (UserException ue) {
                    exceps = add(exceps, ue);
                }
            }
            throwNestedExceptions(exceps, false);
        } finally {
            endOperation();
        }
    }

    public void nontransactional(Object obj, OpCallbacks call) {
        if (obj == null)
            return;

        beginOperation(true);
        try {
            StateManagerImpl sm = getStateManagerImpl(obj, true);
            if ((processArgument(OpCallbacks.OP_NONTRANSACTIONAL, obj, sm, call)
                & OpCallbacks.ACT_RUN) == 0)
                return;
            if (sm != null)
                sm.nontransactional();
        } catch (OpenJPAException ke) {
            throw ke;
        } catch (RuntimeException re) {
            throw new GeneralException(re);
        } finally {
            endOperation();
        }
    }

    /**
     * Make the given instances transactional.
     */
    public void transactionalAll(Collection objs, boolean updateVersion,
        OpCallbacks call) {
        if (objs.isEmpty())
            return;
        if (objs.size() == 1) {
            transactional(objs.iterator().next(), updateVersion, call);
            return;
        }

        beginOperation(true);
        try {
            // collect all hollow instances for load, and make unmananged
            // instances transient-transactional
            Collection load = null;
            Object obj;
            StateManagerImpl sm;
            ClassMetaData meta;
            Collection sms = new ArrayList(objs.size());
            List exceps = null;
            for (Iterator itr = objs.iterator(); itr.hasNext();) {
                obj = itr.next();
                if (obj == null)
                    continue;

                try {
                    sm = getStateManagerImpl(obj, true);
                    if ((processArgument(OpCallbacks.OP_TRANSACTIONAL, obj, sm,
                        call) & OpCallbacks.ACT_RUN) == 0)
                        continue;

                    if (sm == null) {
                        // manage transient instance
                        meta = _conf.getMetaDataRepositoryInstance().
                            getMetaData(obj.getClass(), _loader, true);

                        sm = new StateManagerImpl
                            (StateManagerId.newInstance(this), meta, this);
                        sm.initialize(assertPersistenceCapable(obj),
                            PCState.TCLEAN);
                    } else if (sm.isPersistent()) {
                        assertActiveTransaction();
                        sms.add(sm);
                        if (sm.getPCState() == PCState.HOLLOW) {
                            if (load == null)
                                load = new ArrayList();
                            load.add(sm);
                        }

                        sm.setCheckVersion(true);
                        if (updateVersion)
                            sm.setUpdateVersion(true);
                        _flags |= FLAG_FLUSH_REQUIRED; // version check/up
                    }
                }
                catch (UserException ue) {
                    exceps = add(exceps, ue);
                }
            }

            // load all hollow instances
            Collection failed = null;
            if (load != null) {
                failed = _store.loadAll(load, null, _store.FORCE_LOAD_NONE,
                    _fc, null);
                if (failed != null && !failed.isEmpty())
                    exceps = add(exceps,
                        newObjectNotFoundException(failed));
            }

            transactionalStatesAll(sms, failed, exceps);
        } catch (OpenJPAException ke) {
            throw ke;
        } catch (RuntimeException re) {
            throw new GeneralException(re);
        } finally {
            endOperation();
        }
    }

    /**
     * Make the given instances transactional.
     */
    public void transactional(Object obj, boolean updateVersion,
        OpCallbacks call) {
        if (obj == null)
            return;

        beginOperation(true);
        try {
            StateManagerImpl sm = getStateManagerImpl(obj, true);
            if ((processArgument(OpCallbacks.OP_TRANSACTIONAL, obj, sm, call)
                & OpCallbacks.ACT_RUN) == 0)
                return;

            if (sm != null && sm.isPersistent()) {
                assertActiveTransaction();
                sm.transactional();
                sm.load(_fc, StateManagerImpl.LOAD_FGS, null, null, false);
                sm.setCheckVersion(true);
                if (updateVersion)
                    sm.setUpdateVersion(true);
                _flags |= FLAG_FLUSH_REQUIRED; // version check/up
            } else if (sm == null) {
                // manage transient instance
                ClassMetaData meta = _conf.getMetaDataRepositoryInstance().
                    getMetaData(obj.getClass(), _loader, true);
                Object id = StateManagerId.newInstance(this);
                sm = new StateManagerImpl(id, meta, this);
                sm.initialize(assertPersistenceCapable(obj),
                    PCState.TCLEAN);
            }
        }
        catch (OpenJPAException ke) {
            throw ke;
        } catch (RuntimeException re) {
            throw new GeneralException(re);
        } finally {
            endOperation();
        }
    }

    /**
     * Transition the given state managers to transactional.
     */
    private void transactionalStatesAll(Collection sms, Collection failed,
        List exceps) {
        // make instances transactional and make sure they are loaded
        StateManagerImpl sm;
        for (Iterator itr = sms.iterator(); itr.hasNext();) {
            sm = (StateManagerImpl) itr.next();
            if (failed != null && failed.contains(sm.getId()))
                continue;

            try {
                sm.transactional();
                sm.load(_fc, StateManagerImpl.LOAD_FGS, null, null, false);
            } catch (OpenJPAException ke) {
                exceps = add(exceps, ke);
            }
        }
        throwNestedExceptions(exceps, false);
    }

    /////////////////
    // Extent, Query
    /////////////////

    public Extent newExtent(Class type, boolean subclasses) {
        return newExtent(type, subclasses, null);
    }

    private Extent newExtent(Class type, boolean subclasses,
        FetchConfiguration fetch) {
        beginOperation(true);
        try {
            ExtentImpl extent = new ExtentImpl(this, type, subclasses, fetch);
            if (_extents == null)
                _extents = new ReferenceHashSet(ReferenceHashSet.WEAK);
            _extents.add(extent);

            return extent;
        } catch (OpenJPAException ke) {
            throw ke;
        } catch (RuntimeException re) {
            throw new GeneralException(re);
        } finally {
            endOperation();
        }
    }

    public Iterator extentIterator(Class type, boolean subclasses,
        FetchConfiguration fetch, boolean ignoreChanges) {
        Extent extent = newExtent(type, subclasses, fetch);
        extent.setIgnoreChanges(ignoreChanges);
        return extent.iterator();
    }

    public Query newQuery(String lang, Class cls, Object query) {
        Query q = newQuery(lang, query);
        q.setCandidateType(cls, true);
        return q;
    }

    public Query newQuery(String lang, Object query) {
        // common mistakes
        if (query instanceof Extent || query instanceof Class)
            throw new UserException(_loc.get("bad-new-query"));

        beginOperation(false);
        try {
            StoreQuery sq = _store.newQuery(lang);
            if (sq == null) {
                ExpressionParser ep = QueryLanguages.parserForLanguage(lang);
                if (ep != null)
                    sq = new ExpressionStoreQuery(ep);
                else if (QueryLanguages.LANG_METHODQL.equals(lang))
                    sq = new MethodStoreQuery();
                else
                    throw new UnsupportedException(lang);
            }

            Query q = newQueryImpl(lang, sq);
            q.setIgnoreChanges(_ignoreChanges);
            if (query != null)
                q.setQuery(query);

            // track queries
            if (_queries == null)
                _queries = new ReferenceHashSet(ReferenceHashSet.WEAK);
            _queries.add(q);
            return q;
        } catch (OpenJPAException ke) {
            throw ke;
        } catch (RuntimeException re) {
            throw new GeneralException(re);
        } finally {
            endOperation();
        }
    }

    /**
     * Create a new query.
     */
    protected QueryImpl newQueryImpl(String lang, StoreQuery sq) {
        return new QueryImpl(this, lang, sq);
    }

    public Seq getIdentitySequence(ClassMetaData meta) {
        if (meta == null)
            return null;
        return getSequence(meta, null);
    }

    public Seq getValueSequence(FieldMetaData fmd) {
        if (fmd == null)
            return null;
        return getSequence(fmd.getDefiningMetaData(), fmd);
    }

    /**
     * Return a sequence for the given class and optional field.
     */
    private Seq getSequence(ClassMetaData meta, FieldMetaData fmd) {
        // get sequence strategy from metadata
        int strategy;
        if (fmd == null)
            strategy = meta.getIdentityStrategy();
        else
            strategy = fmd.getValueStrategy();

        // we can handle non-native strategies without the store manager
        switch (strategy) {
            case ValueStrategies.UUID_HEX:
                return UUIDHexSeq.getInstance();
            case ValueStrategies.UUID_STRING:
                return UUIDStringSeq.getInstance();
            case ValueStrategies.UUID_TYPE4_HEX:
                return UUIDType4HexSeq.getInstance();
            case ValueStrategies.UUID_TYPE4_STRING:
                return UUIDType4StringSeq.getInstance();
            case ValueStrategies.SEQUENCE:
                SequenceMetaData smd = (fmd == null)
                    ? meta.getIdentitySequenceMetaData()
                    : fmd.getValueSequenceMetaData();
                return smd.getInstance(_loader);
            default:
                // use store manager for native sequence
                if (fmd == null) {
                    // this will return a sequence even for app id classes,
                    // which is what we want for backwards-compatibility
                    return _store.getDataStoreIdSequence(meta);
                }
                return _store.getValueSequence(fmd);
        }
    }

    ///////////
    // Locking
    ///////////

    public void lock(Object obj, OpCallbacks call) {
        if (obj == null)
            return;

        beginOperation(true); // have to sync or lock level always NONE
        try {
            lock(obj, _fc.getWriteLockLevel(), _fc.getLockTimeout(), call);
        } finally {
            endOperation();
        }
    }

    public void lock(Object obj, int level, int timeout, OpCallbacks call) {
        if (obj == null)
            return;

        beginOperation(true);
        try {
            assertActiveTransaction();

            StateManagerImpl sm = getStateManagerImpl(obj, true);
            if ((processArgument(OpCallbacks.OP_LOCK, obj, sm, call)
                & OpCallbacks.ACT_RUN) == 0)
                return;
            if (sm == null || !sm.isPersistent())
                return;

            _lm.lock(sm, level, timeout, null);
            sm.readLocked(level, level); // use same level for future write
        } catch (OpenJPAException ke) {
            throw ke;
        } catch (RuntimeException re) {
            throw new GeneralException(re);
        } finally {
            endOperation();
        }
    }

    public void lockAll(Collection objs, OpCallbacks call) {
        if (objs.isEmpty())
            return;

        beginOperation(true); // have to sync or lock level always NONE
        try {
            lockAll(objs, _fc.getWriteLockLevel(), _fc.getLockTimeout(),
                call);
        } finally {
            endOperation();
        }
    }

    public void lockAll(Collection objs, int level, int timeout,
        OpCallbacks call) {
        if (objs.isEmpty())
            return;
        if (objs.size() == 1) {
            lock(objs.iterator().next(), level, timeout, call);
            return;
        }

        beginOperation(true);
        try {
            assertActiveTransaction();

            Collection sms = new ArrayList(objs.size());
            Object obj;
            StateManagerImpl sm;
            for (Iterator itr = objs.iterator(); itr.hasNext();) {
                obj = itr.next();
                if (obj == null)
                    continue;

                sm = getStateManagerImpl(obj, true);
                if ((processArgument(OpCallbacks.OP_LOCK, obj, sm, call)
                    & OpCallbacks.ACT_RUN) == 0)
                    continue;
                if (sm != null && sm.isPersistent())
                    sms.add(sm);
            }

            _lm.lockAll(sms, level, timeout, null);
            for (Iterator itr = sms.iterator(); itr.hasNext();)
                ((StateManagerImpl) itr.next()).readLocked(level, level);
        } catch (OpenJPAException ke) {
            throw ke;
        } catch (RuntimeException re) {
            throw new GeneralException(re);
        } finally {
            endOperation();
        }
    }

    //////////////
    // Connection
    //////////////

    public boolean cancelAll() {
        // this method does not lock, since we want to allow a different
        // thread to be able to cancel on a locked-up persistence manager

        assertOpen();
        try {
            // if we're flushing, have to set rollback only -- do this before we
            // attempt to cancel, because otherwise the cancel might case the
            // transaction to complete before we have a chance to set the
            // rollback only flag
            if ((_flags & FLAG_STORE_FLUSHING) != 0)
                setRollbackOnlyInternal(new UserException());
            return _store.cancelAll();
        } catch (OpenJPAException ke) {
            throw ke;
        } catch (RuntimeException re) {
            throw new StoreException(re);
        }
    }

    public Object getConnection() {
        assertOpen();
        if (!_conf.supportedOptions().contains
            (_conf.OPTION_DATASTORE_CONNECTION))
            throw new UnsupportedException(_loc.get("conn-not-supported"));

        return _store.getClientConnection();
    }

    public boolean hasConnection() {
        assertOpen();
        return (_flags & FLAG_RETAINED_CONN) != 0;
    }

    /**
     * Tell store to retain connection if we haven't already.
     */
    private void retainConnection() {
        if ((_flags & FLAG_RETAINED_CONN) == 0) {
            _store.retainConnection();
            _flags |= FLAG_RETAINED_CONN;
        }
    }

    /**
     * Tell store to release connection if we have retained one.
     */
    private void releaseConnection() {
        if ((_flags & FLAG_RETAINED_CONN) != 0) {
            _store.releaseConnection();
            _flags &= ~FLAG_RETAINED_CONN;
        }
    }

    /////////
    // Cache
    /////////

    public Collection getManagedObjects() {
        beginOperation(false);
        try {
            return new ManagedObjectCollection(getManagedStates());
        } finally {
            endOperation();
        }
    }

    public Collection getTransactionalObjects() {
        beginOperation(false);
        try {
            return new ManagedObjectCollection(getTransactionalStates());
        } finally {
            endOperation();
        }
    }

    public Collection getPendingTransactionalObjects() {
        beginOperation(false);
        try {
            return new ManagedObjectCollection
                (getPendingTransactionalStates());
        } finally {
            endOperation();
        }
    }

    public Collection getDirtyObjects() {
        beginOperation(false);
        try {
            return new ManagedObjectCollection(getDirtyStates());
        } finally {
            endOperation();
        }
    }

    public boolean getOrderDirtyObjects() {
        return _orderDirty;
    }

    public void setOrderDirtyObjects(boolean order) {
        _orderDirty = order;
    }

    /**
     * Return a copy of all managed state managers.
     */
    protected Collection getManagedStates() {
        return _cache.copy();
    }

    /**
     * Return a copy of all transactional state managers.
     */
    protected Collection getTransactionalStates() {
        if (!hasTransactionalObjects())
            return Collections.EMPTY_LIST;
        return _transCache.copy();
    }

    /**
     * Whether or not there are any transactional objects in the current
     * persistence context. If there are any instances with untracked state,
     * this method will cause those instances to be scanned.
     */
    private boolean hasTransactionalObjects() {
        _cache.dirtyCheck();
        return _transCache != null;
    }

    /**
     * Return a copy of all dirty state managers.
     */
    protected Collection getDirtyStates() {
        if (!hasTransactionalObjects())
            return Collections.EMPTY_LIST;

        return _transCache.copyDirty();
    }

    /**
     * Return a copy of all state managers which will become
     * transactional upon the next transaction.
     */
    protected Collection getPendingTransactionalStates() {
        if (_pending == null)
            return Collections.EMPTY_LIST;
        return new ArrayList(_pending);
    }

    /**
     * Set the cached StateManager for the instance that had the given oid.
     * This method must not be called multiple times for new instances.
     *
     * @param id the id previously used by the instance
     * @param sm the state manager for the instance; if the state
     * manager is transient, we'll stop managing the instance;
     * if it has updated its oid, we'll re-cache under the new oid
     * @param status one of our STATUS constants describing why we're
     * setting the state manager
     */
    void setStateManager(Object id, StateManagerImpl sm, int status) {
        lock();
        try {
            switch (status) {
                case STATUS_INIT:
                    _cache.add(sm);
                    break;
                case STATUS_TRANSIENT:
                    _cache.remove(id, sm);
                    break;
                case STATUS_OID_ASSIGN:
                    assignObjectId(_cache, id, sm);
                    break;
                case STATUS_COMMIT_NEW:
                    _cache.commitNew(id, sm);
                    break;
                default:
                    throw new InternalException();
            }
        }
        finally {
            unlock();
        }
    }

    /**
     * Notify the broker that the given state manager should
     * be added to the set of instances involved in the current transaction.
     */
    void addToTransaction(StateManagerImpl sm) {
        // we only add clean instances now; dirty instances are added in
        // the setDirty callback
        if (sm.isDirty())
            return;

        lock();
        try {
            if (!hasTransactionalObjects())
                _transCache = new TransactionalCache(_orderDirty);
            _transCache.addClean(sm);
        } finally {
            unlock();
        }
    }

    /**
     * Notify the persistence manager that the given state manager should
     * be removed from the set of instances involved in the current transaction.
     */
    void removeFromTransaction(StateManagerImpl sm) {
        lock();
        try {
            if (_transCache != null)
                // intentional direct access; we don't want to recompute
                // dirtiness while removing instances from the transaction
                _transCache.remove(sm);
            if (_derefCache != null && !sm.isPersistent())
                _derefCache.remove(sm);
        } finally {
            unlock();
        }
    }

    /**
     * Notification that the given instance has been dirtied. This
     * notification is given when an object first transitions to a dirty state,
     * and every time the object is modified by the user thereafter.
     */
    void setDirty(StateManagerImpl sm, boolean firstDirty) {
        if (sm.isPersistent())
            _flags |= FLAG_FLUSH_REQUIRED;

        if (_savepoints != null && !_savepoints.isEmpty()) {
            if (_savepointCache == null)
                _savepointCache = new HashSet();
            _savepointCache.add(sm);
        }

        if (firstDirty && sm.isTransactional()) {
            lock();
            try {
                // cache dirty instance
                if (!hasTransactionalObjects())
                    _transCache = new TransactionalCache(_orderDirty);
                _transCache.addDirty(sm);

                // also record that the class is dirty
                if (sm.isNew()) {
                    if (_persistedClss == null)
                        _persistedClss = new HashSet();
                    _persistedClss.add(sm.getMetaData().getDescribedType());
                } else if (sm.isDeleted()) {
                    if (_deletedClss == null)
                        _deletedClss = new HashSet();
                    _deletedClss.add(sm.getMetaData().getDescribedType());
                } else {
                    if (_updatedClss == null)
                        _updatedClss = new HashSet();
                    _updatedClss.add(sm.getMetaData().getDescribedType());
                }

                // if tracking changes and this instance wasn't already dirty,
                // add to changed set; we use this for detecting instances that
                // enter the transaction during pre store
                if ((_flags & FLAG_PRESTORING) != 0) {
                    if (_transAdditions == null)
                        _transAdditions = new HashSet();
                    _transAdditions.add(sm);
                }
            } finally {
                unlock();
            }
        }
    }

    /**
     * Notify the broker that the given state manager should
     * be added to the set of instances that will become transactional
     * on the next transaction
     */
    void addToPendingTransaction(StateManagerImpl sm) {
        lock();
        try {
            if (_pending == null)
                _pending = new HashSet();
            _pending.add(sm);
        } finally {
            unlock();
        }
    }

    /**
     * Notify the persistence manager that the given state manager should
     * be removed from the set of instances involved in the next transaction.
     */
    void removeFromPendingTransaction(StateManagerImpl sm) {
        lock();
        try {
            if (_pending != null)
                _pending.remove(sm);
            if (_derefCache != null && !sm.isPersistent())
                _derefCache.remove(sm);
        } finally {
            unlock();
        }
    }

    /**
     * Add a dereferenced dependent object to the persistence manager's cache.
     * On flush, these objects will be deleted.
     */
    void addDereferencedDependent(StateManagerImpl sm) {
        lock();
        try {
            // if we're in the middle of flush and introducing more derefs
            // via instance callbacks, add them to the special additions set
            if ((_flags & FLAG_DEREFDELETING) != 0) {
                if (_derefAdditions == null)
                    _derefAdditions = new HashSet();
                _derefAdditions.add(sm);
            } else {
                if (_derefCache == null)
                    _derefCache = new HashSet();
                _derefCache.add(sm);
            }
        }
        finally {
            unlock();
        }
    }

    /**
     * Remove the given previously dereferenced dependent object from the
     * cache. It is now referenced.
     */
    void removeDereferencedDependent(StateManagerImpl sm) {
        lock();
        try {
            boolean removed = false;
            if (_derefAdditions != null)
                removed = _derefAdditions.remove(sm);
            if (!removed && (_derefCache == null || !_derefCache.remove(sm)))
                throw new InvalidStateException(_loc.get("not-derefed",
                    Exceptions.toString(sm.getManagedInstance()))).
                    setFailedObject(sm.getManagedInstance()).
                    setFatal(true);
        } finally {
            unlock();
        }
    }

    public void dirtyType(Class cls) {
        if (cls == null)
            return;

        beginOperation(false);
        try {
            if (_updatedClss == null)
                _updatedClss = new HashSet();
            _updatedClss.add(cls);
        } finally {
            endOperation();
        }
    }

    public Collection getPersistedTypes() {
        if (_persistedClss == null || _persistedClss.isEmpty())
            return Collections.EMPTY_LIST;
        return Collections.unmodifiableCollection(_persistedClss);
    }

    public Collection getUpdatedTypes() {
        if (_updatedClss == null || _updatedClss.isEmpty())
            return Collections.EMPTY_LIST;
        return Collections.unmodifiableCollection(_updatedClss);
    }

    public Collection getDeletedTypes() {
        if (_deletedClss == null || _deletedClss.isEmpty())
            return Collections.EMPTY_LIST;
        return Collections.unmodifiableCollection(_deletedClss);
    }

    ///////////
    // Closing
    ///////////

    public boolean isClosed() {
        return _closed;
    }

    public boolean isCloseInvoked() {
        return _closed || (_flags & FLAG_CLOSE_INVOKED) != 0;
    }

    public void close() {
        beginOperation(false);
        try {
            // throw an exception if closing in an active local trans
            if (!_managed && (_flags & FLAG_ACTIVE) != 0)
                throw new InvalidStateException(_loc.get("active"));

            // only close if not active; if active managed trans wait
            // for completion
            _flags |= FLAG_CLOSE_INVOKED;

            if ((_flags & FLAG_ACTIVE) == 0)
                free();
        } finally {
            endOperation();
        }
    }

    /**
     * Free the resources used by this persistence manager.
     */
    protected void free() {
        RuntimeException err = null;
        if ((_autoDetach & DETACH_CLOSE) != 0) {
            try {
                detachAllInternal(_call);
            } catch (RuntimeException re) {
                err = re;
            }
        }

        _sync = null;
        _userObjects = null;
        _cache.clear();
        _transCache = null;
        _persistedClss = null;
        _updatedClss = null;
        _deletedClss = null;
        _derefCache = null;
        _pending = null;
        _loader = null;
        _transEventManager = null;
        _lifeEventManager = null;

        OpenJPASavepoint save;
        while (_savepoints != null && !_savepoints.isEmpty()) {
            save =
                (OpenJPASavepoint) _savepoints.remove(_savepoints.size() - 1);
            save.release(false);
        }
        _savepoints = null;
        _savepointCache = null;

        if (_queries != null) {
            for (Iterator itr = _queries.iterator(); itr.hasNext();) {
                try {
                    ((Query) itr.next()).closeResources();
                } catch (RuntimeException re) {
                }
            }
            _queries = null;
        }

        if (_extents != null) {
            Extent e;
            for (Iterator itr = _extents.iterator(); itr.hasNext();) {
                e = (Extent) itr.next();
                try {
                    e.closeAll();
                } catch (RuntimeException re) {
                }
            }
            _extents = null;
        }

        try { releaseConnection(); } catch (RuntimeException re) {}

        _lm.close();
        _store.close();
        _flags = 0;
        _closed = true;
        if (_log.isTraceEnabled())
            _closedException = new IllegalStateException();

        _factory.releaseBroker(this);

        if (err != null)
            throw err;
    }

    ///////////////////
    // Synchronization
    ///////////////////

    public void lock() {
        if (_lock != null)
            _lock.lock();
    }

    public void unlock() {
        if (_lock != null)
            _lock.unlock();
    }

    ////////////////////
    // State management
    ////////////////////

    public Object newInstance(Class cls) {
        assertOpen();

        if (!cls.isInterface() && Modifier.isAbstract(cls.getModifiers()))
            throw new UnsupportedOperationException(_loc.get
                ("new-abstract", cls).getMessage());

        // 1.5 doesn't initialize classes without a true Class.forName
        if (!PCRegistry.isRegistered(cls)) {
            try {
                Class.forName(cls.getName(), true, 
                    (ClassLoader) AccessController.doPrivileged(
                        J2DoPrivHelper.getClassLoaderAction(cls)));
            } catch (Throwable t) {
            }
        }

        if (_conf.getMetaDataRepositoryInstance().getMetaData(cls,
            getClassLoader(), false) == null)
            throw new IllegalArgumentException(
                _loc.get("no-interface-metadata", cls.getName()).getMessage());

        try {
            return PCRegistry.newInstance(cls, null, false);
        } catch (IllegalStateException ise) {
            IllegalArgumentException iae =
                new IllegalArgumentException(ise.getMessage());
            iae.setStackTrace(ise.getStackTrace());
            throw iae;
        }
    }

    public Object getObjectId(Object obj) {
        assertOpen();
        if (ImplHelper.isManageable(obj))
            return (ImplHelper.toPersistenceCapable(obj, _conf))
                .pcFetchObjectId();
        return null;
    }

    public int getLockLevel(Object o) {
        assertOpen();
        if (o == null)
            return LockLevels.LOCK_NONE;

        OpenJPAStateManager sm = getStateManager(o);
        if (sm == null)
            return LockLevels.LOCK_NONE;
        return getLockManager().getLockLevel(sm);
    }

    public Object getVersion(Object obj) {
        assertOpen();
        if (ImplHelper.isManageable(obj))
            return (ImplHelper.toPersistenceCapable(obj, _conf)).pcGetVersion();
        return null;
    }

    public boolean isDirty(Object obj) {
        assertOpen();
        if (ImplHelper.isManageable(obj)) {
            PersistenceCapable pc = ImplHelper.toPersistenceCapable(obj, _conf);
            return pc.pcIsDirty();
        }
        return false;
    }

    public boolean isTransactional(Object obj) {
        assertOpen();
        if (ImplHelper.isManageable(obj))
            return (ImplHelper.toPersistenceCapable(obj, _conf))
                .pcIsTransactional();
        return false;
    }

    public boolean isPersistent(Object obj) {
        assertOpen();
        if (ImplHelper.isManageable(obj))
            return (ImplHelper.toPersistenceCapable(obj, _conf)).pcIsPersistent();
        return false;
    }

    public boolean isNew(Object obj) {
        assertOpen();
        if (ImplHelper.isManageable(obj))
            return (ImplHelper.toPersistenceCapable(obj, _conf)).pcIsNew();
        return false;
    }

    public boolean isDeleted(Object obj) {
        assertOpen();
        if (ImplHelper.isManageable(obj))
            return (ImplHelper.toPersistenceCapable(obj, _conf)).pcIsDeleted();
        return false;
    }

    public boolean isDetached(Object obj) {
        if (!(ImplHelper.isManageable(obj)))
            return false;

        PersistenceCapable pc = ImplHelper.toPersistenceCapable(obj, _conf);
        Boolean detached = pc.pcIsDetached();
        if (detached != null)
            return detached.booleanValue();

        // last resort: instance is detached if it has a store record
        ClassMetaData meta = _conf.getMetaDataRepositoryInstance().
            getMetaData(ImplHelper.getManagedInstance(pc).getClass(),
                _loader, true);
        Object oid = ApplicationIds.create(pc, meta);
        if (oid == null)
            return false;
        return find(oid, null, EXCLUDE_ALL, null, 0) != null;
    }

    public OpenJPAStateManager getStateManager(Object obj) {
        assertOpen();
        return getStateManagerImpl(obj, false);
    }

    /**
     * Return the state manager for the given instance, or null.
     *
     * @param assertThisContext if true, thow an exception if the given
     * object is managed by another broker
     */
    protected StateManagerImpl getStateManagerImpl(Object obj,
        boolean assertThisContext) {
        if (ImplHelper.isManageable(obj)) {
            PersistenceCapable pc = ImplHelper.toPersistenceCapable(obj, _conf);
            if (pc.pcGetGenericContext() == this)
                return (StateManagerImpl) pc.pcGetStateManager();
            if (assertThisContext && pc.pcGetGenericContext() != null)
                throw new UserException(_loc.get("not-managed",
                    Exceptions.toString(obj))).setFailedObject(obj);
        }
        return null;
    }

    /**
     * Return the state manager for the given oid.
     *
     * @param allowNew if true, objects made persistent in the current
     * transaction will be included in the search; if
     * multiple new objects match the given oid, it is
     * undefined which will be returned
     */
    protected StateManagerImpl getStateManagerImplById(Object oid,
        boolean allowNew) {
        return _cache.getById(oid, allowNew);
    }

    /**
     * Return the given instance as a {@link PersistenceCapable}.
     * If the instance is not manageable throw the proper exception.
     */
    protected PersistenceCapable assertPersistenceCapable(Object obj) {
        if (obj == null)
            return null;
        if (ImplHelper.isManageable(obj))
            return ImplHelper.toPersistenceCapable(obj, _conf);

        // check for different instances of the PersistenceCapable interface
        // and throw a better error that mentions the class loaders
        Class[] intfs = obj.getClass().getInterfaces();
        for (int i = 0; intfs != null && i < intfs.length; i++) {
            if (intfs[i].getName().equals(PersistenceCapable.class.getName())) {
                throw new UserException(_loc.get("pc-loader-different",
                    Exceptions.toString(obj),
                    (ClassLoader) AccessController.doPrivileged(
                        J2DoPrivHelper.getClassLoaderAction(
                            PersistenceCapable.class)),
                    (ClassLoader) AccessController.doPrivileged(
                        J2DoPrivHelper.getClassLoaderAction(intfs[i]))))
                    .setFailedObject(obj);
            }
        }

        // not enhanced
        throw new UserException(_loc.get("pc-cast",
            Exceptions.toString(obj))).setFailedObject(obj);
    }

    /////////
    // Utils
    /////////
    /**
     * Throw an exception if the context is closed.  The exact message and
     * content of the exception varies whether TRACE is enabled or not.
     */
    public void assertOpen() {
        if (_closed) {
            if (_closedException == null)  // TRACE not enabled
                throw new InvalidStateException(_loc.get("closed-notrace"))
                        .setFatal(true);
            else {
                OpenJPAException e = new InvalidStateException(
                    _loc.get("closed"), _closedException).setFatal(true);
                e.setCause(_closedException);
                throw e;
            }
        }
    }

    public void assertActiveTransaction() {
        if ((_flags & FLAG_ACTIVE) == 0)
            throw new NoTransactionException(_loc.get("not-active"));
    }

    /**
     * Throw exception if a transaction-related operation is attempted and
     * no transaction is active.
     */
    private void assertTransactionOperation() {
        if ((_flags & FLAG_ACTIVE) == 0)
            throw new InvalidStateException(_loc.get("not-active"));
    }

    public void assertNontransactionalRead() {
        if ((_flags & FLAG_ACTIVE) == 0 && !_nontransRead)
            throw new InvalidStateException(_loc.get("non-trans-read"));
    }

    public void assertWriteOperation() {
        if ((_flags & FLAG_ACTIVE) == 0 && (!_nontransWrite
            || (_autoDetach & DETACH_NONTXREAD) != 0))
            throw new NoTransactionException(_loc.get("write-operation"));
    }

    /**
     * Return an object not found exception containing nested exceptions
     * for all of the given failed objects.
     */
    private static ObjectNotFoundException newObjectNotFoundException
        (Collection failed) {
        Throwable[] t = new Throwable[failed.size()];
        int idx = 0;
        for (Iterator itr = failed.iterator(); itr.hasNext(); idx++)
            t[idx] = new ObjectNotFoundException(itr.next());
        return new ObjectNotFoundException(failed, t);
    }

    ////////////////////////////////
    // FindCallbacks implementation
    ////////////////////////////////

    public Object processArgument(Object oid) {
        return oid;
    }

    public Object processReturn(Object oid, OpenJPAStateManager sm) {
        return (sm == null) ? null : sm.getManagedInstance();
    }

    private void writeObject(ObjectOutputStream out) throws IOException {
        assertOpen();
        lock();
        try {
            if (isActive()) {
                if (!getOptimistic())
                    throw new InvalidStateException(
                        _loc.get("cant-serialize-pessimistic-broker"));
                if (hasFlushed())
                    throw new InvalidStateException(
                        _loc.get("cant-serialize-flushed-broker"));
                if (hasConnection())
                    throw new InvalidStateException(
                        _loc.get("cant-serialize-connected-broker"));
            }

            try {
                _isSerializing = true;
                out.writeObject(_factory.getPoolKey());
                out.defaultWriteObject();
            } finally {
                _isSerializing = false;
            }
        } finally {
            unlock();
        }
    }

    private void readObject(ObjectInputStream in)
        throws ClassNotFoundException, IOException {
        Object factoryKey = in.readObject();
        AbstractBrokerFactory factory =
            AbstractBrokerFactory.getPooledFactoryForKey(factoryKey);

        // this needs to happen before defaultReadObject so that it's
        // available for calls to broker.getConfiguration() during
        // StateManager deserialization
        _conf = factory.getConfiguration();
        
        in.defaultReadObject();
        factory.initializeBroker(_managed, _connRetainMode, this, true);

        // re-initialize the lock if needed.
        setMultithreaded(_multithreaded);

        if (isActive() && _runtime instanceof LocalManagedRuntime)
            ((LocalManagedRuntime) _runtime).begin();
    }

    /**
     * Whether or not this broker is in the midst of being serialized.
     *
     * @since 1.1.0 
     */
    boolean isSerializing() {
        return _isSerializing;
    }

    /**
     * Transactional cache that holds soft refs to clean instances.
     */
    static class TransactionalCache
        implements Set, Serializable {

        private final boolean _orderDirty;
        private Set _dirty = null;
        private Set _clean = null;

        public TransactionalCache(boolean orderDirty) {
            _orderDirty = orderDirty;
        }

        /**
         * Return a copy of all transactional state managers.
         */
        public Collection copy() {
            if (isEmpty())
                return Collections.EMPTY_LIST;

            // size may not be entirely accurate due to refs expiring, so
            // manually copy each object; doesn't matter this way if size too
            // big by some
            List copy = new ArrayList(size());
            if (_dirty != null)
                for (Iterator itr = _dirty.iterator(); itr.hasNext();)
                    copy.add(itr.next());
            if (_clean != null)
                for (Iterator itr = _clean.iterator(); itr.hasNext();)
                    copy.add(itr.next());
            return copy;
        }

        /**
         * Return a copy of all dirty state managers.
         */
        public Collection copyDirty() {
            if (_dirty == null || _dirty.isEmpty())
                return Collections.EMPTY_LIST;
            return new ArrayList(_dirty);
        }

        /**
         * Transfer the given instance from the dirty cache to the clean cache.
         */
        public void flushed(StateManagerImpl sm) {
            if (sm.isDirty() && _dirty != null && _dirty.remove(sm))
                addCleanInternal(sm);
        }

        /**
         * Add the given instance to the clean cache.
         */
        public void addClean(StateManagerImpl sm) {
            if (addCleanInternal(sm) && _dirty != null)
                _dirty.remove(sm);
        }

        private boolean addCleanInternal(StateManagerImpl sm) {
            if (_clean == null)
                _clean = new ReferenceHashSet(ReferenceHashSet.SOFT);
            return _clean.add(sm);
        }

        /**
         * Add the given instance to the dirty cache.
         */
        public void addDirty(StateManagerImpl sm) {
            if (_dirty == null) {
                if (_orderDirty)
                    _dirty = MapBackedSet.decorate(new LinkedMap());
                else
                    _dirty = new HashSet();
            }
            if (_dirty.add(sm))
                removeCleanInternal(sm);
        }

        /**
         * Remove the given instance from the cache.
         */
        public boolean remove(StateManagerImpl sm) {
            return removeCleanInternal(sm)
                || (_dirty != null && _dirty.remove(sm));
        }

        private boolean removeCleanInternal(StateManagerImpl sm) {
            return _clean != null && _clean.remove(sm);
        }

        public Iterator iterator() {
            IteratorChain chain = new IteratorChain();
            if (_dirty != null && !_dirty.isEmpty())
                chain.addIterator(_dirty.iterator());
            if (_clean != null && !_clean.isEmpty())
                chain.addIterator(_clean.iterator());
            return chain;
        }

        public boolean contains(Object obj) {
            return (_dirty != null && _dirty.contains(obj))
                || (_clean != null && _clean.contains(obj));
        }

        public boolean containsAll(Collection coll) {
            for (Iterator itr = coll.iterator(); itr.hasNext();)
                if (!contains(itr.next()))
                    return false;
            return true;
        }

        public void clear() {
            if (_dirty != null)
                _dirty = null;
            if (_clean != null)
                _clean = null;
        }

        public boolean isEmpty() {
            return (_dirty == null || _dirty.isEmpty())
                && (_clean == null || _clean.isEmpty());
        }

        public int size() {
            int size = 0;
            if (_dirty != null)
                size += _dirty.size();
            if (_clean != null)
                size += _clean.size();
            return size;
        }

        public boolean add(Object obj) {
            throw new UnsupportedOperationException();
        }

        public boolean addAll(Collection coll) {
            throw new UnsupportedOperationException();
        }

        public boolean remove(Object obj) {
            throw new UnsupportedOperationException();
        }

        public boolean removeAll(Collection coll) {
            throw new UnsupportedOperationException();
        }

        public boolean retainAll(Collection c) {
            throw new UnsupportedOperationException();
        }

        public Object[] toArray() {
            throw new UnsupportedOperationException();
        }

        public Object[] toArray(Object[] arr) {
            throw new UnsupportedOperationException();
        }
    }

    /**
     * Unique id for state managers of new datastore instances without assigned
     * object ids.
     */
    private static class StateManagerId
        implements Serializable {

        public static final String STRING_PREFIX = "openjpasm:";

        private static long _generator = 0;

        private final int _bhash;
        private final long _id;

        public static StateManagerId newInstance(Broker b) {
            return new StateManagerId(System.identityHashCode(b), _generator++);
        }

        private StateManagerId(int bhash, long id) {
            _bhash = bhash;
            _id = id;
        }

        public StateManagerId(String str) {
            str = str.substring(STRING_PREFIX.length());
            int idx = str.indexOf(':');
            _bhash = Integer.parseInt(str.substring(0, idx));
            _id = Long.parseLong(str.substring(idx + 1));
        }

        public boolean equals(Object other) {
            if (other == this)
                return true;
            if (!(other instanceof StateManagerId))
                return false;
            StateManagerId sid = (StateManagerId) other;
            return _bhash == sid._bhash && _id == sid._id;
        }

        public int hashCode() {
            return (int) (_id ^ (_id >>> 32));
        }

        public String toString() {
            return STRING_PREFIX + _bhash + ":" + _id;
        }
    }

    /**
     * Collection type that holds state managers but whose interface deals
     * with the corresponding managed objects.
     */
    private static class ManagedObjectCollection
        extends AbstractCollection {

        private final Collection _states;

        public ManagedObjectCollection(Collection states) {
            _states = states;
        }

        public Collection getStateManagers() {
            return _states;
        }

        public int size() {
            return _states.size();
        }

        public Iterator iterator() {
            return new Iterator() {
                private final Iterator _itr = _states.iterator();

                public boolean hasNext() {
                    return _itr.hasNext();
                }

                public Object next() {
                    return ((OpenJPAStateManager) _itr.next()).
                        getManagedInstance();
                }

                public void remove() {
                    throw new UnsupportedException();
                }
            };
        }
    }

    /**
     * Assign the object id to the cache. Exception will be
     * thrown if the id already exists in the cache. 
     */
    protected void assignObjectId(Object cache, Object id, 
        StateManagerImpl sm) {
        ((ManagedCache) cache).assignObjectId(id, sm); 
    }

    /** 
     * This method makes sure we don't already have the instance cached
     */
    protected void checkForDuplicateId(Object id, Object obj) {
        StateManagerImpl other = getStateManagerImplById(id, false);
        if (other != null && !other.isDeleted() && !other.isNew())
            throw new ObjectExistsException(_loc.get("cache-exists",
                obj.getClass().getName(), id)).setFailedObject(obj);
    }
}
