Added: incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/pm/PersistenceManagerImpl.java URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/pm/PersistenceManagerImpl.java?view=auto&rev=158176 ============================================================================== --- incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/pm/PersistenceManagerImpl.java (added) +++ incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/pm/PersistenceManagerImpl.java Fri Mar 18 17:02:29 2005 @@ -0,0 +1,2173 @@ +/* + * Copyright 2005 The Apache Software Foundation. + * + * Licensed 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. + */ + +/* + * PersistenceManagerImpl.java + * + * Created on December 1, 2000 + */ + +package org.apache.jdo.impl.pm; + +import java.util.*; +import java.security.AccessController; +import java.security.PrivilegedAction; + +import java.lang.reflect.Constructor; +import javax.transaction.Status; + +import javax.jdo.*; +import javax.jdo.spi.*; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import org.apache.jdo.impl.jdoql.QueryImpl; +import org.apache.jdo.impl.model.java.runtime.RuntimeJavaModelFactory; +import org.apache.jdo.model.java.JavaModel; +import org.apache.jdo.model.java.JavaType; +import org.apache.jdo.model.jdo.JDOClass; +import org.apache.jdo.pm.PersistenceManagerFactoryInternal; +import org.apache.jdo.pm.PersistenceManagerInternal; +import org.apache.jdo.sco.SCOCollection; +import org.apache.jdo.sco.SCOMap; +import org.apache.jdo.state.StateManagerInternal; +import org.apache.jdo.store.StoreManager; +import org.apache.jdo.util.I18NHelper; +import org.apache.jdo.util.JDORIVersion; + +/** + * This is the StoreManager independent implemetation of the + * org.apache.jdo.pm.PersistenceManagerInternal interface. Delegates most of + * the method execution to the corresponding instance of the CacheManagerImpl. + * + * @author Marina Vatkina + */ +public class PersistenceManagerImpl implements PersistenceManagerInternal { + private final boolean DEBUG = true; + + /** + * True if this PersistenceManager is closed + */ + private boolean _isClosed = true; + + /** + * Associated Transaction + */ + private TransactionImpl _transaction = null; + + /** + * Reference to the associated JTA Transaction if any + */ + private Object _jta = null; + + /** + * Current PersistenceManagerWrapper as PersistenceManagerInternal + */ + private PersistenceManagerWrapper current = null; + + /** + * PersistenceManagerFactory that created (and could be pooling) + * this PersistenceManager + */ + private PersistenceManagerFactoryImpl pmf = null; + + /** + * Reference to the CacheManager + */ + private CacheManagerImpl _txCache = null; + + /** + * Flag for Query. + * Constructor defaults it to the PMF setting. + */ + private boolean _ignoreCache; + + /** + * Flag for active transaction + */ + private boolean _activeTransaction = false; + + /** + * Flag for optimistic transaction + */ + private boolean optimistic = true; + + /** + * Flag for multithreaded support. + */ + private boolean multithreaded = true; + + /** + * User Object + */ + private Object _userObject = null; + + /** + * Flag for flushing process + */ + private boolean _flushing = false; + + /** + * This is the ClassLoader that was the + * Thread.currentThread().getContextClassLoader() + * at the time this PersistenceManagerImpl was created. + */ + private final ClassLoader myClassLoader; + + /** + * Constructor signatures + */ + private static final Class[] sigSCO_Short = new Class []{ + java.lang.Object.class, + java.lang.String.class}; + + /** The signature for SCO Collections. + */ + private static final Class[] sigSCO_Collection = new Class []{ + java.lang.Class.class, + boolean.class, + int.class}; + + /** The signature for SCO Maps. + */ + private static final Class[] sigSCO_Map = new Class []{ + java.lang.Class.class, + java.lang.Class.class, + boolean.class, + int.class}; + + /** The signature for SCO HashSet. + */ + private static final Class[] sigSCO_HashSet = new Class []{ + java.lang.Class.class, + boolean.class, + int.class, + float.class}; + + /** The signature for SCO TreeSet. + */ + private static final Class[] sigSCO_TreeSet = new Class []{ + java.lang.Class.class, + boolean.class, + java.util.Comparator.class}; + + /** The signature for SCO HashMap. + */ + private static final Class[] sigSCO_HashMap = new Class []{ + java.lang.Class.class, + java.lang.Class.class, + boolean.class, + int.class, + float.class}; + + /** The signature for SCO TreeMap. + */ + private static final Class[] sigSCO_TreeMap = new Class []{ + java.lang.Class.class, + java.lang.Class.class, + boolean.class, + java.util.Comparator.class}; + + /** Default initialCapacity values. + */ + private static final Integer int11 = new Integer(11); + private static final Integer int10 = new Integer(10); + + /** RuntimeJavaModelFactory. */ + private static final RuntimeJavaModelFactory javaModelFactory = + (RuntimeJavaModelFactory) AccessController.doPrivileged( + new PrivilegedAction () { + public Object run () { + return RuntimeJavaModelFactory.getInstance(); + } + } + ); + + /** + * Logger support + */ + private static final Log logger = LogFactory.getFactory().getInstance( + "org.apache.jdo.impl.pm"); // NOI18N + + /** + * I18N message handler + */ + private final static I18NHelper msg = + I18NHelper.getInstance(PersistenceManagerImpl.class); + + /** + * Helper objects to identify StateManager associated with the given + * PersistenceCapable instance + */ + private StateManagerInternal lookingFor = null; + private PersistenceCapable pc = null; + + /** + * Constructs new instance of PersistenceManagerImpl for this + * PersistenceManagerFactoryInternal and particular combination of + * username and password. + * + * @param pmf calling PersistenceManagerFactory as PersistenceManagerFactoryInternal + * @param username user name used for accessing Connector or null if none + * is provided. + * @param password user password used for accessing Connector or null if + * none is provided. + */ + public PersistenceManagerImpl(PersistenceManagerFactoryInternal pmf, + String username, String password) { + + if (debugging()) + debug("constructor"); // NOI18N + + if (javaModelFactory == null) + throw new JDOUserException( + msg.msg("EXC_CannotGetRuntimeJavaModelFactory")); // NOI18N + + this.pmf = (PersistenceManagerFactoryImpl)pmf; + _transaction = new TransactionImpl(this, this.pmf, username, password); + _txCache = new CacheManagerImpl(this); + + optimistic = pmf.getOptimistic(); + _ignoreCache = pmf.getIgnoreCache(); + + _isClosed = false; + + myClassLoader = getContextClassLoaderPrivileged(); + } + + /** + * @see javax.jdo.PersistenceManager#setIgnoreCache(boolean flag) + * @param flag the ignoreCache value + */ + public void setIgnoreCache(boolean flag) { + assertIsOpen(); + _ignoreCache = flag; + } + + /** Get the value of the ignoreCache flag. + * @see javax.jdo.PersistenceManager#getIgnoreCache() + * @return the IgnoreCache flag + */ + public boolean getIgnoreCache() { + assertIsOpen(); + return _ignoreCache; + } + + /** Set the Multithreaded flag for this PersistenceManager. Applications + * that use multiple threads to invoke methods or access fields from + * instances managed by this PersistenceManager must set this flag to true. + * Instances managed by this PersistenceManager include persistent or + * transactional instances of PersistenceCapable classes, as well as + * helper instances such as Query, Transaction, or Extent. + * + * @param flag the Multithreaded setting. + */ + public void setMultithreaded(boolean flag) { + assertIsOpen(); + multithreaded = flag; + } + + /** Get the current Multithreaded flag for this PersistenceManager. + * @see #setMultithreaded + * @return the Multithreaded setting. + */ + public boolean getMultithreaded() { + assertIsOpen(); + return multithreaded; + } + + /** Return whether this PersistenceManager is closed. + * @see javax.jdo.PersistenceManager#isClosed() + */ + public boolean isClosed() { + return _isClosed; + } + + /** + * Close this persistence manager + * @see javax.jdo.PersistenceManager#close() + */ + public synchronized void close() { + if (debugging()) + debug("close"); // NOI18N + + assertIsOpen(); + + if (_activeTransaction) { + throw new JDOUserException(msg.msg( + "EXC_ActiveTransaction"));// NOI18N + } + + if (current == null){ + forceClose(); + } + + } + + /** + * Returns transaction associated with this persistence manager + * @return transaction current transaction + */ + public Transaction currentTransaction() { + assertIsOpen(); + return (Transaction) _transaction; + } + + // + // -------- ObjectId related methods -------- + // + + /** This method locates a persistent instance in the cache of instances + * managed by this PersistenceManager. + * + *
If the validate flag is true: This method verifies that there + * is an instance in the data store with the same oid, constructs an + * instance, and returns it. If there is no transaction active, then + * a hollow instance or persistent non-transactional instance is returned. + * If there is a transaction active, then + * a persistent clean instance is returned. + *
If the validate flag is false: If there is not already an instance + * in the cache with the same oid, then an instance is constructed and + * returned. If the instance does not exist + * in the data store, then this method will + * not fail. However, a request to access fields of the instance will + * throw an exception. + * @return the PersistenceCapable instance with the specified + * ObjectId + * @param oid an ObjectId + * @param validate if the existence of the instance is to be validated + */ + public Object getObjectById (Object oid, boolean validate) { + if (debugging()) + debug("getObjectById " + oid); // NOI18N + + assertIsOpen(); + if (oid == null) + return null; + + return _txCache.getObjectById(oid, validate); + } + + /** The ObjectId returned by this method represents the JDO identity of + * the instance. The ObjectId is a copy (clone) of the internal state + * of the instance, and changing it does not affect the JDO identity of + * the instance. + * Delegates actual execution to the internal method. + * @param pc the PersistenceCapable instance + * @return the corresponding ObjectId of the instance. Returns null + * if pc is null, not persistence-capable, or not persistent. + */ + public Object getObjectId (Object pc) { + if (debugging()) + debug("getObjectId"); // NOI18N + + return getExternalObjectId(pc, false); + } + + + /** + * @see org.apache.jdo.pm.PersistenceManagerInternal#loadClass + */ + public Class loadClass(String name, ClassLoader given) + throws ClassNotFoundException { + + Class rc = null; + + if (null != given) { + try { + rc = Class.forName(name, true, given); + } catch (ClassNotFoundException ex) { + } + } + + if (null == rc) { + try { + rc = Class.forName( + name, true, + getContextClassLoaderPrivileged()); + } catch (ClassNotFoundException ex) { + } + } + + if (null == rc) { + rc = Class.forName(name, true, myClassLoader); + } + + return rc; + } + + /** + * @see org.apache.jdo.pm.PersistenceManagerInternal#loadPCClassForObjectIdClass + */ + public Class loadPCClassForObjectIdClass(Class objectIdClass) + throws ClassNotFoundException + { + if (debugging()) + debug("loadPCClassForObjectIdClass: " + objectIdClass.getName()); //NOI18N + + JavaModel javaModel = null; + JDOClass jdoClass = null; + JavaType objectIdJavaType = javaModelFactory.getJavaType(objectIdClass); + // try Model of objectId's class loader + ClassLoader classLoader = + javaModelFactory.getClassLoaderPrivileged(objectIdClass); + javaModel = javaModelFactory.getJavaModel(classLoader); + jdoClass = javaModel.getJDOModel(). + getJDOClassForObjectIdClass(objectIdJavaType); + + if (null == jdoClass) { + // try Model of thread context class loader + classLoader = getContextClassLoaderPrivileged(); + javaModel = javaModelFactory.getJavaModel(classLoader); + jdoClass = javaModel.getJDOModel(). + getJDOClassForObjectIdClass(objectIdJavaType); + } + + if (null == jdoClass) { + // try Model of the pm's thead context class loader + javaModel = javaModelFactory.getJavaModel(myClassLoader); + jdoClass = javaModel.getJDOModel(). + getJDOClassForObjectIdClass(objectIdJavaType); + } + + if (jdoClass == null) + // persistence-capable class not found => ClassNotFoundException + throw new ClassNotFoundException(msg.msg( + "EXC_CannotFindPCClassForObjectIdClass", // NOI18N + objectIdClass.getName())); //NOI18N + return javaModelFactory.getJavaClass(jdoClass.getJavaType()); + } + + /** + * Gets the internal object id for this instance. Returns null + * if it is not a PersistenceCapable instance. + * @param pc + * @return the internal object id + */ + public Object getInternalObjectId(Object pc) { + if (debugging()) + debug("getInternalObjectId for " + pc.getClass().getName()); // NOI18N + + assertIsOpen(); + + Object rc = null; + if ( pc instanceof PersistenceCapable ) { + PersistenceCapable p = (PersistenceCapable)pc; + if( !(p.jdoIsPersistent()) ) { + throw new JDOFatalInternalException(msg.msg( + "EXC_TransientInstance", pc.getClass().getName()));// NOI18N + } + + StateManagerInternal sm = findStateManager(p); + if (sm == null) { + throw new JDOFatalInternalException( + msg.msg("EXC_CannotFindSM", pc.getClass().getName())); // NOI18N + } + rc = sm.getInternalObjectId(); + } + return rc; + } + + /** + * @see javax.jdo.PersistenceManager#getTransactionalObjectId + */ + public Object getTransactionalObjectId (Object pc) { + if (debugging()) + debug("getTransactionalObjectId"); // NOI18N + + return getExternalObjectId(pc, true); + } + + /** + * This method returns an object id instance corresponding to the Class + * and String arguments. The String argument might have been the + * result of executing toString on an object id instance. + * @param pcClass the Class of the persistence-capable instance + * @param str the String form of the object id + * @return an instance of the object identity class + */ + public Object newObjectIdInstance (Class pcClass, String str) { + if (debugging()) + debug("newObjectIdInstance for: " + pcClass + ", and " + str); // NOI18N + + assertIsOpen(); + return this.getStoreManager().newObjectIdInstance (pcClass, str); + } + + /** Return the Class that implements the JDO Identity for the + * specified PersistenceCapable Class. The application can use the + * returned Class to construct a JDO Identity instance for + * application identity PersistenceCapable classes. This JDO Identity + * instance can then be used to get an instance of the + * PersistenceCapable class for use in the application. + * + *
In order for the application to construct an instance of the ObjectId class + * it needs to know the class being used by the JDO implementation. + * @param cls the PersistenceCapable Class + * @return the Class of the ObjectId of the parameter + * @see #getObjectById + */ + public Class getObjectIdClass(Class cls) { + if (debugging()) + debug("getObjectIdClass for: " + cls); // NOI18N + + assertIsOpen(); + return pmf.getObjectIdClass(cls); + } + + // + // -------- Query and Extent methods -------- + // + + /** Create a new Query with no elements. + * @return a new Query instance with no elements. + */ + public Query newQuery() { + assertIsOpen(); + return new QueryImpl(this); + } + + /** Create a new Query using elements from another Query. The other Query + * must have been created by the same JDO implementation. It might be active + * in a different PersistenceManager or might have been serialized and + * restored. + * @return the new Query + * @param compiled another Query from the same JDO implementation + */ + public Query newQuery (Object compiled) { + assertIsOpen(); + return new QueryImpl(this, compiled); + } + + /** Create a new Query using the specified language. + * @param language the language of the query parameter + * @param query the query, which is of a form determined by the language + * @return the new Query + */ + public Query newQuery (String language, Object query) { + assertIsOpen(); + if ("javax.jdo.query.JDOQL".equals(language)) //NOI18N + return new QueryImpl(this, query); + throw new JDOUserException(msg.msg( + "EXC_UnsupportedQueryLanguage", language)); // NOI18N + } + + /** Create a new Query specifying the Class of the results. + * @param cls the Class of the results + * @return the new Query + */ + public Query newQuery (Class cls) { + assertIsOpen(); + return new QueryImpl(this, cls); + } + + /** Create a new Query with the candidate Extent; the class is taken + * from the Extent. + * specified. + * @return the new Query + * @param cln the Extent of candidate instances */ + public Query newQuery(Extent cln) { + assertIsOpen(); + return new QueryImpl(this, cln); + } + + /** Create a new Query with the Class of the results and candidate Collection. + * specified. + * @param cls the Class of results + * @param cln the Collection of candidate instances + * @return the new Query + */ + public Query newQuery (Class cls, Collection cln) { + assertIsOpen(); + return new QueryImpl(this, cls, cln); + } + + /** Create a new Query with the Class of the results and Filter. + * specified. + * @param cls the Class of results + * @param filter the Filter for candidate instances + * @return the new Query + */ + public Query newQuery (Class cls, String filter) { + assertIsOpen(); + return new QueryImpl(this, cls, filter); + } + + /** Create a new Query with the Class of the results, candidate Collection, + * and Filter. + * @param cls the Class of results + * @param cln the Collection of candidate instances + * @param filter the Filter for candidate instances + * @return the new Query + */ + public Query newQuery (Class cls, Collection cln, String filter) { + assertIsOpen(); + return new QueryImpl(this, cls, cln, filter); + } + + /** Create a new Query with the candidate Extent and Filter. + * The class is taken from the Extent. + * @return the new Query + * @param cln the Extent of candidate instances + * @param filter the Filter for candidate instances */ + public Query newQuery(Extent cln, String filter) { + assertIsOpen(); + return new QueryImpl(this, cln, filter); + } + + /** The PersistenceManager may manage a collection of instances in the data + * store based on the class of the instances. This method returns an + * Extent of instances in the data store that might be iterated or + * given to a Query as the Extent of candidate instances. + * @param persistenceCapableClass Class of instances + * @param subclasses whether to include instances of subclasses + * @return an Extent of instances. + * @see StoreManager#getExtent + * @see javax.jdo.Query + */ + public Extent getExtent (Class persistenceCapableClass, boolean subclasses) { + if (debugging()) + debug("getExtent for: " + persistenceCapableClass + // NOI18N + ", subclasses: " + subclasses); // NOI18N + + assertIsOpen(); + Extent rc = null; + if (PersistenceCapable.class.isAssignableFrom(persistenceCapableClass)) { + rc = this.getStoreManager().getExtent(persistenceCapableClass, subclasses, this); + } else { + throw new JDOUserException(msg.msg( + "EXC_ClassNotPersistenceCapable", persistenceCapableClass.getName())); // NOI18N + } + if (null == rc) { + // Protect against bogus store managers that return null. + rc = new EmptyExtent(persistenceCapableClass, subclasses); + } + return rc; + } + + class EmptyExtent implements Extent { + private final Class cls; + private final boolean subclasses; + EmptyExtent(Class cls, boolean subclasses) { + this.cls = cls; + this.subclasses = subclasses; + } + public Iterator iterator() { + return new Iterator() { + public boolean hasNext() { return false; } + public Object next() { return null; } + public void remove() { } + };} + public boolean hasSubclasses() { return false; } + public Class getCandidateClass() { return cls; } + public boolean subclasses() { return subclasses; } + public PersistenceManager getPersistenceManager() { + return PersistenceManagerImpl.this.current; + } + public void closeAll() { } + public void close(Iterator it) { } + } + + // + // -------- State transition methods -------- + // + + /** Make the transient instance persistent in this PersistenceManager. + * This method must be called in an active transaction. + * The PersistenceManager assigns an ObjectId to the instance and + * transitions it to persistent-new. + * The instance will be managed in the Extent associated with its Class. + * The instance will be put into the data store at commit. + * @param pc a transient instance of a Class that implements + * PersistenceCapable + */ + public void makePersistent (Object pc) { + if (debugging()) + debug("makePersistent"); // NOI18N + + assertIsOpen(); + assertActiveTransaction(false); + + makePersistentInternal(pc); + } + + /** Make an array of instances persistent. + * @param pcs an array of transient instances + * @see #makePersistent(Object pc) + */ + public void makePersistentAll(Object[] pcs) { + if (debugging()) + debug("makePersistentAll"); // NOI18N + + assertIsOpen(); + assertIsOpen(); + assertActiveTransaction(false); + makePersistentAllInternal(pcs); + + } + + /** Make an collection of instances persistent. + * @param pcs an collection of transient instances + * @see #makePersistent(Object pc) + */ + public void makePersistentAll(Collection pcs) { + if (debugging()) + debug("makePersistentAll"); // NOI18N + + assertIsOpen(); + assertActiveTransaction(false); + makePersistentAllInternal(pcs.toArray()); + } + + /** Delete the persistent instance from the data store. + * This method must be called in an active transaction. + * The data store object will be removed at commit. + * Unlike makePersistent, which makes the closure of the instance persistent, + * the closure of the instance is not deleted from the data store. + * This method has no effect if the instance is already deleted in the + * current transaction. + * This method throws an exception if the instance is transient or is managed by another + * PersistenceManager. + * + * @param pc a persistent instance + */ + public void deletePersistent (Object pc) { + if (debugging()) + debug("deletePersistent"); // NOI18N + + assertIsOpen(); + assertActiveTransaction(false); + deletePersistentInternal(pc); + } + + /** Delete an array of instances from the data store. + * @param pcs a Collection of persistent instances + * @see #deletePersistent(Object pc) + */ + public void deletePersistentAll(Object[] pcs) { + if (debugging()) + debug("deletePersistentAll"); // NOI18N + + assertIsOpen(); + assertActiveTransaction(false); + deletePersistentAllInternal(pcs); + + } + + /** Delete a Collection of instances from the data store. + * @param pcs a Collection of persistent instances + * @see #deletePersistent(Object pc) + */ + public void deletePersistentAll(Collection pcs) { + if (debugging()) + debug("deletePersistentAll"); // NOI18N + + assertIsOpen(); + assertActiveTransaction(false); + deletePersistentAllInternal(pcs.toArray()); + } + + /** Make an instance transient, removing it from management by this + * PersistenceManager. + * + *
The instance loses its JDO identity and it is no longer associated + * with any PersistenceManager. The state of fields is preserved unchanged. + * @param pc the instance to make transient. + */ + public void makeTransient(Object pc) { + if (debugging()) + debug("makeTransient"); // NOI18N + + assertIsOpen(); + makeTransientInternal(pc); + } + + /** Make an array of instances transient, removing them from management by this + * PersistenceManager. + * + *
The instances lose their JDO identity and they are no longer associated + * with any PersistenceManager. The state of fields is preserved unchanged. + * @param pcs the instances to make transient. + */ + public void makeTransientAll(Object[] pcs) { + if (debugging()) + debug("makeTransientAll"); // NOI18N + + assertIsOpen(); + makeTransientAllInternal(pcs); + } + + /** Make a Collection of instances transient, removing them from management by this + * PersistenceManager. + * + *
The instances lose their JDO identity and they are no longer associated + * with any PersistenceManager. The state of fields is preserved unchanged. + * @param pcs the instances to make transient. + */ + public void makeTransientAll(Collection pcs) { + if (debugging()) + debug("makeTransientAll"); // NOI18N + + assertIsOpen(); + makeTransientAll(pcs.toArray()); + } + + /** Make an instance subject to transactional boundaries. + * + *
Transient instances normally do not observe transaction boundaries. + * This method makes transient instances sensitive to transaction completion. + * If an instance is modified in a transaction, and the transaction rolls back, + * the state of the instance is restored to the state before the first change + * in the transaction. + * + *
For persistent instances read in optimistic transactions, this method + * allows the application to make the state of the instance part of the + * transactional state. At transaction commit, the state of the instance in + * cache is compared to the state of the instance in the data store. If they + * are not the same, then an exception is thrown. + * @param pc the instance to make transactional. + */ + public void makeTransactional(Object pc) { + if (debugging()) + debug("makeTransactional"); // NOI18N + + assertIsOpen(); + makeTransactionalInternal(pc); + } + + /** Make an array of instances subject to transactional boundaries. + * @param pcs the array of instances to make transactional. + * @see #makeTransactional(Object pc) + */ + public void makeTransactionalAll(Object[] pcs) { + if (debugging()) + debug("makeTransactionalAll"); // NOI18N + + assertIsOpen(); + makeTransactionalAllInternal(pcs); + } + + /** Make a Collection of instances subject to transactional boundaries. + * @param pcs the Collection of instances to make transactional. + * @see #makeTransactional(Object pc) + */ + public void makeTransactionalAll(Collection pcs) { + if (debugging()) + debug("makeTransactionalAll"); // NOI18N + + assertIsOpen(); + makeTransactionalAllInternal(pcs.toArray()); + } + + /** Make an instance non-transactional after commit. + * + *
Normally, at transaction completion, instances are evicted from the + * cache. This method allows an application to identify an instance as + * not being evicted from the cache at transaction completion. Instead, + * the instance remains in the cache with nontransactional state. + * + * @param pc the instance to make nontransactional. + */ + public void makeNontransactional(Object pc) { + if (debugging()) + debug("makeNontransactional"); // NOI18N + + assertIsOpen(); + makeNontransactionalInternal(pc); + } + + /** Make an array of instances non-transactional after commit. + * + * @param pcs the array of instances to make nontransactional. + * @see #makeNontransactional(Object pc) + */ + public void makeNontransactionalAll(Object[] pcs){ + if (debugging()) + debug("makeNontransactionalAll"); // NOI18N + + assertIsOpen(); + makeNontransactionalAllInternal(pcs); + } + + /** Make a Collection of instances non-transactional after commit. + * + * @param pcs the Collection of instances to make nontransactional. + * @see #makeNontransactional(Object pc) + */ + public void makeNontransactionalAll(Collection pcs) { + if (debugging()) + debug("makeNontransactionalAll"); // NOI18N + + assertIsOpen(); + makeNontransactionalAllInternal(pcs.toArray()); + } + + /** Mark an instance as no longer needed in the cache. + * Eviction is normally done automatically by the PersistenceManager + * at transaction completion. This method allows the application to + * explicitly provide a hint to the PersistenceManager that the instance + * is no longer needed in the cache. + * @param pc the instance to evict from the cache. + */ + public void evict(Object pc) { + if (debugging()) + debug("evict"); // NOI18N + + assertIsOpen(); + evictInternal(pc); + } + + /** Mark an array of instances as no longer needed in the cache. + * @see #evict(Object pc) + * @param pcs the array of instances to evict from the cache. + */ + public void evictAll(Object[] pcs) { + if (debugging()) + debug("evictAll"); // NOI18N + + assertIsOpen(); + evictAllInternal(pcs); + } + + /** Mark a Collection of instances as no longer needed in the cache. + * @param pcs the Collection of instance to evict from the cache. + */ + public void evictAll(Collection pcs) { + if (debugging()) + debug("evictAll"); // NOI18N + + assertIsOpen(); + evictAllInternal(pcs.toArray()); + } + + /** Mark all persistent-nontransactional instances as no longer needed + * in the cache. It transitions + * all persistent-nontransactional instances to hollow. Transactional + * instances are subject to eviction based on the RetainValues setting. + * @see #evict(Object pc) + */ + public void evictAll() { + if (debugging()) + debug("evictAll()"); // NOI18N + + assertIsOpen(); + _txCache.evictAll(); + } + + + /** Refresh the state of the instance from the data store. + * + *
In an optimistic transaction, the state of instances in the cache + * might not match the state in the data store. This method is used to + * reload the state of the instance from the data store so that a subsequent + * commit is more likely to succeed. + *
Outside a transaction, this method will refresh nontransactional state. + * @param pc the instance to refresh. + */ + public void refresh(Object pc) { + if (debugging()) + debug("refresh"); // NOI18N + + assertIsOpen(); + refreshInternal(pc); + } + + /** Refresh the state of an array of instances from the data store. + * + * @see #refresh(Object pc) + * @param pcs the array of instances to refresh. + */ + public void refreshAll(Object[] pcs) { + if (debugging()) + debug("refreshAll"); // NOI18N + + assertIsOpen(); + refreshAllInternal(pcs); + } + + /** Refresh the state of a Collection of instances from the data store. + * + * @see #refresh(Object pc) + * @param pcs the Collection of instances to refresh. + */ + public void refreshAll(Collection pcs) { + if (debugging()) + debug("refreshAll"); // NOI18N + + assertIsOpen(); + refreshAllInternal(pcs.toArray()); + } + + /** Refresh the state of all applicable instances from the data store. + *
If called with an active transaction, all transactional instances
+ * will be refreshed. If called outside an active transaction, all
+ * nontransactional instances will be refreshed.
+ * @see #refresh(Object pc)
+ */
+ public void refreshAll() {
+ if (debugging())
+ debug("refreshAll()"); // NOI18N
+
+ assertIsOpen();
+ if (_activeTransaction) {
+ _txCache.refreshAllTransactional();
+ } else {
+ _txCache.refreshAllNontransactional();
+ }
+ }
+
+ /** Retrieve field values of an instance from the store. This tells
+ * the PersistenceManager that the application intends to use the
+ * instance, and its field values must be retrieved.
+ *
The PersistenceManager might use policy information about the
+ * class to retrieve associated instances.
+ * @param pc the instance
+ */
+ public void retrieve(Object pc) {
+ if (debugging())
+ debug("retrieve"); // NOI18N
+
+ assertIsOpen();
+ retrieveInternal(pc, false);
+ }
+
+ /** Retrieve field values of instances from the store. This tells
+ * the PersistenceManager that the application intends to use the
+ * instances, and all field values must be retrieved.
+ *
The PersistenceManager might use policy information about the
+ * class to retrieve associated instances.
+ * @param pcs the instances
+ */
+ public void retrieveAll(Object[] pcs) {
+ retrieveAll(pcs, false);
+ }
+
+ /** Retrieve field values of instances from the store. This tells
+ * the PersistenceManager that the application intends to use the
+ * instances, and their field values should be retrieved. The fields
+ * in the default fetch group must be retrieved, and the implementation
+ * might retrieve more fields than the default fetch group.
+ *
The PersistenceManager might use policy information about the
+ * class to retrieve associated instances.
+ * @param pcs the instances
+ * @param DFGOnly whether to retrieve only the default fetch group fields
+ * @since 1.0.1
+ */
+ public void retrieveAll (Object[] pcs, boolean DFGOnly) {
+ if (debugging())
+ debug("retrieveAll, DFGOnly: " + DFGOnly); // NOI18N
+
+ assertIsOpen();
+ retrieveAllInternal(pcs, DFGOnly);
+ }
+
+
+ /** Retrieve field values of instances from the store. This tells
+ * the PersistenceManager that the application intends to use the
+ * instances, and all field values must be retrieved.
+ *
The PersistenceManager might use policy information about the
+ * class to retrieve associated instances.
+ * @param pcs the instances
+ */
+ public void retrieveAll(Collection pcs) {
+ retrieveAll(pcs, false);
+ }
+
+ /** Retrieve field values of instances from the store. This tells
+ * the PersistenceManager that the application intends to use the
+ * instances, and their field values should be retrieved. The fields
+ * in the default fetch group must be retrieved, and the implementation
+ * might retrieve more fields than the default fetch group.
+ *
The PersistenceManager might use policy information about the
+ * class to retrieve associated instances.
+ * @param pcs the instances
+ * @param DFGOnly whether to retrieve only the default fetch group fields
+ * @since 1.0.1
+ */
+ public void retrieveAll (Collection pcs, boolean DFGOnly) {
+ if (debugging())
+ debug("retrieveAll, DFGOnly: " + DFGOnly); // NOI18N
+
+ assertIsOpen();
+ retrieveAllInternal(pcs.toArray(), DFGOnly);
+ }
+
+ //
+ // -------- Other public methods --------
+ //
+
+ /** This method returns the PersistenceManagerFactory used to create
+ * this PersistenceManager. It returns null if this instance was
+ * created via a constructor.
+ * @return the PersistenceManagerFactory that created
+ * this PersistenceManager
+ */
+ public PersistenceManagerFactory getPersistenceManagerFactory() {
+ assertIsOpen();
+ return (PersistenceManagerFactory)pmf;
+ }
+
+ /** The application can manage the PersistenceManager instances
+ * more easily by having an application object associated with each
+ * PersistenceManager instance.
+ * @param o the user instance to be remembered by the PersistenceManager
+ * @see #getUserObject
+ */
+ public void setUserObject(Object o) {
+ assertIsOpen();
+ this._userObject = o;
+ }
+
+ /** The application can manage the PersistenceManager instances
+ * more easily by having an application object associated with each
+ * PersistenceManager instance.
+ * @return the user object associated with this PersistenceManager
+ * @see #setUserObject
+ */
+ public Object getUserObject() {
+ assertIsOpen();
+ return _userObject;
+ }
+
+ /** The JDO vendor might store certain non-operational properties and
+ * make those properties available to applications (for troubleshooting).
+ *
+ *
Standard properties include: + *
true if this object is the same as the obj
+ * argument; false otherwise.
+ */
+ public boolean equals(Object obj) {
+ if (obj instanceof PersistenceManagerWrapper) {
+ return (((PersistenceManagerWrapper)obj).getPersistenceManager() == this);
+
+ } else if (obj instanceof PersistenceManagerImpl) {
+ return (((PersistenceManagerImpl)obj) == this);
+ }
+ return false;
+ }
+
+ //
+ // ----------- Protected methods -----------------
+ //
+
+ /**
+ * Remember the current wrapper
+ */
+ protected void pushCurrentWrapper(PersistenceManagerWrapper pmw) {
+ if (debugging())
+ debug("pushCurrentWrapper"); // NOI18N
+
+ current = pmw;
+ }
+
+ /**
+ * Replace current wrapper with the previous
+ */
+ protected void popCurrentWrapper(PersistenceManagerWrapper prev) {
+ if (debugging())
+ debug("popCurrentWrapper"); // NOI18N
+
+ current = prev;
+ if (_jta == null && current == null) {
+ this.close();
+ }
+ }
+
+ /**
+ * with the current thread in the managed environment
+ */
+ protected void setJTATransaction(Object t) {
+ if (debugging())
+ debug("setJTATransaction"); // NOI18N
+
+ if (this._jta != null) {
+ throw new JDOFatalInternalException(
+ msg.msg("EXC_NotNullJTATransaction")); //NOI18N
+ }
+ this._jta = t;
+ }
+
+ /**
+ * Disassociate this PersistenceManager with the current JTA
+ * transaction.
+ */
+ protected void deregisterJTA() {
+ if (debugging())
+ debug("deregisterJTA"); // NOI18N
+
+ pmf.deregisterPersistenceManager(this, _jta);
+ _jta = null;
+ }
+
+ /**
+ * Close this persistence manager even if there are open wrappers
+ * or an uncomplete transaction.
+ * Called by transaction completion in case of an inconsistent state
+ * or as a part of a normal close process.
+ */
+ protected void forceClose() {
+ if (debugging())
+ debug("forceClose"); // NOI18N
+
+ _txCache.close();
+
+ // Remove association with JTA Transaction if any and return
+ // to the pool.
+ pmf.releasePersistenceManager(this, _jta);
+
+ // Reset all references:
+ pmf = null;
+ _jta = null;
+ _isClosed = true;
+ _transaction = null;
+ _txCache = null;
+ _userObject = null;
+ }
+
+ /**
+ * Verify that cached instance of a PersistenceManager was initialy
+ * requested with the same values for username and password
+ */
+ protected boolean verify(String username, String password) {
+ if (debugging())
+ debug("verify"); // NOI18N
+
+ return _transaction.verify(username, password);
+ }
+
+ /**
+ * Called by Transaction commit()
+ * Loops through transactional cache and calls PersistentStore.updatePersistent()
+ * on each instance
+ */
+ protected void flushInstances() {
+ if (debugging())
+ debug("flushInstances"); // NOI18N
+
+ assertIsOpen();
+ assertActiveTransaction(false);
+ _flushing = true;
+
+ try {
+ _txCache.flushInstances();
+ } finally {
+ _flushing = false;
+ }
+ }
+
+ /**
+ * Called by Transaction commit() or rollback()
+ * cleans up transactional cache
+ * @param status javax.transaction.Status
+ */
+ protected void afterCompletion(int status) {
+ if (debugging())
+ debug("afterCompletion"); // NOI18N
+
+ assertIsOpen();
+ _flushing = true;
+ boolean abort = ((status == Status.STATUS_ROLLEDBACK) ||
+ (status == Status.STATUS_ROLLING_BACK) ||
+ (status == Status.STATUS_MARKED_ROLLBACK));
+ _txCache.afterCompletion(abort);
+ _flushing = false;
+ }
+
+ /**
+ * Called by Query or Extent to flush updates to the database
+ * in a datastore transaction. Delegates to TransactionImpl to do
+ * the processing that will call internaly flushInstances() to do actual
+ * flush.
+ * @see #flushInstances()
+ */
+ public synchronized void flush() {
+ if (debugging())
+ debug("flush"); // NOI18N
+
+ _transaction.internalFlush();
+ }
+
+ /**
+ * For Transaction to notify PersistenceManager that
+ * status is changed
+ */
+ protected synchronized void notifyStatusChange(boolean isActive) {
+ _activeTransaction = isActive;
+ }
+
+ /**
+ * For Transaction to notify PersistenceManager that
+ * optimistic flag is changed
+ */
+ protected synchronized void notifyOptimistic(boolean optimistic) {
+ this.optimistic = optimistic;
+ }
+
+ /** --------------Private Methods-------------- */
+
+ /** Returns external representation of the current or transactional
+ * objectId depending on the parameter
+ * @param pc the PersistenceCapable instance
+ * @param transactional true if the transactional Id is requested
+ * @return the corresponding ObjectId of the instance. Returns null
+ * if pc is null, not persistence-capable, or not persistent.
+ */
+ private Object getExternalObjectId(Object pc, boolean transactional) {
+ if (debugging())
+ debug("getExternalObjectId"); // NOI18N
+
+ assertIsOpen();
+ if (pc != null && pc instanceof PersistenceCapable) {
+ PersistenceCapable p = (PersistenceCapable)pc;
+ if (p.jdoIsPersistent()) {
+ return _txCache.getExternalObjectId(p, transactional);
+ }
+ }
+ // All other cases if no exception thrown
+ return null;
+ }
+
+ /**
+ * assert that the associated Transaction is active
+ */
+ private void assertActiveTransaction(boolean insideQuery) {
+ if (_flushing || (insideQuery && _transaction.getNontransactionalRead())) {
+ return;
+ }
+
+ if (!_activeTransaction) {
+ throw new JDOUserException(msg.msg(
+ "EXC_TransactionNotActive"));// NOI18N
+ }
+
+ }
+
+ /**
+ * assert Object is PersistenceCapable
+ */
+ private void assertPersistenceCapable(Object pc, String caller) {
+ if ( !(pc instanceof PersistenceCapable) ) {
+ String message = null;
+ if (pc instanceof Collection) {
+ message = msg.msg("EXC_CollectionType", caller); // NOI18N
+ } else if (pc.getClass().isArray()) {
+ message = msg.msg("EXC_ArrayType", caller);
+ } else {
+ message = msg.msg("EXC_NotPersistenceCapable", pc.getClass().getName()); // NOI18N
+ }
+ throw new JDOUserException(message, pc);
+ }
+
+ }
+
+ /**
+ * assert PersistenceCapable is associated with this instance of PersistenceManager
+ */
+ private void assertPersistenceManager(PersistenceCapable pc) {
+ // pc.jdoGetPersistenceManager() returns the wrapper. It should compare equals
+ // to this PersistenceManager:
+ if (!this.equals(pc.jdoGetPersistenceManager())) {
+ throw new JDOUserException(msg.msg(
+ "EXC_AnotherPersistenceManager"));// NOI18N
+ }
+ }
+
+ /**
+ * Helper method to validate errors on processing arrays of objects.
+ * @param l actual size of the array
+ * @param err array of Throwable to validate
+ * @throws JDOUserException if l is greater than 0.
+ */
+ private void validateResult(int l, Throwable[] err) {
+ if (l > 0) {
+ Throwable[] t = new Throwable[l];
+ System.arraycopy(err, 0, t, 0, l);
+ throw new JDOUserException(msg.msg(
+ "EXC_FailedToProcessAll"), t); //(Throwable[])err.toArray());// NOI18N
+ }
+ }
+ /**
+ * Helper method to calculate initialSize of the Collection or Map if
+ * null is specifield for the new tracked instance.
+ *
+ * @param type Class type for which the request is processed.
+ * @return default initialSize as Integer.
+ */
+ private Integer getInitialSize(Class type) {
+ if (type.equals(org.apache.jdo.impl.sco.HashSet.class) ||
+ type.equals(org.apache.jdo.impl.sco.HashMap.class) ||
+ type.equals(org.apache.jdo.impl.sco.Hashtable.class)) {
+ return int11;
+ } else {
+ return int10;
+ }
+ }
+
+ //
+ // Internal methods to process state transitions requests.
+ //
+
+ /**
+ * Internal method for processing makePersistent request.
+ * @see #makePersistent(Object pc)
+ */
+ private void makePersistentInternal(Object pc) {
+ if (pc == null) {
+ if (debugging())
+ debug("makePersistentInternal null"); // NOI18N
+ return; // ignore
+ }
+ if (debugging())
+ debug("makePersistentInternal for " + pc.getClass().getName()); // NOI18N
+
+ assertPersistenceCapable(pc, "makePersistent");
+ if (debugging())
+ debug("makePersistentInternal is pc"); // NOI18N
+
+ PersistenceCapable p = (PersistenceCapable)pc;
+ _txCache.makePersistent(p);
+ }
+
+ /**
+ * Internal method for processing makePersistentAll request.
+ * @see #makePersistentAll(Object[] pcs)
+ */
+ private void makePersistentAllInternal(Object[] pcs) {
+ Throwable[] err = new Throwable[pcs.length];
+ int l = 0;
+
+ if (debugging())
+ debug("makePersistentAllInternal " + pcs.length); // NOI18N
+ for(int i = 0; i < pcs.length; i++) {
+ try {
+ makePersistentInternal(pcs[i]);
+ } catch (Throwable e) {
+ err[l++] = e;
+ }
+ }
+ validateResult(l, err);
+ }
+
+ /**
+ * Internal method to process deletePersistent call.
+ * @see #deletePersistent(Object pc)
+ */
+ private void deletePersistentInternal(Object pc) {
+ if (pc == null) {
+ return; // ignore
+ }
+ assertPersistenceCapable(pc, "deletePersistent");
+
+ PersistenceCapable p = (PersistenceCapable)pc;
+
+ if( !(p.jdoIsPersistent()) ) {
+ throw new JDOUserException(msg.msg(
+ "EXC_TransientInstance", pc.getClass().getName()));// NOI18N
+ }
+
+ StateManagerInternal sm = findStateManager(p);
+ sm.deletePersistent();
+ }
+
+ /**
+ * Internal method to process deletePersistentAll call.
+ * @see #deletePersistentAll(Object[] pcs)
+ */
+ private void deletePersistentAllInternal(Object[] pcs) {
+ Throwable[] err = new Throwable[pcs.length];
+ int l = 0;
+
+ for(int i = 0; i < pcs.length; i++) {
+ try {
+ deletePersistentInternal(pcs[i]);
+ } catch (Throwable e) {
+ err[l++] = e;
+ }
+ }
+ validateResult(l, err);
+ }
+
+ /**
+ * Internal method to process makeTransient call.
+ * @see #makeTransient(Object pc)
+ */
+ private void makeTransientInternal(Object pc) {
+ if (pc == null) {
+ return; // ignore
+ }
+ assertPersistenceCapable(pc, "makeTransient");
+
+ PersistenceCapable p = (PersistenceCapable)pc;
+ _txCache.makeTransient(p);
+ }
+
+ /**
+ * Internal method to process makeTransientAll call.
+ * @see #makeTransientAll(Object[] pcs)
+ */
+ private void makeTransientAllInternal(Object[] pcs) {
+ Throwable[] err = new Throwable[pcs.length];
+ int l = 0;
+
+ for(int i = 0; i < pcs.length; i++) {
+ try {
+ makeTransientInternal(pcs[i]);
+ } catch (Throwable e) {
+ err[l++] = e;
+ }
+ }
+ validateResult(l, err);
+ }
+
+ /**
+ * Internal method to process makeTransactional call.
+ * @see #makeTransactional(Object pc)
+ */
+ private void makeTransactionalInternal(Object pc) {
+ if (pc == null) {
+ return; // ignore
+ }
+ assertPersistenceCapable(pc, "makeTransactional");
+
+ PersistenceCapable p = (PersistenceCapable)pc;
+ if (p.jdoIsPersistent()) {
+ assertActiveTransaction(false);
+ }
+
+ _txCache.makeTransactional(p);
+ }
+
+ /**
+ * Internal method to process makeTransactionalAll call.
+ * @see #makeTransactionalAll(Object[] pcs)
+ */
+ private void makeTransactionalAllInternal(Object[] pcs) {
+ Throwable[] err = new Throwable[pcs.length];
+ int l = 0;
+
+ for(int i = 0; i < pcs.length; i++) {
+ try {
+ makeTransactionalInternal(pcs[i]);
+ } catch (Throwable e) {
+ err[l++] = e;
+ }
+ }
+ validateResult(l, err);
+ }
+
+ /**
+ * Internal method to process makeNontransactional call.
+ * @see #makeNontransactional(Object pc)
+ */
+ private void makeNontransactionalInternal(Object pc) {
+ if (pc == null) {
+ return; // ignore
+ }
+ assertPersistenceCapable(pc, "makeNontransactional");
+
+ PersistenceCapable p = (PersistenceCapable)pc;
+ _txCache.makeNontransactional(p);
+ }
+
+ /**
+ * Internal method to process makeNontransactionalAll call.
+ * @see #makeNontransactionalAll(Object[] pcs)
+ */
+ private void makeNontransactionalAllInternal(Object[] pcs) {
+ Throwable[] err = new Throwable[pcs.length];
+ int l = 0;
+
+ for(int i = 0; i < pcs.length; i++) {
+ try {
+ makeNontransactionalInternal(pcs[i]);
+ } catch (Throwable e) {
+ err[l++] = e;
+ }
+ }
+ validateResult(l, err);
+ }
+
+ /**
+ * Internal method to process evict call.
+ * @see #evict(Object pc)
+ */
+ private void evictInternal(Object pc) {
+ if (pc == null) {
+ return; // ignore
+ }
+ assertPersistenceCapable(pc, "evict");
+
+ PersistenceCapable p = (PersistenceCapable)pc;
+ _txCache.evict(p);
+ }
+
+ /**
+ * Internal method to process evictAll call.
+ * @see #evictAll(Object[] pcs)
+ */
+ private void evictAllInternal(Object[] pcs) {
+ Throwable[] err = new Throwable[pcs.length];
+ int l = 0;
+
+ for(int i = 0; i < pcs.length; i++) {
+ try {
+ evict(pcs[i]);
+ } catch (Throwable e) {
+ err[l++] = e;
+ }
+ }
+ validateResult(l, err);
+ }
+
+ /**
+ * Internal method to process refresh call.
+ * @see #refresh(Object pc)
+ */
+ private void refreshInternal(Object pc) {
+ if (pc == null) {
+ return; // ignore
+ }
+ assertPersistenceCapable(pc, "refresh");
+
+ PersistenceCapable p = (PersistenceCapable)pc;
+ _txCache.refresh(p);
+ }
+
+ /**
+ * Internal method to process refreshAll call.
+ * @see #refreshAll(Object[] pcs)
+ */
+ private void refreshAllInternal(Object[] pcs) {
+ Throwable[] err = new Throwable[pcs.length];
+ int l = 0;
+
+ for(int i = 0; i < pcs.length; i++) {
+ try {
+ refresh(pcs[i]);
+ } catch (Throwable e) {
+ err[l++] = e;
+ }
+ }
+ validateResult(l, err);
+ }
+
+ /**
+ * Internal method to process retrieve call.
+ * @see #retrieve(Object pc)
+ */
+ private void retrieveInternal(Object pc, boolean DFGOnly) {
+ // XXX the DFGOnly flag is ignored here.
+ if (pc == null) {
+ return; // ignore
+ }
+ assertPersistenceCapable(pc, "retrieve");
+
+ PersistenceCapable p = (PersistenceCapable)pc;
+ _txCache.retrieve(p);
+ }
+
+ /**
+ * Internal method to process retrieveAll call.
+ * @see #retrieveAll(Object[] pcs)
+ */
+ private void retrieveAllInternal(Object[] pcs, boolean DFGOnly) {
+ Throwable[] err = new Throwable[pcs.length];
+ int l = 0;
+
+ for(int i = 0; i < pcs.length; i++) {
+ try {
+ retrieveInternal(pcs[i], DFGOnly);
+ } catch (Throwable e) {
+ err[l++] = e;
+ }
+ }
+ validateResult(l, err);
+ }
+
+ /**
+ * Tracing method
+ * @param msg String to display
+ */
+ private void debug(String msg) {
+ logger.debug("In PersistenceManagerImpl " + msg); // NOI18N
+ }
+
+ /**
+ * Verifies if debugging is enabled.
+ * @return true if debugging is enabled.
+ */
+ private boolean debugging() {
+ return logger.isDebugEnabled();
+ }
+
+ /**
+ * Calls getContextClassLoader for the current Thread in a
+ * doPrivileged block.
+ * @return the context class loader of the current Thread
+ * @exception SecurityException thrown by getContextClassLoader.
+ */
+ public ClassLoader getContextClassLoaderPrivileged()
+ throws SecurityException
+ {
+ return (ClassLoader) AccessController.doPrivileged (
+ new PrivilegedAction () {
+ public Object run () {
+ return Thread.currentThread().getContextClassLoader();
+ }
+ }
+ );
+ }
+
+ /**
+ * Assert the NontransactionalRead flag is true or a transaction is active.
+ */
+ public void assertReadAllowed() {
+ assertIsOpen();
+ _transaction.assertReadAllowed();
+ }
+
+}