Return-Path: Delivered-To: apmail-db-jdo-commits-archive@www.apache.org Received: (qmail 91637 invoked from network); 19 Mar 2005 05:32:13 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (209.237.227.199) by minotaur.apache.org with SMTP; 19 Mar 2005 05:32:13 -0000 Received: (qmail 4987 invoked by uid 500); 19 Mar 2005 05:32:12 -0000 Mailing-List: contact jdo-commits-help@db.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: jdo-dev@db.apache.org Delivered-To: mailing list jdo-commits@db.apache.org Delivered-To: moderator for jdo-commits@db.apache.org Received: (qmail 90369 invoked by uid 99); 19 Mar 2005 01:12:51 -0000 X-ASF-Spam-Status: No, hits=-9.8 required=10.0 tests=ALL_TRUSTED,NO_REAL_NAME X-Spam-Check-By: apache.org Message-ID: <20050319010608.28191.qmail@minotaur.apache.org> Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Mailer: svnmailer-1.0.0-dev Date: Sat, 19 Mar 2005 01:06:08 -0000 Subject: svn commit: r158176 [42/79] - in incubator/jdo/trunk/ri11: ./ src/ src/conf/ src/java/ src/java/org/ src/java/org/apache/ src/java/org/apache/jdo/ src/java/org/apache/jdo/ejb/ src/java/org/apache/jdo/enhancer/ src/java/org/apache/jdo/impl/ src/java/org/apache/jdo/impl/enhancer/ src/java/org/apache/jdo/impl/enhancer/classfile/ src/java/org/apache/jdo/impl/enhancer/core/ src/java/org/apache/jdo/impl/enhancer/generator/ src/java/org/apache/jdo/impl/enhancer/meta/ src/java/org/apache/jdo/impl/enhancer/meta/model/ src/java/org/apache/jdo/impl/enhancer/meta/prop/ src/java/org/apache/jdo/impl/enhancer/meta/util/ src/java/org/apache/jdo/impl/enhancer/util/ src/java/org/apache/jdo/impl/fostore/ src/java/org/apache/jdo/impl/jdoql/ src/java/org/apache/jdo/impl/jdoql/jdoqlc/ src/java/org/apache/jdo/impl/jdoql/scope/ src/java/org/apache/jdo/impl/jdoql/tree/ src/java/org/apache/jdo/impl/model/ src/java/org/apache/jdo/impl/model/java/ src/java/org/apache/jdo/impl/model/java/runtime/ src/java/org/apache/jdo/impl/model/jdo/ src/java/org/apache/jdo/impl/model/jdo/caching/ src/java/org/apache/jdo/impl/model/jdo/util/ src/java/org/apache/jdo/impl/model/jdo/xml/ src/java/org/apache/jdo/impl/pm/ src/java/org/apache/jdo/impl/sco/ src/java/org/apache/jdo/impl/state/ src/java/org/apache/jdo/jdoql/ src/java/org/apache/jdo/jdoql/tree/ src/java/org/apache/jdo/model/ src/java/org/apache/jdo/model/java/ src/java/org/apache/jdo/model/jdo/ src/java/org/apache/jdo/pm/ src/java/org/apache/jdo/sco/ src/java/org/apache/jdo/state/ src/java/org/apache/jdo/store/ src/java/org/apache/jdo/util/ test/ test/conf/ test/enhancer/ test/enhancer/sempdept/ test/enhancer/sempdept/src/ test/enhancer/sempdept/src/empdept/ test/fsuid2/ test/fsuid2/org/ test/fsuid2/org/apache/ test/fsuid2/org/apache/jdo/ test/fsuid2/org/apache/jdo/pc/ test/java/ test/java/org/ test/java/org/apache/ test/java/org/apache/jdo/ test/java/org/apache/jdo/impl/ test/java/org/apache/jdo/impl/fostore/ test/java/org/apache/jdo/pc/ test/java/org/apache/jdo/pc/appid/ test/java/org/apache/jdo/pc/empdept/ test/java/org/apache/jdo/pc/serializable/ test/java/org/apache/jdo/pc/xempdept/ test/java/org/apache/jdo/test/ test/java/org/apache/jdo/test/query/ test/java/org/apache/jdo/test/util/ test/jdo/ test/jdo/org/ test/jdo/org/apache/ test/jdo/org/apache/jdo/ test/jdo/org/apache/jdo/pc/ test/jdo/org/apache/jdo/pc/appid/ test/jdo/org/apache/jdo/pc/empdept/ test/jdo/org/apache/jdo/pc/serializable/ test/jdo/org/apache/jdo/pc/xempdept/ xdocs/ To: jdo-commits@db.apache.org From: mbo@apache.org X-Virus-Checked: Checked X-Spam-Rating: minotaur.apache.org 1.6.2 0/1000/N Added: incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/pm/Persistence= ManagerImpl.java URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/ri11/src/java/org/ap= ache/jdo/impl/pm/PersistenceManagerImpl.java?view=3Dauto&rev=3D158176 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D --- incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/pm/PersistenceMan= agerImpl.java (added) +++ incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/pm/PersistenceMan= agerImpl.java Fri Mar 18 17:02:29 2005 @@ -0,0 +1,2173 @@ +/* + * Copyright 2005 The Apache Software Foundation. + *=20 + * 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=20 + *=20 + * http://www.apache.org/licenses/LICENSE-2.0 + *=20 + * Unless required by applicable law or agreed to in writing, software=20 + * distributed under the License is distributed on an "AS IS" BASIS,=20 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied= .=20 + * See the License for the specific language governing permissions and=20 + * 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; + +/**=20 + * This is the StoreManager independent implemetation of the=20 + * org.apache.jdo.pm.PersistenceManagerInternal interface. Delegates most = of=20 + * the method execution to the corresponding instance of the CacheManagerI= mpl. + *=20 + * @author Marina Vatkina + */=20 +public class PersistenceManagerImpl implements PersistenceManagerInternal { + private final boolean DEBUG =3D true; + =20 + /** + * True if this PersistenceManager is closed + */ + private boolean _isClosed =3D true; + + /** + * Associated Transaction + */ + private TransactionImpl _transaction =3D null; + + /** + * Reference to the associated JTA Transaction if any + */ + private Object _jta =3D null; + + /** + * Current PersistenceManagerWrapper as PersistenceManagerInternal + */ + private PersistenceManagerWrapper current =3D null; + + /** + * PersistenceManagerFactory that created (and could be pooling) + * this PersistenceManager + */ + private PersistenceManagerFactoryImpl pmf =3D null; + + /** + * Reference to the CacheManager + */ + private CacheManagerImpl _txCache =3D null; + + /** + * Flag for Query.=20 + * Constructor defaults it to the PMF setting. + */ + private boolean _ignoreCache; + + /** + * Flag for active transaction + */ + private boolean _activeTransaction =3D false; + + /** + * Flag for optimistic transaction + */ + private boolean optimistic =3D true; + =20 + /** + * Flag for multithreaded support. + */ + private boolean multithreaded =3D true; + + /** + * User Object + */ + private Object _userObject =3D null; + + /** + * Flag for flushing process + */ + private boolean _flushing =3D false; + + /** + * This is the ClassLoader that was the + * Thread.currentThread().getContextClassLoader() + * at the time this PersistenceManagerImpl was created. + */ + private final ClassLoader myClassLoader; + + /** + * Constructor signatures=20 + */ + private static final Class[] sigSCO_Short =3D new Class []{ + java.lang.Object.class, + java.lang.String.class}; + + /** The signature for SCO Collections. + */ =20 + private static final Class[] sigSCO_Collection =3D new Class []{ + java.lang.Class.class, + boolean.class, + int.class}; + + /** The signature for SCO Maps. + */ =20 + private static final Class[] sigSCO_Map =3D new Class []{ + java.lang.Class.class, + java.lang.Class.class, + boolean.class, + int.class}; + + /** The signature for SCO HashSet. + */ =20 + private static final Class[] sigSCO_HashSet =3D new Class []{ + java.lang.Class.class, + boolean.class, + int.class, + float.class}; + + /** The signature for SCO TreeSet. + */ =20 + private static final Class[] sigSCO_TreeSet =3D new Class []{ + java.lang.Class.class, + boolean.class, + java.util.Comparator.class}; + + /** The signature for SCO HashMap. + */ =20 + private static final Class[] sigSCO_HashMap =3D new Class []{ + java.lang.Class.class, + java.lang.Class.class, + boolean.class, + int.class, + float.class}; + + /** The signature for SCO TreeMap. + */ =20 + private static final Class[] sigSCO_TreeMap =3D new Class []{ + java.lang.Class.class, + java.lang.Class.class, + boolean.class, + java.util.Comparator.class}; + + /** Default initialCapacity values. + */ =20 + private static final Integer int11 =3D new Integer(11); + private static final Integer int10 =3D new Integer(10); + + /** RuntimeJavaModelFactory. */ + private static final RuntimeJavaModelFactory javaModelFactory =3D + (RuntimeJavaModelFactory) AccessController.doPrivileged( + new PrivilegedAction () { + public Object run () { + return RuntimeJavaModelFactory.getInstance(); + } + } + ); +=20 + /** + * Logger support + */ + private static final Log logger =3D LogFactory.getFactory().getInstanc= e( + "org.apache.jdo.impl.pm"); // NOI18N + + /** + * I18N message handler + */ + private final static I18NHelper msg =3D=20 + I18NHelper.getInstance(PersistenceManagerImpl.class); + + /** + * Helper objects to identify StateManager associated with the given=20 + * PersistenceCapable instance + */ + private StateManagerInternal lookingFor =3D null; + private PersistenceCapable pc =3D null; + + /** + * Constructs new instance of PersistenceManagerImpl for this + * PersistenceManagerFactoryInternal and particular combination of=20 + * username and password. + * + * @param pmf calling PersistenceManagerFactory as PersistenceManagerF= actoryInternal + * @param username user name used for accessing Connector or null if n= one=20 + * is provided. + * @param password user password used for accessing Connector or null = if=20 + * none is provided. + */ + public PersistenceManagerImpl(PersistenceManagerFactoryInternal pmf, + String username, String password) { + + if (debugging()) + debug("constructor"); // NOI18N + + if (javaModelFactory =3D=3D null) + throw new JDOUserException( + msg.msg("EXC_CannotGetRuntimeJavaModelFactory")); // NOI18N + + this.pmf =3D (PersistenceManagerFactoryImpl)pmf; + _transaction =3D new TransactionImpl(this, this.pmf, username, pas= sword); + _txCache =3D new CacheManagerImpl(this); + + optimistic =3D pmf.getOptimistic(); + _ignoreCache =3D pmf.getIgnoreCache(); + + _isClosed =3D false; + + myClassLoader =3D getContextClassLoaderPrivileged(); + } + + /** + * @see javax.jdo.PersistenceManager#setIgnoreCache(boolean flag) + * @param flag the ignoreCache value + */ + public void setIgnoreCache(boolean flag) { + assertIsOpen(); + _ignoreCache =3D 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. Applicati= ons + * that use multiple threads to invoke methods or access fields from=20 + * 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=20 + * helper instances such as Query, Transaction, or Extent. + * + * @param flag the Multithreaded setting. + */ + public void setMultithreaded(boolean flag) { + assertIsOpen(); + multithreaded =3D flag; + } + =20 + /** Get the current Multithreaded flag for this PersistenceManager. =20 + * @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 =3D=3D 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. + * =20 + *

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 return= ed. + * 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 =3D=3D 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 =3D null; + + if (null !=3D given) { + try { + rc =3D Class.forName(name, true, given); + } catch (ClassNotFoundException ex) { + } + } + + if (null =3D=3D rc) { + try { + rc =3D Class.forName( + name, true, + getContextClassLoaderPrivileged()); + } catch (ClassNotFoundException ex) { + } + } + + if (null =3D=3D rc) { + rc =3D Class.forName(name, true, myClassLoader); + } + + return rc; =20 + } + + /** + * @see org.apache.jdo.pm.PersistenceManagerInternal#loadPCClassForObj= ectIdClass + */ + public Class loadPCClassForObjectIdClass(Class objectIdClass)=20 + throws ClassNotFoundException + { + if (debugging()) + debug("loadPCClassForObjectIdClass: " + objectIdClass.getName(= )); //NOI18N + + JavaModel javaModel =3D null; + JDOClass jdoClass =3D null; + JavaType objectIdJavaType =3D javaModelFactory.getJavaType(objectI= dClass); + // try Model of objectId's class loader + ClassLoader classLoader =3D=20 + javaModelFactory.getClassLoaderPrivileged(objectIdClass); + javaModel =3D javaModelFactory.getJavaModel(classLoader); + jdoClass =3D javaModel.getJDOModel(). + getJDOClassForObjectIdClass(objectIdJavaType); + =20 + if (null =3D=3D jdoClass) { + // try Model of thread context class loader + classLoader =3D getContextClassLoaderPrivileged(); + javaModel =3D javaModelFactory.getJavaModel(classLoader); + jdoClass =3D javaModel.getJDOModel(). + getJDOClassForObjectIdClass(objectIdJavaType); + } + + if (null =3D=3D jdoClass) { + // try Model of the pm's thead context class loader + javaModel =3D javaModelFactory.getJavaModel(myClassLoader); + jdoClass =3D javaModel.getJDOModel(). + getJDOClassForObjectIdClass(objectIdJavaType); + } + + if (jdoClass =3D=3D null)=20 + // persistence-capable class not found =3D> ClassNotFoundExcep= tion + 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 =3D null; + if ( pc instanceof PersistenceCapable ) { + PersistenceCapable p =3D (PersistenceCapable)pc; + if( !(p.jdoIsPersistent()) ) { + throw new JDOFatalInternalException(msg.msg( + "EXC_TransientInstance", pc.getClass().getName()));// = NOI18N + } + + StateManagerInternal sm =3D findStateManager(p); + if (sm =3D=3D null) { + throw new JDOFatalInternalException( + msg.msg("EXC_CannotFindSM", pc.getClass().getName()));= // NOI18N + } + rc =3D sm.getInternalObjectId(); + } + return rc; + } + + /** + * @see javax.jdo.PersistenceManager#getTransactionalObjectId + */ + public Object getTransactionalObjectId (Object pc) { + if (debugging()) + debug("getTransactionalObjectId"); // NOI18N + + return getExternalObjectId(pc, true); + } + + /**=20 + * This method returns an object id instance corresponding to the Clas= s=20 + * and String arguments. The String argument might have been the=20 + * result of executing toString on an object id instance.=20 + * @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); + } + =20 + /** 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. + * =20 + *

In order for the application to construct an instance of the Obje= ctId 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 + */ =20 + public Class getObjectIdClass(Class cls) { + if (debugging()) + debug("getObjectIdClass for: " + cls); // NOI18N + + assertIsOpen(); + return pmf.getObjectIdClass(cls); + } + =20 + // + // -------- Query and Extent methods -------- + // + + /** Create a new Query with no elements. + * @return a new Query instance with no elements. + */ =20 + public Query newQuery() { + assertIsOpen(); + return new QueryImpl(this); + } + + /** Create a new Query using elements from another Query. The other Q= uery + * 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 + */ =20 + 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 langua= ge + * @return the new Query + */ =20 + 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 + } + =20 + /** 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 */ =20 + public Query newQuery(Extent cln) { + assertIsOpen(); + return new QueryImpl(this, cln); + } + + /** Create a new Query with the Class of the results and candidate Col= lection. + * 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 Collec= tion, + * 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 */ =20 + 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 subcla= sses) { + if (debugging()) + debug("getExtent for: " + persistenceCapableClass + // NOI18N + ", subclasses: " + subclasses); // NOI18N + + assertIsOpen(); + Extent rc =3D null; + if (PersistenceCapable.class.isAssignableFrom(persistenceCapableCl= ass)) { + rc =3D this.getStoreManager().getExtent(persistenceCapableClas= s, subclasses, this); + } else { + throw new JDOUserException(msg.msg( + "EXC_ClassNotPersistenceCapable", persistenceCapableClass.= getName())); // NOI18N + } + if (null =3D=3D rc) { + // Protect against bogus store managers that return null. + rc =3D 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 =3D cls; + this.subclasses =3D 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 pers= istent, + * 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. + * =20 + * @param pc a persistent instance + */=20 + 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) + */ =20 + 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. + * =20 + *

The instance loses its JDO identity and it is no longer associated + * with any PersistenceManager. The state of fields is preserved uncha= nged. + * @param pc the instance to make transient. + */ =20 + public void makeTransient(Object pc) { + if (debugging()) + debug("makeTransient"); // NOI18N + + assertIsOpen(); + makeTransientInternal(pc); + } + =20 + /** Make an array of instances transient, removing them from managemen= t by this + * PersistenceManager. + * =20 + *

The instances lose their JDO identity and they are no longer asso= ciated + * with any PersistenceManager. The state of fields is preserved uncha= nged. + * @param pcs the instances to make transient. + */ =20 + public void makeTransientAll(Object[] pcs) { + if (debugging()) + debug("makeTransientAll"); // NOI18N + + assertIsOpen(); + makeTransientAllInternal(pcs); + } + =20 + /** Make a Collection of instances transient, removing them from manag= ement by this + * PersistenceManager. + * =20 + *

The instances lose their JDO identity and they are no longer asso= ciated + * with any PersistenceManager. The state of fields is preserved uncha= nged. + * @param pcs the instances to make transient. + */ =20 + public void makeTransientAll(Collection pcs) { + if (debugging()) + debug("makeTransientAll"); // NOI18N + + assertIsOpen(); + makeTransientAll(pcs.toArray()); + } + + /** Make an instance subject to transactional boundaries. + * =20 + *

Transient instances normally do not observe transaction boundarie= s=2E + * This method makes transient instances sensitive to transaction compl= etion. + * If an instance is modified in a transaction, and the transaction rol= ls back, + * the state of the instance is restored to the state before the first = change + * in the transaction. + * =20 + *

For persistent instances read in optimistic transactions, this me= thod + * allows the application to make the state of the instance part of the + * transactional state. At transaction commit, the state of the instan= ce in + * cache is compared to the state of the instance in the data store. I= f they + * are not the same, then an exception is thrown. + * @param pc the instance to make transactional. + */ =20 + public void makeTransactional(Object pc) { + if (debugging()) + debug("makeTransactional"); // NOI18N + + assertIsOpen(); + makeTransactionalInternal(pc); + } + =20 + /** 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); + } + =20 + /** 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 t= he + * 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); + } + =20 + /** 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. + */ =20 + 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. + */ =20 + 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. + */ =20 + 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) + */ =20 + public void evictAll() { + if (debugging()) + debug("evictAll()"); // NOI18N + + assertIsOpen(); + _txCache.evictAll(); + } + + + /** Refresh the state of the instance from the data store. + * =20 + *

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 subse= quent + * commit is more likely to succeed. + *

Outside a transaction, this method will refresh nontransactional = state. + * @param pc the instance to refresh. + */ =20 + public void refresh(Object pc) {=20 + if (debugging()) + debug("refresh"); // NOI18N + + assertIsOpen(); + refreshInternal(pc); + } + =20 + /** Refresh the state of an array of instances from the data store. + * =20 + * @see #refresh(Object pc) + * @param pcs the array of instances to refresh. + */ =20 + public void refreshAll(Object[] pcs) { + if (debugging()) + debug("refreshAll"); // NOI18N + + assertIsOpen(); + refreshAllInternal(pcs); + } + =20 + /** 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()); + } + =20 + /** 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();=20 + } else { + _txCache.refreshAllNontransactional();=20 + } + } + + /** 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); + } + =20 + /** 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); + } + =20 + /** 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 fie= lds + * @since 1.0.1 + */ + public void retrieveAll (Object[] pcs, boolean DFGOnly) { + if (debugging()) + debug("retrieveAll, DFGOnly: " + DFGOnly); // NOI18N + + assertIsOpen(); + retrieveAllInternal(pcs, DFGOnly); + } + + =20 + /** 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); + } + =20 + /** 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 fie= lds + * @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 + */ =20 + public PersistenceManagerFactory getPersistenceManagerFactory() { + assertIsOpen(); + return (PersistenceManagerFactory)pmf; + } + =20 + /** 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 + */ =20 + public void setUserObject(Object o) { + assertIsOpen(); + this._userObject =3D o; + } + =20 + /** 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 + */ =20 + public Object getUserObject() { + assertIsOpen(); + return _userObject; + } + =20 + /** The JDO vendor might store certain non-operational properties and + * make those properties available to applications (for troubleshooting= )=2E + * =20 + *

Standard properties include: + *

  • VendorName
  • + *
  • VersionNumber
  • + * @return the Properties of this PersistenceManager + */ =20 + public Properties getProperties() { + assertIsOpen(); + return JDORIVersion.getVendorProperties(); + } + + // + // Implement PersistenceManagerInternal methods + // + + /** + * assert this PM instance is open + */ + public void assertIsOpen() { + if (_isClosed) { + throw new JDOFatalUserException(msg.msg( + "EXC_PersistenceManagerClosed"));// NOI18N + } + // this is synchronized on pmf.closeLock + pmf.assertNotClosed(); + } + + /** + * @see org.apache.jdo.pm.PersistenceManagerInternal#getStoreManager() + */ + public StoreManager getStoreManager() { + return pmf.getStoreManager(this); + } + + // + // -------- SCO Instance creation methods -------- + // + + /** + * Called by internally by the runtime to create a new tracked instanc= e=2E + * Will not result in marking field as dirty + * + * @see PersistenceManagerInternal#newSCOInstanceInternal (Class type) + */ =20 + public Object newSCOInstanceInternal (Class type) { + if (debugging()) + debug("newSCOInstanceInternal for: " + type); // NOI18N + + Class newType =3D pmf.getTrackedClass(type); + if (newType =3D=3D null) { + // Not found - means not supported. Return null here for + // the internal calls.=20 + return null; + } + + Object obj =3D null; + + try { + Constructor constr =3D newType.getConstructor(null); + + if (constr !=3D null) { + obj =3D constr.newInstance(null); + } + } catch (Exception e) { + throw new JDOUserException(msg.msg( + "EXC_CannotConstructSCO",// NOI18N + newType.getName()), e); + } + + return obj; + } + + /** + * Called by internally by the runtime to create a new tracked instanc= e=2E + * Will not result in marking field as dirty + * + * @see PersistenceManagerInternal#newCollectionInstanceInternal(Class= type, + Class elementType, boolean allowNulls, Integer initialSize, + Float loadFactor, Collection initialContents, Comparator comparato= r) + */ + public Collection newCollectionInstanceInternal( + Class type, + Class elementType, boolean allowNulls, Integer initialSize, + Float loadFactor, Collection initialContents, Comparator comparato= r) { + + if (debugging()) + debug("newCollectionInstanceInternal for: " + type); // NOI18N + + Class newType =3D pmf.getTrackedClass(type); + if (newType =3D=3D null) { + // Not found - means not supported. Return null here for + // the internal calls.=20 + return null; + } + + Object obj =3D null; + SCOCollection rc =3D null; + + + try { + if (org.apache.jdo.impl.sco.TreeSet.class =3D=3D newType) { + // Comparator can be null. + Constructor constr =3D newType.getConstructor(sigSCO_TreeS= et); + + if (constr !=3D null) { + obj =3D constr.newInstance( + new Object[] { + elementType, + new Boolean(allowNulls), comparator + }); + } + } else if (null =3D=3D loadFactor) { =20 + // If loadFactor is null, then it might be a HashSet. If = loadFactor + // is not null, it must be a HashSet, or we'll throw an ex= ception below. + + Constructor constr =3D newType.getConstructor(sigSCO_Colle= ction); + + if (constr !=3D null) { + if (initialSize =3D=3D null) { + initialSize =3D getInitialSize(newType); + } + obj =3D constr.newInstance( + new Object[] { + elementType, + new Boolean(allowNulls), initialSize + }); + } + } else if (org.apache.jdo.impl.sco.HashSet.class =3D=3D newTyp= e) { + Constructor constr =3D newType.getConstructor(sigSCO_HashS= et); + =20 + if (constr !=3D null) { + if (initialSize =3D=3D null) { + initialSize =3D getInitialSize(newType); + } + obj =3D constr.newInstance( + new Object[] { + elementType, + new Boolean(allowNulls), initialSize, loadFact= or + }); + // We don't have a good way of testing this, because + // HashSet is opaque w.r.t. loadFactor. Uncommenting = this + // is all I can suggest! + /* + System.out.println( + "newCollection: loadFactor " + loadFactor); // NOI= 18N + */ + } + } else { + throw new IllegalArgumentException(msg.msg( + "EXC_IllegalArguments",// NOI18N + type.getName())); + } + rc =3D (SCOCollection)obj; + if (initialContents !=3D null && initialContents.size() > 0) { + // Do not use addAllInternal to verify element types of + // initialContents. + rc.addAll(initialContents); + } + } catch (IllegalArgumentException e) { + throw e; + } catch (Exception e) { + throw new JDOUserException(msg.msg( + "EXC_CannotConstructSCO",// NOI18N + newType.getName()), e); + } + return rc; + } + + /** + * Called by internally by the runtime to create a new tracked instanc= e=2E + * Will not result in marking field as dirty. + * + * @see PersistenceManagerInternal#newMapInstanceInternal(Class type, + Class keyType, Class valueType, boolean allowNulls, Integer initia= lSize, + Float loadFactor, Map initialContents, Comparator comparator) + */ + public Map newMapInstanceInternal( + Class type, + Class keyType, Class valueType, boolean allowNulls, Integer initia= lSize, + Float loadFactor, Map initialContents, Comparator comparator) { + + if (debugging()) + debug("newMapInstanceInternal for: " + type); // NOI18N + + Class newType =3D pmf.getTrackedClass(type); + if (newType =3D=3D null) { + // Not found - means not supported. Return null here for + // the internal calls.=20 + return null; + } + + Object obj =3D null; + SCOMap rc =3D null; + + + try { + if (org.apache.jdo.impl.sco.TreeMap.class =3D=3D newType) { + // Comparator can be null. + Constructor constr =3D newType.getConstructor(sigSCO_TreeM= ap); + + if (constr !=3D null) { + obj =3D constr.newInstance( + new Object[] { + keyType, + valueType, + new Boolean(allowNulls), comparator + }); + } + } else if (null =3D=3D loadFactor) { =20 + // It is not TreeMap, so it should be either HashMap or Ha= shtable + // and they can be constructed with or without loadFactor. + Constructor constr =3D newType.getConstructor(sigSCO_Map); + + if (constr !=3D null) { + if (initialSize =3D=3D null) { + initialSize =3D getInitialSize(newType); + } + obj =3D constr.newInstance( + new Object[] { + keyType, + valueType, + new Boolean(allowNulls), initialSize + }); + } + } else if (org.apache.jdo.impl.sco.HashMap.class =3D=3D newTyp= e || + org.apache.jdo.impl.sco.Hashtable.class =3D=3D newType) { + Constructor constr =3D newType.getConstructor(sigSCO_HashM= ap); + =20 + if (constr !=3D null) { + if (initialSize =3D=3D null) { + initialSize =3D getInitialSize(newType); + } + obj =3D constr.newInstance( + new Object[] { + keyType, + valueType, + new Boolean(allowNulls), initialSize, loadFact= or + }); + // We don't have a good way of testing this, because + // HashMap is opaque w.r.t. loadFactor. Uncommenting = this + // is all I can suggest! + /* + System.out.println( + "newMap: loadFactor " + loadFactor); // NOI18N + */ + } + } else { + throw new IllegalArgumentException(msg.msg( + "EXC_IllegalArguments",// NOI18N + type.getName())); + } + rc =3D (SCOMap)obj; + if (initialContents !=3D null && initialContents.size() > 0) { + // Do not use putAllInternal to verify key/value types of + // initialContents. + rc.putAll(initialContents); + } + } catch (IllegalArgumentException e) { + throw e; + } catch (Exception e) { + throw new JDOUserException(msg.msg( + "EXC_CannotConstructSCO",// NOI18N + newType.getName()), e); + } + return rc; + } + + // + // ----------- StateManger interaction methods ----------------- + // + + /** + * + * @see PersistenceManagerInternal#isSupportedSCOType (Class type) + */ =20 + public boolean isSupportedSCOType (Class type) { + return (pmf.getTrackedClass(type) !=3D null); + } + + /** + * @see PersistenceManagerInternal#register(StateManagerInternal sm, O= bject oid,=20 + * boolean transactional, boolean throwDuplicateException) + */ + public void register(StateManagerInternal sm, Object oid, boolean tran= sactional,=20 + boolean throwDuplicateException) { + if (debugging()) + debug("register" + oid); // NOI18N + + _txCache.register(sm, oid, transactional, throwDuplicateException); + } + + /** + * @see PersistenceManagerInternal#registerTransient(StateManagerInter= nal sm) + */ + public void registerTransient(StateManagerInternal sm) { + if (debugging()) + debug("registerTransient"); // NOI18N + + _txCache.registerTransient(sm); + } + + /** + * @see PersistenceManagerInternal#deregister(Object oid) + */ + public void deregister(Object oid) { + if (debugging()) + debug("deregister" + oid); // NOI18N + + _txCache.deregister(oid); + } + + /** + * @see PersistenceManagerInternal#deregisterTransient(StateManagerInt= ernal sm) + */ + public void deregisterTransient(StateManagerInternal sm) { + if (debugging()) + debug("deregisterTransient"); // NOI18N + + _txCache.deregisterTransient(sm); + } + + /** + * @see PersistenceManagerInternal#replaceObjectId(Object oldId, Objec= t newId) + */ + public void replaceObjectId(Object oldId, Object newId) { + if (debugging()) + debug("replaceObjectId old: " + oldId + " new: " + newId); // = NOI18N + + if (!newId.equals(oldId)) { + _txCache.replaceObjectId(oldId, newId); + } + } + + /** + * @see PersistenceManagerInternal#markAsFlushed(StateManagerInternal = sm) + */ + public void markAsFlushed(StateManagerInternal sm) { + if (debugging()) + debug("markAsFlushed"); // NOI18N + + if (!_flushing) { + _txCache.markAsFlushed(sm); + } + } + + /** + * @see PersistenceManagerInternal#insideCommit() + */ + public boolean insideCommit() { + return _transaction.startedCommit(); + } + + /** A helper method called from the StateManager inside getPersistence= Manager() + * to identify StateManager associated with this PC instance + * @param pc PC instance=20 + * @param sm StateManager to save + */ + public synchronized void hereIsStateManager(StateManagerInternal sm,=20 + PersistenceCapable pc) { + if (debugging()) + debug("hereIsStateManager"); // NOI18N + + if (this.pc =3D=3D pc) { + lookingFor =3D sm; + } + } + + /** + * @see PersistenceManagerInternal#getStateManager + */ + public StateManagerInternal getStateManager(Object oid, Class pcClass)= { + if (debugging()) + debug("getStateManager"); // NOI18N + + return _txCache.getStateManager(oid, pcClass); + } + + /** A helper method to find the StateManager associated with this PC i= nstance + * @param pc PC instance + * @return StateManager as StateManagerInternal + */ + public synchronized StateManagerInternal findStateManager(PersistenceC= apable pc) { + if (debugging()) + debug("findStateManager"); // NOI18N + + lookingFor =3D null; + this.pc =3D pc; + // pc.jdoGetPersistenceManager() returns the wrapper. It should co= mpare equals + // to this PersistenceManager: + PersistenceManager pm =3D pc.jdoGetPersistenceManager(); + if (debugging()) + debug("findStateManager " + pm); // NOI18N + + if (pm !=3D null && !this.equals(pm)) { + throw new JDOUserException(msg.msg( + "EXC_AnotherPersistenceManager"));// NOI18N + } + return lookingFor; + } =20 + + /** + * Returns current wrapper + */ + public PersistenceManager getCurrentWrapper() { + return current; + } + + /** + * Returns a Collection of instances that has been made persistent + * or become persistent through persistence-by-reachability + * algorithm in this transaction. Called by the Extent.iterator. + * @see PersistenceManagerInternal#getInsertedInstances + * @return Collection of Persistent-New instances. + */ + public Collection getInsertedInstances() { + if (debugging()) + debug("getInsertedInstances"); // NOI18N + + return _txCache.getInsertedInstances(); + } + + /** + * Returns a hash code value for this PersistenceManager. + * @return a hash code value for this PersistenceManager. + */ =20 + public int hashCode() { + return super.hashCode(); + } +=20 + /** =20 + * Indicates whether some other object is "equal to" this one. + * @param obj the reference object with which to compare. + * @return true if this object is the same as the obj + * argument; false otherwise. + */ =20 + public boolean equals(Object obj) { + if (obj instanceof PersistenceManagerWrapper) { + return (((PersistenceManagerWrapper)obj).getPersistenceManager= () =3D=3D this);=20 +=20 + } else if (obj instanceof PersistenceManagerImpl) { + return (((PersistenceManagerImpl)obj) =3D=3D this);=20 + }=20 + return false;=20 + }=20 + + // + // ----------- Protected methods ----------------- + // + + /** + * Remember the current wrapper + */ + protected void pushCurrentWrapper(PersistenceManagerWrapper pmw) { + if (debugging()) + debug("pushCurrentWrapper"); // NOI18N + + current =3D pmw; + } + + /** + * Replace current wrapper with the previous + */ + protected void popCurrentWrapper(PersistenceManagerWrapper prev) { + if (debugging()) + debug("popCurrentWrapper"); // NOI18N + + current =3D prev; + if (_jta =3D=3D null && current =3D=3D null) { + this.close(); + } + } + + /** + * with the current thread in the managed environment + */ + protected void setJTATransaction(Object t) { + if (debugging()) + debug("setJTATransaction"); // NOI18N + + if (this._jta !=3D null) { + throw new JDOFatalInternalException( + msg.msg("EXC_NotNullJTATransaction")); //NOI18N + } + this._jta =3D t; + } + + /** + * Disassociate this PersistenceManager with the current JTA + * transaction. + */ + protected void deregisterJTA() { + if (debugging()) + debug("deregisterJTA"); // NOI18N + + pmf.deregisterPersistenceManager(this, _jta); + _jta =3D null; + } + + /**=20 + * 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 =3D null; + _jta =3D null; + _isClosed =3D true; + _transaction =3D null; + _txCache =3D null; + _userObject =3D 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.updateP= ersistent() + * on each instance + */ + protected void flushInstances() { + if (debugging()) + debug("flushInstances"); // NOI18N + + assertIsOpen(); + assertActiveTransaction(false); + _flushing =3D true; + + try { + _txCache.flushInstances(); + } finally { + _flushing =3D 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 =3D true; + boolean abort =3D ((status =3D=3D Status.STATUS_ROLLEDBACK) || + (status =3D=3D Status.STATUS_ROLLING_BACK) || + (status =3D=3D Status.STATUS_MARKED_ROLLBACK)); + _txCache.afterCompletion(abort); + _flushing =3D 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 actu= al + * 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 =3D isActive; + } + + /** + * For Transaction to notify PersistenceManager that + * optimistic flag is changed + */ + protected synchronized void notifyOptimistic(boolean optimistic) { + this.optimistic =3D 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 !=3D null && pc instanceof PersistenceCapable) { + PersistenceCapable p =3D (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=20 + */ + private void assertActiveTransaction(boolean insideQuery) { + if (_flushing || (insideQuery && _transaction.getNontransactionalR= ead())) { + 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 =3D null; + if (pc instanceof Collection) { + message =3D msg.msg("EXC_CollectionType", caller); // NOI1= 8N + } else if (pc.getClass().isArray()) { + message =3D msg.msg("EXC_ArrayType", caller); + } else { + message =3D msg.msg("EXC_NotPersistenceCapable", pc.getCla= ss().getName()); // NOI18N + } + throw new JDOUserException(message, pc); + } + + } + + /** + * assert PersistenceCapable is associated with this instance of Persi= stenceManager + */ =20 + private void assertPersistenceManager(PersistenceCapable pc) { + // pc.jdoGetPersistenceManager() returns the wrapper. It should co= mpare 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. + */ =20 + private void validateResult(int l, Throwable[] err) { + if (l > 0) { + Throwable[] t =3D new Throwable[l]; + System.arraycopy(err, 0, t, 0, l); + throw new JDOUserException(msg.msg( + "EXC_FailedToProcessAll"), t); //(Throwable[])err.toArray(= ));// NOI18N + }=20 + } + /** + * 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. + */ =20 + 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; + } + } + =20 + // + // Internal methods to process state transitions requests. + // + + /** + * Internal method for processing makePersistent request. + * @see #makePersistent(Object pc) + */ + private void makePersistentInternal(Object pc) { + if (pc =3D=3D 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 =3D (PersistenceCapable)pc; + _txCache.makePersistent(p); + } + + /** + * Internal method for processing makePersistentAll request. + * @see #makePersistentAll(Object[] pcs) + */ + private void makePersistentAllInternal(Object[] pcs) { + Throwable[] err =3D new Throwable[pcs.length]; + int l =3D 0; + + if (debugging()) + debug("makePersistentAllInternal " + pcs.length); // NOI18N + for(int i =3D 0; i < pcs.length; i++) { + try { + makePersistentInternal(pcs[i]); + } catch (Throwable e) { + err[l++] =3D e; + } + } + validateResult(l, err); + } + + /** + * Internal method to process deletePersistent call. + * @see #deletePersistent(Object pc) + */ + private void deletePersistentInternal(Object pc) { + if (pc =3D=3D null) { + return; // ignore + } + assertPersistenceCapable(pc, "deletePersistent"); + =20 + PersistenceCapable p =3D (PersistenceCapable)pc; + + if( !(p.jdoIsPersistent()) ) { + throw new JDOUserException(msg.msg( + "EXC_TransientInstance", pc.getClass().getName()));// NOI1= 8N + } + + StateManagerInternal sm =3D findStateManager(p); + sm.deletePersistent(); + } + =20 + /** + * Internal method to process deletePersistentAll call. + * @see #deletePersistentAll(Object[] pcs) + */ + private void deletePersistentAllInternal(Object[] pcs) { + Throwable[] err =3D new Throwable[pcs.length]; + int l =3D 0; + + for(int i =3D 0; i < pcs.length; i++) {=20 + try { + deletePersistentInternal(pcs[i]);=20 + } catch (Throwable e) { + err[l++] =3D e; + } + } + validateResult(l, err); + } + + /** + * Internal method to process makeTransient call. + * @see #makeTransient(Object pc) + */ =20 + private void makeTransientInternal(Object pc) { + if (pc =3D=3D null) { + return; // ignore + } + assertPersistenceCapable(pc, "makeTransient"); + + PersistenceCapable p =3D (PersistenceCapable)pc; + _txCache.makeTransient(p); + } + + /** + * Internal method to process makeTransientAll call. + * @see #makeTransientAll(Object[] pcs) + */ =20 + private void makeTransientAllInternal(Object[] pcs) { + Throwable[] err =3D new Throwable[pcs.length]; + int l =3D 0; + + for(int i =3D 0; i < pcs.length; i++) {=20 + try { + makeTransientInternal(pcs[i]); + } catch (Throwable e) { + err[l++] =3D e; + } + } + validateResult(l, err); + } + + /** + * Internal method to process makeTransactional call. + * @see #makeTransactional(Object pc) + */ =20 + private void makeTransactionalInternal(Object pc) { + if (pc =3D=3D null) { + return; // ignore + } + assertPersistenceCapable(pc, "makeTransactional"); + =20 + PersistenceCapable p =3D (PersistenceCapable)pc; + if (p.jdoIsPersistent()) { + assertActiveTransaction(false); + } + + _txCache.makeTransactional(p); + } + + /** + * Internal method to process makeTransactionalAll call. + * @see #makeTransactionalAll(Object[] pcs) + */ =20 + private void makeTransactionalAllInternal(Object[] pcs) { + Throwable[] err =3D new Throwable[pcs.length]; + int l =3D 0; + + for(int i =3D 0; i < pcs.length; i++) { + try { + makeTransactionalInternal(pcs[i]); + } catch (Throwable e) { + err[l++] =3D e; + } + } + validateResult(l, err); + } + + /** + * Internal method to process makeNontransactional call. + * @see #makeNontransactional(Object pc) + */ =20 + private void makeNontransactionalInternal(Object pc) { + if (pc =3D=3D null) { + return; // ignore + } + assertPersistenceCapable(pc, "makeNontransactional"); + =20 + PersistenceCapable p =3D (PersistenceCapable)pc; + _txCache.makeNontransactional(p); + } + + /** + * Internal method to process makeNontransactionalAll call. + * @see #makeNontransactionalAll(Object[] pcs) + */ =20 + private void makeNontransactionalAllInternal(Object[] pcs) { + Throwable[] err =3D new Throwable[pcs.length]; + int l =3D 0; + + for(int i =3D 0; i < pcs.length; i++) { + try { + makeNontransactionalInternal(pcs[i]); + } catch (Throwable e) { + err[l++] =3D e; + } + } + validateResult(l, err); + } + + /** + * Internal method to process evict call. + * @see #evict(Object pc) + */ =20 + private void evictInternal(Object pc) { + if (pc =3D=3D null) { + return; // ignore + } + assertPersistenceCapable(pc, "evict"); + + PersistenceCapable p =3D (PersistenceCapable)pc; + _txCache.evict(p); + } + + /** + * Internal method to process evictAll call. + * @see #evictAll(Object[] pcs) + */ =20 + private void evictAllInternal(Object[] pcs) { + Throwable[] err =3D new Throwable[pcs.length]; + int l =3D 0; + + for(int i =3D 0; i < pcs.length; i++) { + try { + evict(pcs[i]); + } catch (Throwable e) { + err[l++] =3D e; + } + } + validateResult(l, err); + } + + /** + * Internal method to process refresh call. + * @see #refresh(Object pc) + */ =20 + private void refreshInternal(Object pc) { + if (pc =3D=3D null) { + return; // ignore + } + assertPersistenceCapable(pc, "refresh"); + + PersistenceCapable p =3D (PersistenceCapable)pc; + _txCache.refresh(p); + } + + /** + * Internal method to process refreshAll call. + * @see #refreshAll(Object[] pcs) + */ =20 + private void refreshAllInternal(Object[] pcs) { + Throwable[] err =3D new Throwable[pcs.length]; + int l =3D 0; + + for(int i =3D 0; i < pcs.length; i++) { + try { + refresh(pcs[i]); + } catch (Throwable e) { + err[l++] =3D e; + } + } + validateResult(l, err); + } + + /** + * Internal method to process retrieve call. + * @see #retrieve(Object pc) + */ =20 + private void retrieveInternal(Object pc, boolean DFGOnly) { + // XXX the DFGOnly flag is ignored here. + if (pc =3D=3D null) { + return; // ignore + } + assertPersistenceCapable(pc, "retrieve"); + + PersistenceCapable p =3D (PersistenceCapable)pc; + _txCache.retrieve(p); + } + + /** + * Internal method to process retrieveAll call. + * @see #retrieveAll(Object[] pcs) + */ =20 + private void retrieveAllInternal(Object[] pcs, boolean DFGOnly) { + Throwable[] err =3D new Throwable[pcs.length]; + int l =3D 0; + + for(int i =3D 0; i < pcs.length; i++) { + try { + retrieveInternal(pcs[i], DFGOnly); + } catch (Throwable e) { + err[l++] =3D 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.=20 + * @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(); + } + } + ); + } + =20 + /** + * Assert the NontransactionalRead flag is true or a transaction is ac= tive. + */ + public void assertReadAllowed() { + assertIsOpen(); + _transaction.assertReadAllowed(); + } + =20 +}