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