Added: incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/pm/PersistenceManagerWrapper.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/pm/PersistenceManagerWrapper.java?view=auto&rev=158176
==============================================================================
--- incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/pm/PersistenceManagerWrapper.java (added)
+++ incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/pm/PersistenceManagerWrapper.java Fri Mar 18 17:02:29 2005
@@ -0,0 +1,764 @@
+/*
+ * 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.
+ */
+
+/*
+ * PersistenceManagerWrapper.java
+ *
+ * Created on January 16, 2001
+ */
+
+package org.apache.jdo.impl.pm;
+
+import java.util.*;
+
+import javax.jdo.*;
+
+import org.apache.jdo.pm.PersistenceManagerInternal;
+import org.apache.jdo.util.I18NHelper;
+
+
+/**
+ * This is a thin wrapper for the current implemetation of javax.jdo.PersistenceManager
+ * interface. Delegates most of method execution to the corresponding instance of
+ * the PersistenceManagerImpl. Becomes invalid after PersistenceManager is closed.
+ *
+ * @author Marina Vatkina
+ */
+public class PersistenceManagerWrapper implements PersistenceManager {
+
+ // Previous PersistenceManagerWrapper
+ private PersistenceManagerWrapper prev = null;
+
+ // Actual PersistenceManager
+ private PersistenceManagerImpl pm = null;
+
+ // Boolean flag that allows to use this wrapper
+ private boolean isValid = false;
+
+ /**
+ * I18N message handler
+ */
+ private final static I18NHelper msg =
+ I18NHelper.getInstance("org.apache.jdo.impl.pm.Bundle"); // NOI18N
+
+ // Constructed by PersistenceManagerFactoryImpl
+ PersistenceManagerWrapper(PersistenceManagerImpl pm) {
+ this.pm = pm;
+ prev = (PersistenceManagerWrapper)pm.getCurrentWrapper();
+ pm.pushCurrentWrapper(this);
+ isValid = true;
+ }
+
+ /**
+ * @see javax.jdo.PersistenceManager#isClosed()
+ */
+ public boolean isClosed() {
+ if (isValid) {
+ return pm.isClosed();
+ } else {
+ return true;
+ }
+ }
+
+
+ /**
+ * @see javax.jdo.PersistenceManager#close()
+ */
+ public void close() {
+ if (isValid) {
+ pm.popCurrentWrapper(prev);
+ isValid = false;
+ } else {
+ throw new JDOFatalUserException(msg.msg(
+ "EXC_PersistenceManagerClosed"));// NOI18N
+ }
+ }
+
+ /**
+ * @see javax.jdo.PersistenceManager#currentTransaction()
+ */
+ public Transaction currentTransaction() {
+ if (isValid) {
+ return pm.currentTransaction();
+ } else {
+ throw new JDOFatalUserException(msg.msg(
+ "EXC_PersistenceManagerClosed"));// NOI18N
+ }
+ }
+
+ /**
+ * @see javax.jdo.PersistenceManager#setIgnoreCache(boolean flag)
+ */
+ public void setIgnoreCache(boolean flag) {
+ if (isValid) {
+ pm.setIgnoreCache(flag);
+ } else {
+ throw new JDOFatalUserException(msg.msg(
+ "EXC_PersistenceManagerClosed"));// NOI18N
+ }
+ }
+
+ /**
+ * @see javax.jdo.PersistenceManager#getIgnoreCache()
+ */
+ public boolean getIgnoreCache() {
+ if (isValid) {
+ return pm.getIgnoreCache();
+ } else {
+ throw new JDOFatalUserException(msg.msg(
+ "EXC_PersistenceManagerClosed"));// NOI18N
+ }
+
+ }
+
+ /**
+ * @see javax.jdo.PersistenceManager#getMultithreaded()
+ */
+ public boolean getMultithreaded() {
+ if (isValid) {
+ return pm.getMultithreaded();
+ } else {
+ throw new JDOFatalUserException(msg.msg(
+ "EXC_PersistenceManagerClosed"));// NOI18N
+ }
+ }
+
+ /**
+ * @see javax.jdo.PersistenceManager#setMultithreaded(boolean flag)
+ */
+ public void setMultithreaded(boolean flag) {
+ if (isValid) {
+ pm.setMultithreaded(flag);
+ } else {
+ throw new JDOFatalUserException(msg.msg(
+ "EXC_PersistenceManagerClosed"));// NOI18N
+ }
+ }
+
+ /**
+ * @see javax.jdo.PersistenceManager#evict(Object pc)
+ */
+ public void evict(Object pc) {
+ if (isValid) {
+ pm.evict(pc);
+ } else {
+ throw new JDOFatalUserException(msg.msg(
+ "EXC_PersistenceManagerClosed"));// NOI18N
+ }
+ }
+
+ /**
+ * @see javax.jdo.PersistenceManager#evictAll(Object[] pcs)
+ */
+ public void evictAll(Object[] pcs) {
+ if (isValid) {
+ pm.evictAll(pcs);
+ } else {
+ throw new JDOFatalUserException(msg.msg(
+ "EXC_PersistenceManagerClosed"));// NOI18N
+ }
+ }
+
+ /**
+ * @see javax.jdo.PersistenceManager#evictAll(Collection pcs)
+ */
+ public void evictAll(Collection pcs) {
+ if (isValid) {
+ pm.evictAll(pcs);
+ } else {
+ throw new JDOFatalUserException(msg.msg(
+ "EXC_PersistenceManagerClosed"));// NOI18N
+ }
+ }
+
+ /**
+ * @see javax.jdo.PersistenceManager#evictAll()
+ */
+ public void evictAll() {
+ if (isValid) {
+ pm.evictAll();
+ } else {
+ throw new JDOFatalUserException(msg.msg(
+ "EXC_PersistenceManagerClosed"));// NOI18N
+ }
+ }
+
+ /**
+ * @see javax.jdo.PersistenceManager#refresh(Object pc)
+ */
+ public void refresh(Object pc) {
+ if (isValid) {
+ pm.refresh(pc);
+ } else {
+ throw new JDOFatalUserException(msg.msg(
+ "EXC_PersistenceManagerClosed"));// NOI18N
+ }
+ }
+
+ /**
+ * @see javax.jdo.PersistenceManager#refreshAll(Object[] pcs)
+ */
+ public void refreshAll(Object[] pcs) {
+ if (isValid) {
+ pm.refreshAll(pcs);
+ } else {
+ throw new JDOFatalUserException(msg.msg(
+ "EXC_PersistenceManagerClosed"));// NOI18N
+ }
+ }
+
+ /**
+ * @see javax.jdo.PersistenceManager#refreshAll(Collection pcs)
+ */
+ public void refreshAll(Collection pcs) {
+ if (isValid) {
+ pm.refreshAll(pcs);
+ } else {
+ throw new JDOFatalUserException(msg.msg(
+ "EXC_PersistenceManagerClosed"));// NOI18N
+ }
+ }
+
+ /**
+ * @see javax.jdo.PersistenceManager#refreshAll()
+ */
+ public void refreshAll() {
+ if (isValid) {
+ pm.refreshAll();
+ } else {
+ throw new JDOFatalUserException(msg.msg(
+ "EXC_PersistenceManagerClosed"));// NOI18N
+ }
+ }
+
+ /**
+ * @see javax.jdo.PersistenceManager#newQuery()
+ */
+ public Query newQuery(){
+ if (isValid) {
+ return pm.newQuery();
+ } else {
+ throw new JDOFatalUserException(msg.msg(
+ "EXC_PersistenceManagerClosed"));// NOI18N
+ }
+ }
+ /**
+ * @see javax.jdo.PersistenceManager#newQuery(Object compiled)
+ */
+ public Query newQuery(Object compiled){
+ if (isValid) {
+ return pm.newQuery(compiled);
+ } else {
+ throw new JDOFatalUserException(msg.msg(
+ "EXC_PersistenceManagerClosed"));// NOI18N
+ }
+ }
+
+ /**
+ * @see javax.jdo.PersistenceManager#newQuery(Class cls)
+ */
+ public Query newQuery(Class cls){
+ if (isValid) {
+ return pm.newQuery(cls);
+ } else {
+ throw new JDOFatalUserException(msg.msg(
+ "EXC_PersistenceManagerClosed"));// NOI18N
+ }
+ }
+
+ /**
+ * @see javax.jdo.PersistenceManager#newQuery(Extent cln)
+ */
+ public Query newQuery(Extent cln){
+ if (isValid) {
+ return pm.newQuery(cln);
+ } else {
+ throw new JDOFatalUserException(msg.msg(
+ "EXC_PersistenceManagerClosed"));// NOI18N
+ }
+ }
+
+ /**
+ * @see javax.jdo.PersistenceManager#newQuery(Class cls,Collection cln)
+ */
+ public Query newQuery(Class cls,Collection cln){
+ if (isValid) {
+ return pm.newQuery(cls, cln);
+ } else {
+ throw new JDOFatalUserException(msg.msg(
+ "EXC_PersistenceManagerClosed"));// NOI18N
+ }
+ }
+
+ /**
+ * @see javax.jdo.PersistenceManager#newQuery(String language, Object query)
+ */
+ public Query newQuery (String language, Object query){
+ if (isValid) {
+ return pm.newQuery(language, query);
+ } else {
+ throw new JDOFatalUserException(msg.msg(
+ "EXC_PersistenceManagerClosed"));// NOI18N
+ }
+ }
+
+ /**
+ * @see javax.jdo.PersistenceManager#newQuery(Class cls, String filter)
+ */
+ public Query newQuery (Class cls, String filter){
+ if (isValid) {
+ return pm.newQuery(cls, filter);
+ } else {
+ throw new JDOFatalUserException(msg.msg(
+ "EXC_PersistenceManagerClosed"));// NOI18N
+ }
+ }
+
+ /**
+ * @see javax.jdo.PersistenceManager#newQuery(Class cls, Collection cln, String filter)
+ */
+ public Query newQuery (Class cls, Collection cln, String filter){
+ if (isValid) {
+ return pm.newQuery(cls, cln, filter);
+ } else {
+ throw new JDOFatalUserException(msg.msg(
+ "EXC_PersistenceManagerClosed"));// NOI18N
+ }
+ }
+
+ /**
+ * @see javax.jdo.PersistenceManager#newQuery(Extent cln, String filter)
+ */
+ public Query newQuery (Extent cln, String filter){
+ if (isValid) {
+ return pm.newQuery(cln, filter);
+ } else {
+ throw new JDOFatalUserException(msg.msg(
+ "EXC_PersistenceManagerClosed"));// NOI18N
+ }
+ }
+
+ /**
+ * @see javax.jdo.PersistenceManager#getExtent(Class persistenceCapableClass,
+ * boolean subclasses)
+ */
+ public Extent getExtent(Class persistenceCapableClass,boolean subclasses){
+ if (isValid) {
+ return pm.getExtent(persistenceCapableClass, subclasses);
+ } else {
+ throw new JDOFatalUserException(msg.msg(
+ "EXC_PersistenceManagerClosed"));// NOI18N
+ }
+ }
+
+ /**
+ * @see javax.jdo.PersistenceManager#getObjectById(Object oid, boolean validate)
+ */
+ public Object getObjectById(Object oid, boolean validate){
+ if (isValid) {
+ return pm.getObjectById(oid, validate);
+ } else {
+ throw new JDOFatalUserException(msg.msg(
+ "EXC_PersistenceManagerClosed"));// NOI18N
+ }
+ }
+
+ /**
+ * @see javax.jdo.PersistenceManager#getObjectId(Object pc)
+ */
+ public Object getObjectId(Object pc){
+ if (isValid) {
+ return pm.getObjectId(pc);
+ } else {
+ throw new JDOFatalUserException(msg.msg(
+ "EXC_PersistenceManagerClosed"));// NOI18N
+ }
+ }
+
+ /**
+ * @see javax.jdo.PersistenceManager#getTransactionalObjectId (Object pc)
+ */
+ public Object getTransactionalObjectId (Object pc) {
+ if (isValid) {
+ return pm.getTransactionalObjectId(pc);
+ } else {
+ throw new JDOFatalUserException(msg.msg(
+ "EXC_PersistenceManagerClosed"));// NOI18N
+ }
+ }
+
+ /**
+ * @see javax.jdo.PersistenceManager#newObjectIdInstance (Class pcClass, String str)
+ */
+ public Object newObjectIdInstance (Class pcClass, String str) {
+ if (isValid) {
+ return pm.newObjectIdInstance (pcClass, str);
+ } else {
+ throw new JDOFatalUserException(msg.msg(
+ "EXC_PersistenceManagerClosed"));// NOI18N
+ }
+ }
+
+ /**
+ * @see javax.jdo.PersistenceManager#makePersistent(Object pc)
+ */
+ public void makePersistent(Object pc){
+ if (isValid) {
+ pm.makePersistent(pc);
+ } else {
+ throw new JDOFatalUserException(msg.msg(
+ "EXC_PersistenceManagerClosed"));// NOI18N
+ }
+ }
+
+ /**
+ * @see javax.jdo.PersistenceManager#makePersistentAll(Object[] pc)
+ */
+ public void makePersistentAll(Object[] pcs){
+ if (isValid) {
+ pm.makePersistentAll(pcs);
+ } else {
+ throw new JDOFatalUserException(msg.msg(
+ "EXC_PersistenceManagerClosed"));// NOI18N
+ }
+ }
+
+ /**
+ * @see javax.jdo.PersistenceManager#makePersistentAll(Collection pcs)
+ */
+ public void makePersistentAll (Collection pcs){
+ if (isValid) {
+ pm.makePersistentAll(pcs);
+ } else {
+ throw new JDOFatalUserException(msg.msg(
+ "EXC_PersistenceManagerClosed"));// NOI18N
+ }
+ }
+
+ /**
+ * @see javax.jdo.PersistenceManager#deletePersistent(Object pc)
+ */
+ public void deletePersistent(Object pc){
+ if (isValid) {
+ pm.deletePersistent(pc);
+ } else {
+ throw new JDOFatalUserException(msg.msg(
+ "EXC_PersistenceManagerClosed"));// NOI18N
+ }
+ }
+
+ /**
+ * @see javax.jdo.PersistenceManager#deletePersistentAll(Object[] pc)
+ */
+ public void deletePersistentAll (Object[] pcs){
+ if (isValid) {
+ pm.deletePersistentAll(pcs);
+ } else {
+ throw new JDOFatalUserException(msg.msg(
+ "EXC_PersistenceManagerClosed"));// NOI18N
+ }
+ }
+
+ /**
+ * @see javax.jdo.PersistenceManager#deletePersistentAll(Collection pc)
+ */
+ public void deletePersistentAll (Collection pcs){
+ if (isValid) {
+ pm.deletePersistentAll(pcs);
+ } else {
+ throw new JDOFatalUserException(msg.msg(
+ "EXC_PersistenceManagerClosed"));// NOI18N
+ }
+ }
+
+ /**
+ * @see javax.jdo.PersistenceManager#makeTransient(Object pc)
+ */
+ public void makeTransient(Object pc){
+ if (isValid) {
+ pm.makeTransient(pc);
+ } else {
+ throw new JDOFatalUserException(msg.msg(
+ "EXC_PersistenceManagerClosed"));// NOI18N
+ }
+ }
+
+ /**
+ * @see javax.jdo.PersistenceManager#makeTransientAll(Object[] pc)
+ */
+ public void makeTransientAll(Object[] pcs){
+ if (isValid) {
+ pm.makeTransientAll(pcs);
+ } else {
+ throw new JDOFatalUserException(msg.msg(
+ "EXC_PersistenceManagerClosed"));// NOI18N
+ }
+ }
+
+ /**
+ * @see javax.jdo.PersistenceManager#makeTransientAll(Collection pcs)
+ */
+ public void makeTransientAll (Collection pcs){
+ if (isValid) {
+ pm.makeTransientAll(pcs);
+ } else {
+ throw new JDOFatalUserException(msg.msg(
+ "EXC_PersistenceManagerClosed"));// NOI18N
+ }
+ }
+
+ /**
+ * @see javax.jdo.PersistenceManager#makeTransactional(Object pc)
+ */
+ public void makeTransactional(Object pc){
+ if (isValid) {
+ pm.makeTransactional(pc);
+ } else {
+ throw new JDOFatalUserException(msg.msg(
+ "EXC_PersistenceManagerClosed"));// NOI18N
+ }
+ }
+
+ /**
+ * @see javax.jdo.PersistenceManager#makeTransactionalAll(Object[] pc)
+ */
+ public void makeTransactionalAll(Object[] pcs){
+ if (isValid) {
+ pm.makeTransactionalAll(pcs);
+ } else {
+ throw new JDOFatalUserException(msg.msg(
+ "EXC_PersistenceManagerClosed"));// NOI18N
+ }
+ }
+
+ /**
+ * @see javax.jdo.PersistenceManager#makeTransactionalAll(Collection pcs)
+ */
+ public void makeTransactionalAll (Collection pcs){
+ if (isValid) {
+ pm.makeTransactionalAll(pcs);
+ } else {
+ throw new JDOFatalUserException(msg.msg(
+ "EXC_PersistenceManagerClosed"));// NOI18N
+ }
+ }
+
+ /*
+ * @see javax.jdo.PersistenceManager#makeNontransactional(Object pc)
+ */
+ public void makeNontransactional(Object pc){
+ if (isValid) {
+ pm.makeNontransactional(pc);
+ } else {
+ throw new JDOFatalUserException(msg.msg(
+ "EXC_PersistenceManagerClosed"));// NOI18N
+ }
+ }
+
+ /**
+ * @see javax.jdo.PersistenceManager#makeNontransactionalAll(Object[] pc)
+ */
+ public void makeNontransactionalAll(Object[] pcs){
+ if (isValid) {
+ pm.makeNontransactionalAll(pcs);
+ } else {
+ throw new JDOFatalUserException(msg.msg(
+ "EXC_PersistenceManagerClosed"));// NOI18N
+ }
+ }
+
+ /**
+ * @see javax.jdo.PersistenceManager#makeNontransactionalAll(Collection pcs)
+ */
+ public void makeNontransactionalAll (Collection pcs){
+ if (isValid) {
+ pm.makeNontransactionalAll(pcs);
+ } else {
+ throw new JDOFatalUserException(msg.msg(
+ "EXC_PersistenceManagerClosed"));// NOI18N
+ }
+ }
+
+ /** Retrieve an instance from the store. This is only a hint to
+ * the PersistenceManager that the application intends to use the
+ * instance, and its field values should be retrieved.
+ * <P>The PersistenceManager might use policy information about the
+ * class to retrieve associated instances.
+ */
+ public void retrieve(Object pc) {
+ if (isValid) {
+ pm.retrieve(pc);
+ } else {
+ throw new JDOFatalUserException(msg.msg(
+ "EXC_PersistenceManagerClosed"));// NOI18N
+ }
+ }
+
+ /** Retrieve field values of instances from the store. This tells
+ * the <code>PersistenceManager</code> that the application intends to use the
+ * instances, and all field values must be retrieved.
+ * <P>The <code>PersistenceManager</code> might use policy information about the
+ * class to retrieve associated instances.
+ * @param pcs the instances
+ */
+ public void retrieveAll(Object[] pcs) {
+ if (isValid) {
+ pm.retrieveAll(pcs);
+ } else {
+ throw new JDOFatalUserException(msg.msg(
+ "EXC_PersistenceManagerClosed"));// NOI18N
+ }
+ }
+
+ /** Retrieve field values of instances from the store. This tells
+ * the <code>PersistenceManager</code> 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.
+ * <P>The <code>PersistenceManager</code> 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 (isValid) {
+ pm.retrieveAll(pcs, DFGOnly);
+ } else {
+ throw new JDOFatalUserException(msg.msg(
+ "EXC_PersistenceManagerClosed"));// NOI18N
+ }
+ }
+
+ /** Retrieve field values of instances from the store. This tells
+ * the <code>PersistenceManager</code> that the application intends to use the
+ * instances, and all field values must be retrieved.
+ * <P>The <code>PersistenceManager</code> might use policy information about the
+ * class to retrieve associated instances.
+ * @param pcs the instances
+ */
+ public void retrieveAll(Collection pcs) {
+ if (isValid) {
+ pm.retrieveAll(pcs);
+ } else {
+ throw new JDOFatalUserException(msg.msg(
+ "EXC_PersistenceManagerClosed"));// NOI18N
+ }
+ }
+
+ /** Retrieve field values of instances from the store. This tells
+ * the <code>PersistenceManager</code> 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.
+ * <P>The <code>PersistenceManager</code> 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 (isValid) {
+ pm.retrieveAll(pcs, DFGOnly);
+ } else {
+ throw new JDOFatalUserException(msg.msg(
+ "EXC_PersistenceManagerClosed"));// NOI18N
+ }
+ }
+
+
+ /**
+ * @see javax.jdo.PersistenceManager#getPersistenceManagerFactory()
+ */
+ public PersistenceManagerFactory getPersistenceManagerFactory(){
+ if (isValid) {
+ return pm.getPersistenceManagerFactory();
+ } else {
+ throw new JDOFatalUserException(msg.msg(
+ "EXC_PersistenceManagerClosed"));// NOI18N
+ }
+ }
+
+ /**
+ * @see javax.jdo.PersistenceManager#setUserObject(Object o)
+ */
+ public void setUserObject(Object o){
+ if (isValid) {
+ pm.setUserObject(o);
+ } else {
+ throw new JDOFatalUserException(msg.msg(
+ "EXC_PersistenceManagerClosed"));// NOI18N
+ }
+ }
+
+ /**
+ * @see javax.jdo.PersistenceManager#getUserObject()
+ */
+ public Object getUserObject(){
+ if (isValid) {
+ return pm.getUserObject();
+ } else {
+ throw new JDOFatalUserException(msg.msg(
+ "EXC_PersistenceManagerClosed"));// NOI18N
+ }
+ }
+
+ /**
+ * @see javax.jdo.PersistenceManager#getObjectIdClass(Class cls)
+ */
+ public Class getObjectIdClass(Class cls){
+ if (isValid) {
+ return pm.getObjectIdClass(cls);
+ } else {
+ throw new JDOFatalUserException(msg.msg(
+ "EXC_PersistenceManagerClosed"));// NOI18N
+ }
+ }
+
+ /**
+ * Returns PersistenceManagerInternal associated with this wrapper.
+ * This method should be accessed by the PersistenceManagerInternal
+ * only.
+ * @return PersistenceManagerInternal.
+ */
+ protected PersistenceManagerInternal getPersistenceManager() {
+ return (PersistenceManagerInternal)pm;
+ }
+
+ /**
+ * Returns a hash code value for this PersistenceManagerWrapper.
+ * @return a hash code value for this PersistenceManagerWrapper.
+ */
+ public int hashCode() {
+ return pm.hashCode();
+ }
+
+ /**
+ * Indicates whether some other object is "equal to" this one.
+ * @param obj the reference object with which to compare.
+ * @return <code>true</code> if this object is the same as the obj
+ * argument; <code>false</code> otherwise.
+ */
+ public boolean equals(Object obj) {
+ if (obj instanceof PersistenceManagerWrapper) {
+ return (((PersistenceManagerWrapper)obj).pm == this.pm);
+
+ } else if (obj instanceof PersistenceManagerImpl) {
+ return (((PersistenceManagerImpl)obj) == this.pm);
+ }
+ return false;
+ }
+}
Added: incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/pm/TransactionImpl.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/pm/TransactionImpl.java?view=auto&rev=158176
==============================================================================
--- incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/pm/TransactionImpl.java (added)
+++ incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/pm/TransactionImpl.java Fri Mar 18 17:02:29 2005
@@ -0,0 +1,1160 @@
+/*
+ * 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.
+ */
+
+/*
+ * TransactionImpl.java
+ *
+ * Create on December 1, 2000
+ */
+
+package org.apache.jdo.impl.pm;
+
+import java.util.*;
+import javax.transaction.*;
+
+import javax.jdo.*;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.apache.jdo.ejb.EJBImplHelper;
+import org.apache.jdo.store.Connector;
+import org.apache.jdo.store.StoreManager;
+import org.apache.jdo.util.I18NHelper;
+
+/**
+ *
+ * The Transaction interface allows operations to be performed against
+ * the transaction in the target Transaction object. A Transaction
+ * object is created corresponding to each PersistentManagerImpl creation.
+ * The Transaction object can be used for synchronization registration,
+ * transaction completion and status query operations.
+ *
+ * This implementation is StoreManager independent.
+ *
+ * @author Marina Vatkina
+ */
+class TransactionImpl implements javax.jdo.Transaction {
+
+ /**
+ * Transaction status (from javax.transaction.Status).
+ */
+ private int status;
+
+ /**
+ * The commit process has already begun (even though the status is still
+ * STATUS_ACTIVE). This is the first thing set during commit or rollback.
+ */
+ private boolean startedCommit;
+
+ /**
+ * Registered Synchronization object.
+ */
+ private Object synchronization;
+
+ /**
+ * Synchronisation object associated with this transaction instance
+ */
+ private Object txSync = null;
+
+ /**
+ * PersistenceManagerFactory associated with this transaction
+ */
+ private PersistenceManagerFactoryImpl pmFactory = null;
+
+ /**
+ * PersistenceManager associated with this transaction (1-1)
+ */
+ private PersistenceManagerImpl persistenceManager = null;
+
+ /**
+ * Connector associated with this transaction
+ */
+ private Connector connector = null;
+
+ /**
+ * javax.transaction.Transaction instance associated with the current
+ * thread or null if there is none.
+ */
+ private javax.transaction.Transaction jta = null;
+
+ /**
+ * Flag that indicates how to handle objects after commit.
+ * If true, at commit instances retain their values and the instances
+ */
+ private boolean retainValues = true;
+
+ /**
+ * Flag that indicates how to handle objects after rollback.
+ * If true, at rollback instances have their values restored.
+ */
+ private boolean restoreValues = true;
+
+ /**
+ * Flag that indicates type of the transaction.
+ * Optimistic transactions do not hold data store locks until commit time.
+ */
+ private boolean optimistic = true;
+
+ /**
+ * Flag that indicates if queries and navigation are allowed
+ * without an active transaction
+ */
+ private boolean nontransactionalRead = true;
+
+ /**
+ * Flag that indicates if write access is allowed
+ * without an active transaction
+ */
+ private boolean nontransactionalWrite = true;
+
+ /** values for the datasource user and user password to access
+ * security connections
+ */
+ private String username = null;
+ private String password = null;
+
+ /**
+ * Possible values of txType
+ */
+ protected static final int NON_MGD = 0;
+ protected static final int CMT = 1;
+ protected static final int BMT_UT = 2;
+ protected static final int BMT_JDO = 3;
+
+ /**
+ * Flag to indicate usage mode (non-managed versus managed, and so on).
+ */
+ private int txType = -1;
+
+ /**
+ * Logger instance
+ */
+ private static final Log logger = LogFactory.getFactory().getInstance(
+ "org.apache.jdo.impl.pm"); // NOI18N
+
+ /**
+ * I18N message handler
+ */
+ private final static I18NHelper msg =
+ I18NHelper.getInstance("org.apache.jdo.impl.pm.Bundle"); // NOI18N
+
+ /**
+ * Constructors new instance of TransactionImpl for the corresponding
+ * PersistenceManagerImpl. Username and password are provided for future
+ * validation and Connector request.
+ *
+ * @param pm calling instance of PersistenceManagerImpl
+ * @param pmf PersistenceManagerFactoryImpl associated with the instance of
+ * PersistenceManagerImpl
+ * @param username user name for Connector request
+ * @param password user password for Connector request
+ */
+ TransactionImpl(PersistenceManagerImpl pm, PersistenceManagerFactoryImpl pmf,
+ String username, String password) {
+
+ this.status = Status.STATUS_NO_TRANSACTION;
+ this.startedCommit = false;
+ this.persistenceManager = pm;
+
+ pmFactory = pmf;
+ optimistic = pmFactory.getOptimistic();
+ retainValues = pmFactory.getRetainValues();
+ restoreValues = pmFactory.getRestoreValues();
+ nontransactionalRead = pmFactory.getNontransactionalRead();
+ nontransactionalWrite = pmFactory.getNontransactionalWrite();
+
+ this.username = username;
+ this.password = password;
+
+ }
+
+ //
+ // ----- Methods from javax.jdo.Transaction interface ------
+ //
+
+ /**
+ * Returns PersistenceManager associated with this transaction
+ * @see javax.jdo.Transaction#getPersistenceManager()
+ */
+ public javax.jdo.PersistenceManager getPersistenceManager() {
+ persistenceManager.assertIsOpen();
+ return (javax.jdo.PersistenceManager) persistenceManager.getCurrentWrapper();
+ }
+
+ /**
+ * @see javax.jdo.Transaction#isActive()
+ */
+ public boolean isActive() {
+ persistenceManager.assertIsOpen();
+ return !isTerminated();
+ }
+
+ /**
+ * @see javax.jdo.Transaction#setRetainValues(boolean flag)
+ */
+ public void setRetainValues(boolean flag) {
+ persistenceManager.assertIsOpen();
+
+ // Cannot change flag value when transaction commit is in progress.
+ if (startedCommit)
+ throw new JDOUserException(msg.msg(
+ "EXC_CannotSetFlag")); // NOI18N
+
+ this.retainValues = flag;
+ }
+
+ /**
+ * @see javax.jdo.Transaction#getRetainValues()
+ */
+ public boolean getRetainValues() {
+ persistenceManager.assertIsOpen();
+ return retainValues;
+ }
+
+ /**
+ * @see javax.jdo.Transaction#setRestoreValues(boolean flag)
+ */
+ public void setRestoreValues(boolean flag) {
+ persistenceManager.assertIsOpen();
+ // Cannot change flag if transaction is active.
+ if (isActive()) {
+ throw new JDOUserException(msg.msg(
+ "EXC_CannotSetFlagIfActive")); // NOI18N
+ }
+ this.restoreValues = flag;
+ }
+
+ /**
+ * @see javax.jdo.Transaction#getRestoreValues()
+ */
+ public boolean getRestoreValues() {
+ persistenceManager.assertIsOpen();
+ return restoreValues;
+ }
+
+ /**
+ * @see javax.jdo.Transaction#setNontransactionalRead(boolean flag)
+ */
+ public synchronized void setNontransactionalRead (boolean flag) {
+ persistenceManager.assertIsOpen();
+
+ // Cannot change flag value when transaction commit is in progress.
+ if (startedCommit)
+ throw new JDOUserException(msg.msg(
+ "EXC_CannotSetFlag")); // NOI18N
+
+ this.nontransactionalRead = flag;
+
+ }
+
+ /**
+ * @see javax.jdo.Transaction#getNontransactionalRead()
+ */
+ public boolean getNontransactionalRead() {
+ persistenceManager.assertIsOpen();
+ return nontransactionalRead;
+ }
+
+ /**
+ * @see javax.jdo.Transaction#setNontransactionalWrite(boolean flag)
+ */
+ public synchronized void setNontransactionalWrite (boolean flag) {
+ persistenceManager.assertIsOpen();
+
+ // Cannot change flag value when transaction commit is in progress.
+ if (startedCommit)
+ throw new JDOUserException(msg.msg(
+ "EXC_CannotSetFlag")); // NOI18N
+
+ this.nontransactionalWrite = flag;
+ }
+
+ /**
+ * @see javax.jdo.Transaction#getNontransactionalWrite()
+ */
+ public boolean getNontransactionalWrite() {
+ persistenceManager.assertIsOpen();
+ return nontransactionalWrite;
+ }
+
+ /**
+ * @see javax.jdo.Transaction#setOptimistic(boolean flag)
+ */
+ public synchronized void setOptimistic(boolean flag) {
+ persistenceManager.assertIsOpen();
+
+ if (isTerminated()) {
+ this.optimistic = flag;
+ } else {
+ // Cannot change flag value inside an active transaction.
+ throw new JDOUserException(msg.msg(
+ "EXC_CannotChangeType")); // NOI18N
+ }
+
+ // Notify PM about Tx type change
+ persistenceManager.notifyOptimistic(flag);
+ }
+
+ /**
+ * @see javax.jdo.Transaction#getOptimistic()
+ */
+ public boolean getOptimistic() {
+ persistenceManager.assertIsOpen();
+ return optimistic;
+ }
+
+ /**
+ * @see javax.jdo.Transaction#setSynchronization(Synchronization sync)
+ */
+ public void setSynchronization(Synchronization sync) {
+ persistenceManager.assertIsOpen();
+ if (sync == synchronization) {
+ return; // the same Synchronization.
+
+ } else if (sync != null && synchronization != null) {
+ throw new JDOUserException(msg.msg(
+ "EXC_SynchronizationNotNull")); // NOI18N
+ }
+
+ this.registerSynchronization(sync);
+ }
+
+ /**
+ * @see javax.jdo.Transaction#getRetainValues()
+ */
+ public Synchronization getSynchronization() {
+ persistenceManager.assertIsOpen();
+ return (Synchronization)synchronization;
+ }
+
+ public void assertReadAllowed() {
+ if ((!isActive()) && (!getNontransactionalRead())) {
+ throw new JDOUserException(msg.msg(
+ "EXC_NontransactionalRead"));// NOI18N
+ }
+ }
+
+ /**
+ * Begin a transaction.
+ * @see javax.jdo.Transaction#begin()
+ */
+ public void begin() {
+ // Check and set status...
+ beginInternal();
+
+ // BMT with JDO Transaction
+ if (EJBImplHelper.isManaged()) {
+ txType = BMT_JDO;
+ try {
+ EJBImplHelper.getUserTransaction().begin();
+ jta = EJBImplHelper.getTransaction();
+ if (txSync == null)
+ txSync = new TransactionSynchronization(this);
+
+ jta.registerSynchronization((Synchronization)txSync);
+ pmFactory.registerPersistenceManager(persistenceManager, jta);
+
+ } catch (JDOException e) {
+ throw e; // re-throw it.
+ } catch (Exception e) {
+ throw new JDOFatalInternalException(
+ "EXC_ErrorRegister", e); // NOI18N
+ }
+ } else {
+ // Mark as non-managed transaction.
+ txType = NON_MGD;
+ }
+
+ }
+
+ /**
+ * Commit the transaction represented by this Transaction object
+ * @see javax.jdo.Transaction#commit()
+ */
+ public void commit() {
+ persistenceManager.assertIsOpen();
+
+ if (txType == CMT || txType == BMT_UT) {
+ // Error - should not be called
+ throw new JDOUserException(msg.msg(
+ "EXC_WrongMgdOperation", "commit")); //NOI18N
+ } else if (txType == BMT_JDO) {
+ // Send request to the container:
+ try {
+ EJBImplHelper.getUserTransaction().commit();
+ return;
+ } catch (Exception e) {
+ throw new JDOException("", e); // NOI18N
+ }
+ }
+
+ // Proceede with non-managed environment call.
+ synchronized (this) {
+ //
+ // Disallow parallel transaction completion calls:
+ //
+ if (startedCommit) {
+ throw new JDOUserException(msg.msg(
+ "EXC_TransactionCommitting")); // NOI18N
+ }
+
+ // This flag prevents user from making any changes to the transaction object.
+ this.startedCommit = true;
+ }
+
+ if (debugging())
+ this.traceCall("commit"); // NOI18N
+
+ try {
+ this.prepareFlush(true); // do actual beforeComplition.
+ this.commitPrepare(); // check internal status.
+ this.commitComplete(); // commitConnector and set status to success.
+
+ } catch (Throwable e) {
+ try {
+ this.internalRollback();
+ } catch (Exception re) {
+ // Do not rethrow the rollback exception - just log it.
+ if (debugging())
+ logger.debug("Exception during rollback after failed commit: " + re);
+ }
+
+ if (e instanceof JDOException) {
+ throw (JDOException)e;
+ }
+ throw new JDOException("", e); // NOI18N
+ } finally {
+ this.internalAfterCompletion(); // do afterCompletion and cleanup.
+ }
+ }
+
+ /**
+ * Rollback the transaction represented by this transaction object.
+ * @see javax.jdo.Transaction#rollback()
+ */
+ public void rollback() {
+ persistenceManager.assertIsOpen();
+ if (txType == CMT || txType == BMT_UT) {
+ // Error - should not be called
+ throw new JDOUserException(msg.msg(
+ "EXC_WrongMgdOperation", "rollback")); //NOI18N
+ }
+
+ if (debugging())
+ this.traceCall("rollback"); // NOI18N
+
+ synchronized (this) {
+ //
+ // Disallow parallel transaction completion calls:
+ //
+ if (startedCommit) {
+ throw new JDOUserException(msg.msg(
+ "EXC_TransactionCommitting")); // NOI18N
+
+ } else if ((this.status != Status.STATUS_ACTIVE) &&
+ (this.status != Status.STATUS_MARKED_ROLLBACK)) {
+
+ throw new JDOUserException(msg.msg(
+ "EXC_TransactionNotActive")); // NOI18N
+ }
+
+ // This flag prevents user from making any changes to the transaction object.
+ this.startedCommit = true;
+ }
+
+ try {
+ this.internalRollback();
+
+ if (txType == BMT_JDO) {
+ // Send request to the container:
+ EJBImplHelper.getUserTransaction().rollback();
+ }
+ } catch (JDOException e) {
+ throw e;
+
+ } catch (Exception e) {
+ throw new JDOException("", e); // NOI18N
+
+ } finally {
+ if (txType == NON_MGD) {
+ // afterCompletion and cleanup in case of the managed env. had been
+ // done already.
+ this.internalAfterCompletion();
+ }
+ }
+ }
+
+ //
+ // ----- Other public methods ------
+ //
+
+ /**
+ * Modify the transaction object such that the only possible outcome of
+ * the transaction is to roll back.
+ */
+ public void setRollbackOnly() {
+ if (debugging())
+ this.traceCall("setRollbackOnly"); // NOI18N
+
+ if ((this.status == Status.STATUS_ROLLING_BACK)
+ || (this.status == Status.STATUS_ROLLEDBACK)
+ || (this.status == Status.STATUS_MARKED_ROLLBACK)) {
+ //
+ // Already rolled back, rollback in progress or already marked.
+ //
+ return;
+ }
+
+ if (txType == NON_MGD) {
+ this.setStatus(Status.STATUS_MARKED_ROLLBACK);
+ } else {
+ try {
+ jta.setRollbackOnly();
+ } catch (Exception e) {
+ throw new JDOException("", e); // NOI18N
+ }
+ }
+
+ }
+
+ /**
+ * Obtain the status of this transaction object.
+ *
+ * @return The transaction status.
+ */
+ public int getStatus() {
+ synchronized (this) {
+ return this.status;
+ }
+ }
+
+ /**
+ * Translates a javax.transaction.Status value into a string.
+ *
+ * @param status Status object to translate.
+ * @return Printable String for a Status object.
+ */
+ public static String statusString(int status) {
+ switch (status) {
+ case Status.STATUS_ACTIVE: return "STATUS_ACTIVE"; // NOI18N
+ case Status.STATUS_MARKED_ROLLBACK: return "STATUS_MARKED_ROLLBACK"; // NOI18N
+ case Status.STATUS_PREPARED: return "STATUS_PREPARED"; // NOI18N
+ case Status.STATUS_COMMITTED: return "STATUS_COMMITTED"; // NOI18N
+ case Status.STATUS_ROLLEDBACK: return "STATUS_ROLLEDBACK"; // NOI18N
+ case Status.STATUS_UNKNOWN: return "STATUS_UNKNOWN"; // NOI18N
+ case Status.STATUS_NO_TRANSACTION: return "STATUS_NO_TRANSACTION"; // NOI18N
+ case Status.STATUS_PREPARING: return "STATUS_PREPARING"; // NOI18N
+ case Status.STATUS_COMMITTING: return "STATUS_COMMITTING"; // NOI18N
+ case Status.STATUS_ROLLING_BACK: return "STATUS_ROLLING_BACK"; // NOI18N
+ default: break;
+ }
+ return "STATUS_Invalid[" + status + "]"; // NOI18N
+ }
+
+ /**
+ * Returns a string representation of this transaction object.
+ *
+ * @return String describing contents of this Transaction object.
+ */
+ public String toString() {
+ StringBuffer s = new StringBuffer();
+
+ s.append(" Transaction: \n status = " + this.statusString(this.status)+ "\n"); // NOI18N
+ if (this.startedCommit)
+ s.append(" startedCommit = true\n"); // NOI18N
+
+ if (synchronization != null)
+ s.append(" sync = " + synchronization.getClass().getName() + "\n"); // NOI18N
+
+ return s.toString();
+ }
+
+ //
+ // ----- protected methods ------
+ //
+
+ /**
+ * Returns current transaction type
+ * @return current transaction type as int.
+ */
+ protected int getTransactionType() {
+ return txType;
+ }
+
+ /** Verify that username and password are equal to ones stored before
+ *
+ * @param username as String
+ * @param password as String
+ * @return true if they are equal
+ */
+ protected boolean verify(String username, String password) {
+ if ((this.username != null && !this.username.equals(username)) ||
+ (this.username == null && username != null) ||
+ (this.password != null && !this.password.equals(password)) ||
+ (this.password == null && password != null)) {
+ return false;
+ }
+ return true;
+ }
+
+ /** Returns true if commit has started
+ * @return true if commit has started
+ */
+ protected boolean startedCommit() {
+ return startedCommit;
+ }
+
+ /**
+ * Flush changes to the datastore. Performed in an active datastore
+ * transaction only.
+ */
+ protected void internalFlush() {
+ if (this.status != Status.STATUS_ACTIVE) {
+ throw new JDOUserException(msg.msg(
+ "EXC_TransactionNotActive")); // NOI18N
+ }
+
+ this.prepareFlush(false); // prepare the flush.
+ }
+
+ /**
+ * Begin a transaction in a managed environment. Called by
+ * PersistenceManagerFactoryImpl when JTA Transaction associated with
+ * the current thread is active.
+ *
+ * @param t JTA Transaction associated with the current thread
+ */
+ protected void begin(javax.transaction.Transaction t) {
+
+ beginInternal();
+ try {
+ jta = t;
+ if (txSync == null)
+ txSync = new TransactionSynchronization(this);
+
+ jta.registerSynchronization((Synchronization)txSync);
+ } catch (Exception e) {
+ throw new JDOFatalInternalException(msg.msg(
+ "EXC_ErrorRegister")); //NOI18N
+ }
+
+ // Set transaction type.
+ txType = CMT;
+ }
+
+ /**
+ * Called in the managed environment only for transaction completion
+ * by TransactionSynchronization#beforeCompletion().
+ */
+ protected void beforeCompletion() {
+
+ if (txType == NON_MGD) {
+ // Error - should not be called
+ throw new JDOUserException(msg.msg(
+ "EXC_WrongNonMgdOperation", "beforeCompletion")); //NOI18N
+ }
+
+ Object o = null;
+
+ // This flag prevents user from making any changes to the transaction object.
+ this.startedCommit = true;
+
+ try {
+ o = EJBImplHelper.enlistBeforeCompletion(
+ new Object[] {this, persistenceManager, jta});
+ this.prepareFlush(true); // do actual beforeComplition.
+ this.commitPrepare(); // check internal status.
+
+ // do not do commitConnector() in the managed environment:
+ this.setStatus(Status.STATUS_COMMITTED);
+
+ } finally {
+ EJBImplHelper.delistBeforeCompletion(o);
+ }
+ }
+
+ /**
+ * Called in the managed environment only for transaction completion
+ * by TransactionSynchronization#afterCompletion(int st).
+ */
+ protected void afterCompletion(int st) {
+ if (txType == NON_MGD) {
+ // Error - should not be called
+ throw new JDOUserException(msg.msg(
+ "EXC_WrongNonMgdOperation", "afterCompletion")); //NOI18N
+ }
+ st = EJBImplHelper.translateStatus(st); // translate Status
+
+ if (debugging()) {
+ this.traceCall("afterCompletion", st); // NOI18N
+ }
+
+ if (st == Status.STATUS_ROLLEDBACK) {
+ this.internalRollback();
+ }
+
+ if (st != this.status) {
+ // Status mismatch - should not happen.
+ throw new JDOUserException(msg.msg(
+ "EXC_InvalidStatus", // NOI18N
+ "afterCompletion", this.statusString(this.status), // NOI18N
+ this.statusString(st)));
+ }
+
+ this.internalAfterCompletion();
+
+ }
+
+ //
+ // ----- private methods ------
+ //
+
+ /**
+ * Status change and validation. Called by begin methods.
+ */
+ private void beginInternal() {
+ persistenceManager.assertIsOpen();
+
+ if (debugging())
+ this.traceCall("begin"); // NOI18N
+
+ if (this.isActive()) {
+ throw new JDOUserException(msg.msg(
+ "EXC_ErrorBegin")); // NOI18N
+
+ }
+ this.setStatus(Status.STATUS_ACTIVE);
+
+ connector = this.getConnector();
+ connector.begin(optimistic);
+ }
+
+ /**
+ * Lower-level before-commit method - phase 1.
+ *
+ * This is called to flush changes to the store.
+ * State transition:
+ * STATUS_ACTIVE starting state
+ * internalBeforeCompletion() called while still active
+ * STATUS_PREPARING no longer active, about to "really" commit
+ *
+ * @param _commit true if called during the commit processing
+ * For exceptions see commit() method.
+ */
+ private void prepareFlush(boolean _commit) {
+ boolean rollbackOnly = false; //marked for rollback
+
+ if (debugging())
+ this.traceCall("prepareFlush"); // NOI18N
+ //
+ // Prepare connection
+ //
+ connector = this.getConnector();
+
+ //
+ // Validate transaction state before we commit
+ //
+
+ if ((this.status == Status.STATUS_ROLLING_BACK)
+ || (this.status == Status.STATUS_ROLLEDBACK)) {
+ throw new JDOUserException(msg.msg(
+ "EXC_TransactionRolledback")); // NOI18N
+ }
+
+ if (connector.getRollbackOnly() ||
+ this.status == Status.STATUS_MARKED_ROLLBACK) {
+ rollbackOnly = true;
+
+ } else if (this.status != Status.STATUS_ACTIVE) {
+ throw new JDOUserException(msg.msg(
+ "EXC_TransactionNotActive")); // NOI18N
+ }
+
+ //
+ // User notifications done outside of lock - check for concurrent
+ // rollback or setRollbackOnly during notification.
+ //
+ if (!rollbackOnly) {
+ this.flushInstances(_commit);
+
+ if (this.status == Status.STATUS_ACTIVE) { // All ok
+ if (this.startedCommit) { // inside commit - change status.
+ this.setStatus(Status.STATUS_PREPARING);
+ }
+
+ } else if (this.status == Status.STATUS_MARKED_ROLLBACK) {
+ // This could happen only if this.setRollbackOnly() was called
+ // during flushInstances() without throwing an
+ // exception.
+ rollbackOnly = true;
+
+ } else { // concurrently rolled back - should not happen.
+ throw new JDOUserException(msg.msg(
+ "EXC_TransactionRolledback")); // NOI18N
+ }
+ }
+ if (rollbackOnly) {
+ // Do not rollback here, but throw the exception and the rollback
+ // will happen in the 'catch' block. Usually happens if the
+ // connector was set rollback-only before the commit.
+ this.setRollbackOnly();
+
+ throw new JDOUserException(msg.msg(
+ "EXC_MarkedRolledback")); // NOI18N
+
+ }
+ }
+
+ /**
+ * Lower-level prepare-commit method - phase 2.
+ *
+ * This is called when flush is finished but before connectorCommit.
+ * Will allow to support 2-phase commit.
+ * State transition:
+ * STATUS_PREPARING starting state
+ * STATUS_PREPARED
+ *
+ * For exceptions see commit() method.
+ */
+ private void commitPrepare() {
+ if (debugging())
+ this.traceCall("commitPrepare"); // NOI18N
+ //
+ // Once we've reached the Status.STATUS_PREPARING state we do not need
+ // to check for concurrent state changes. All user-level methods
+ // (rollback, setRollbackOnly, register, enlist, etc) are no longer
+ // allowed.
+ //
+
+ //
+ // Validate initial state
+ //
+ if (this.status != Status.STATUS_PREPARING) {
+ throw new JDOUserException(msg.msg(
+ "EXC_WrongStateCommit")); // NOI18N
+ }
+
+ this.setStatus(Status.STATUS_PREPARED);
+ }
+
+ /**
+ * Lower-level commit method - phase 3. Called only in a non-
+ * managed environment.
+ *
+ * State transition:
+ * STATUS_PREPARED starting state
+ * STATUS_COMMITTING starting to do final phase
+ * commitConnector() commit the flush.
+ * STATUS_COMMITTED
+ *
+ */
+ private void commitComplete() {
+ if (debugging())
+ this.traceCall("commitComplete"); // NOI18N
+
+ //
+ // Validate initial state
+ //
+ if (this.status == Status.STATUS_ROLLING_BACK) {
+ this.setStatus(Status.STATUS_ROLLING_BACK);
+
+ this.setStatus(Status.STATUS_ROLLEDBACK);
+
+ } else if (this.status == Status.STATUS_PREPARED) {
+ this.setStatus(Status.STATUS_COMMITTING);
+ this.commitConnector();
+ this.setStatus(Status.STATUS_COMMITTED);
+
+ } else {
+ throw new JDOUserException(msg.msg(
+ "EXC_WrongStateCommit")); // NOI18N
+ }
+ }
+
+ /**
+ * Lower-level internal rollback method. This is to avoid concurrent rollbacks.
+ *
+ */
+ private void internalRollback() {
+ if (debugging())
+ this.traceCall("internalRollback"); // NOI18N
+
+ this.setStatus(Status.STATUS_ROLLING_BACK);
+ try {
+ if (txType == NON_MGD) {
+ this.rollbackConnector();
+ }
+ } catch (JDOException ex) {
+ throw ex;
+
+ } catch (Exception ex) {
+ throw new JDOException("", ex);
+
+ } finally {
+ this.setStatus(Status.STATUS_ROLLEDBACK);
+ }
+ }
+
+ /**
+ *
+ * Force rollback. This is called when something goes wrong during
+ * a late state check (i.e. some failure occurred during the prepare
+ * stage). Unless we're not already rolling back (or rolled back) this
+ * will blindly change the state of the transaction and complete the
+ * latter stage of rollback.
+ *
+ * @return the final status of the transaction.
+ *
+ * See internalRollback() for exceptions
+ */
+ private int forceRollback() {
+ if (debugging())
+ this.traceCall("forceRollback"); // NOI18N
+
+ if ((this.status == Status.STATUS_ROLLING_BACK) // Already
+ || (this.status == Status.STATUS_ROLLEDBACK) // Done
+ || (this.status == Status.STATUS_COMMITTED) // Too late
+ || (this.status == Status.STATUS_NO_TRANSACTION) // Never was
+ ) {
+ return this.status;
+ }
+ try {
+ this.internalRollback();
+ } finally {
+ this.internalAfterCompletion();
+ }
+
+ return this.status;
+ }
+
+ /**
+ * Register a Synchronization object for this transaction object.
+ * The transction manager invokes the beforeCompletion method prior to
+ * starting the transaction commit process. After the transaction is
+ * completed (or aborted), the transaction manager invokes the
+ * afterCompletion method.
+ *
+ * @param sync The Synchronization object for the transaction.
+ */
+ private void registerSynchronization(Synchronization sync) {
+ if (debugging())
+ this.traceCall("registerSynchronization"); // NOI18N
+ synchronized (this) {
+ //
+ // Disallow registration of new synchronization objects during
+ // beforeCompletion or afterCompletion processing. Synchronizations
+ // are themselves involved in the process.
+ //
+ if (this.startedCommit) {
+ throw new JDOUserException(msg.msg(
+ "EXC_TransactionCommitting")); // NOI18N
+ }
+
+ synchronization = sync;
+
+ if (debugging()) {
+ this.traceCall("registerSynchronization"); // NOI18N
+ }
+ }
+ }
+
+
+ /**
+ * Confirm that transaction is terminated.
+ *
+ * @return True if transaction is completed or not started.
+ */
+ private boolean isTerminated() {
+ synchronized (this) {
+ return ( (this.status == Status.STATUS_COMMITTED)
+ || (this.status == Status.STATUS_ROLLEDBACK)
+ || (this.status == Status.STATUS_NO_TRANSACTION));
+ }
+ }
+
+ /**
+ * Flush dirty persistent instances to the datastore.
+ * If called during the commit processing, notifies registered
+ * Synchronization interfaces with beforeCompletion().
+ */
+ private void flushInstances(boolean commit) {
+ if (commit) {
+ this.getConnector().beforeCompletion();
+ if (synchronization != null) {
+ ((Synchronization)synchronization).beforeCompletion();
+ }
+ }
+
+ persistenceManager.flushInstances();
+ }
+
+ /**
+ * Notify Connector, PersistenceManager, and registered Synchronization
+ * instances about afterCompletion().
+ * All status changes occured before executing this method.
+ */
+ private void internalAfterCompletion() {
+ //
+ // This will execute w/o an active transaction context
+ //
+ persistenceManager.afterCompletion(status);
+
+ try {
+ if (synchronization != null)
+ ((Synchronization)synchronization).afterCompletion(status);
+ } catch (Exception ex) {
+ //
+ // Exceptions ignored
+ //
+ }
+
+ this.finish();
+ }
+
+ /**
+ * Set status under lock (may be a nested lock which is ok)
+ */
+ private void setStatus(int status) {
+ if (debugging()) {
+ logger.debug(
+ "Tran[" + this.toString() + "].setStatus: " + // NOI18N
+ this.statusString(this.status) + " => " + // NOI18N
+ this.statusString(status));
+ }
+
+ synchronized(this) {
+ this.status = status;
+ persistenceManager.notifyStatusChange(!isTerminated());
+ }
+ }
+
+ /**
+ * Finish this transaction
+ */
+ private void finish() {
+ if (debugging())
+ this.traceCall("finish"); // NOI18N
+
+ //
+ // Do not clear:
+ //
+ // .status -- users can still check status
+ //
+ this.startedCommit = false;
+
+ if (txType == CMT || txType == BMT_UT) {
+ persistenceManager.forceClose();
+ } else if (txType == BMT_JDO) {
+ persistenceManager.deregisterJTA();
+ }
+
+ jta = null;
+ txType = NON_MGD; // Restore the flag
+ }
+
+ //
+ // ----- Connector utilities -----
+ //
+
+ /**
+ * Get a connector
+ */
+ private Connector getConnector() {
+ StoreManager srm = persistenceManager.getStoreManager();
+
+ if (username != null) {
+ return srm.getConnector(username, password);
+ }
+ return srm.getConnector();
+ }
+
+ /**
+ * Close a connector does flush of the changes and close
+ */
+ private void flushConnector() {
+ connector = this.getConnector();
+ connector.flush();
+ }
+
+ /**
+ * Rollback a connector does rollback and close
+ */
+ private void rollbackConnector() {
+ connector = this.getConnector();
+ connector.rollback();
+ }
+
+ /**
+ * Commit a connector does flush if necessary, commit and close
+ */
+ private void commitConnector() {
+ connector = this.getConnector();
+ connector.commit();
+ }
+
+ //
+ // ----- Debugging utilities -----
+ //
+
+ /**
+ * Verifies if debugging is enabled.
+ * @return true if debugging is enabled.
+ */
+ private boolean debugging() {
+ return logger.isDebugEnabled();
+ }
+
+
+ /**
+ * Trace method call.
+ */
+ private void traceCall(String call) {
+ logger.debug(
+ "Tran[" + this.toString() + "]." + call + // NOI18N
+ ": status = " + this.statusString(this.status) + // NOI18N
+ ", txType: " + txTypeString()); // NOI18N
+ }
+
+ /**
+ * Trace method call with a provided status.
+ */
+ private void traceCall(String call, int st) {
+ logger.debug(
+ "Tran[" + this.toString() + "]." + call + // NOI18N
+ ": status = " + this.statusString(st) + // NOI18N
+ ", txType: " + txTypeString()); // NOI18N
+ }
+
+ /**
+ * Translates a txType value into a string.
+ *
+ * @return Printable String for a txType value
+ */
+ private String txTypeString() {
+ switch (txType) {
+ case NON_MGD: return "NON_MGD"; // NOI18N
+ case CMT: return "CMT"; // NOI18N
+ case BMT_UT: return "BMT_UT"; // NOI18N
+ case BMT_JDO: return "BMT_JDO"; // NOI18N
+ default: break;
+ }
+ return "UNKNOWN"; // NOI18N
+ }
+}
+
+
+
Added: incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/pm/TransactionSynchronization.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/pm/TransactionSynchronization.java?view=auto&rev=158176
==============================================================================
--- incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/pm/TransactionSynchronization.java (added)
+++ incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/pm/TransactionSynchronization.java Fri Mar 18 17:02:29 2005
@@ -0,0 +1,60 @@
+/*
+ * 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.
+ */
+
+/*
+ * TransactionSynchronization.java
+ *
+ * Create on August 1, 20001
+ */
+
+package org.apache.jdo.impl.pm;
+
+import javax.transaction.*;
+
+
+/**
+ * This is a Synchronization instance associated with the corresponding instance
+ * of the TransactionImpl. Is used for synchronization callbacks in a managed
+ * environment. This is a separate object to avoid a requirement for a non-managed
+ * application have JTA classes in its classpath.
+ *
+ * @author Marina Vatkina
+ */
+class TransactionSynchronization implements Synchronization {
+ /** Reference to TransactionImpl instance associated
+ * with this instance of TransactionSynchronization
+ */
+ private TransactionImpl tx = null;
+
+ TransactionSynchronization(TransactionImpl newtx) {
+ tx = newtx;
+ }
+
+ /**
+ * @see javax.transaction.Synchronization#beforeCompletion()
+ */
+ public void beforeCompletion() {
+ tx.beforeCompletion();
+ }
+
+ /**
+ * @see javax.transaction.Synchronization#afterCompletion(int status)
+ */
+ public void afterCompletion(int status) {
+ tx.afterCompletion(status);
+ }
+
+}
Added: incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/pm/package.html
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/pm/package.html?view=auto&rev=158176
==============================================================================
--- incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/pm/package.html (added)
+++ incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/pm/package.html Fri Mar 18 17:02:29 2005
@@ -0,0 +1,28 @@
+<!--
+ 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.
+-->
+
+<html>
+<head>
+<title>Package org.apache.jdo.impl.pm</title>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"/>
+</head>
+
+<body bgcolor="#FFFFFF">
+<p>This package contains classes that are for use across all kinds of implementations
+ of the JDO Reference Implementation. The classes herein by and large implement
+ the interfaces defined in <a href="../package-summary.html">org.apache.jdo.pm</a>.
+</body>
+</html>
Added: incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/sco/ArrayList.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/sco/ArrayList.java?view=auto&rev=158176
==============================================================================
--- incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/sco/ArrayList.java (added)
+++ incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/sco/ArrayList.java Fri Mar 18 17:02:29 2005
@@ -0,0 +1,605 @@
+/*
+ * 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.
+ */
+
+/*
+ * sco.ArrayList.java
+ */
+
+package org.apache.jdo.impl.sco;
+
+import java.util.Collection;
+import java.util.Iterator;
+
+import javax.jdo.JDOUserException;
+import javax.jdo.JDOFatalInternalException;
+
+import org.apache.jdo.sco.SCO;
+import org.apache.jdo.sco.SCOCollection;
+import org.apache.jdo.state.StateManagerInternal;
+import org.apache.jdo.util.I18NHelper;
+
+
+/**
+ * A mutable 2nd class object that represents ArrayList.
+ * @author Marina Vatkina
+ * @version 1.0.1
+ * @see java.util.ArrayList
+ */
+public class ArrayList extends java.util.ArrayList
+ implements SCOCollection {
+
+ private transient StateManagerInternal owner;
+
+ private transient int fieldNumber = -1;
+
+ private transient Class elementType;
+
+ private transient boolean allowNulls;
+
+ private transient java.util.Vector added = new java.util.Vector();
+
+ private transient java.util.Vector removed = new java.util.Vector();
+
+ /**
+ * I18N message handler
+ */
+ private final static I18NHelper msg = I18NHelper.getInstance(
+ "org.apache.jdo.impl.sco.Bundle"); // NOI18N
+
+ private final static String _ArrayList = "ArrayList"; // NOI18N
+
+ /**
+ * Constructs an empty <code>ArrayList</code> object.
+ *
+ * @param elementType the element types allowed
+ * @param allowNulls true if nulls are allowed
+ */
+ public ArrayList(Class elementType, boolean allowNulls) {
+ super();
+
+ this.elementType = elementType;
+ this.allowNulls = allowNulls;
+ }
+
+ /**
+ * Constructs an empty <code>ArrayList</code> object that the specified
+ * initial capacity.
+ *
+ * @param elementType the element types allowed
+ * @param allowNulls true if nulls are allowed
+ * @param initialCapacity the initial capacity of the list.
+ * @exception IllegalArgumentException if the specified initial capacity
+ * is negative
+ */
+ public ArrayList(Class elementType, boolean allowNulls,
+ int initialCapacity) {
+ super(initialCapacity);
+ this.elementType = elementType;
+ this.allowNulls = allowNulls;
+ }
+
+ /** ------------------Public Methods----------------*/
+
+ /**
+ * Replaces the element at the specified position in this ArrayList with the
+ * specified element.
+ *
+ * @param index index of element to replace.
+ * @param element element to be stored at the specified position.
+ * @return the element previously at the specified position.
+ * @exception IndexOutOfBoundsException index out of range
+ * (index < 0 || index >= size()).
+ * @exception IllegalArgumentException fromIndex > toIndex.
+ * @see java.util.ArrayList
+ */
+ public Object set(int index, Object element) {
+ SCOHelper.debug(_ArrayList, "set"); // NOI18N
+
+ if (element == null) {
+ SCOHelper.assertNullsAllowed(element, allowNulls);
+ // It is actualy remove
+ return this.remove(index);
+ }
+ SCOHelper.assertElementType(element, elementType);
+ // Mark the field as dirty
+ this.makeDirty();
+
+ Object o = super.set(index, element);
+ if (added.remove(o) == false) {
+ removed.add(o);
+ }
+ if (removed.remove(element) == false) {
+ added.add(element);
+ }
+ // Apply updates
+ this.trackUpdates(true);
+
+ return o;
+ }
+
+
+ /**
+ * Appends the specified element to the end of this ArrayList.
+ *
+ * @param o element to be appended to this ArrayList.
+ * @return true (as per the general contract of Collection.add).
+ * @see java.util.ArrayList
+ */
+ public boolean add(Object o) {
+ SCOHelper.debug(_ArrayList, "add"); // NOI18N
+
+ SCOHelper.assertNullsAllowed(o, allowNulls);
+ SCOHelper.assertElementType(o, elementType);
+
+ // Mark the field as dirty
+ this.makeDirty();
+
+ if (removed.remove(o) == false) {
+ added.add(o);
+ }
+
+ boolean modified = super.add(o);
+
+ // Apply updates
+ this.trackUpdates(modified);
+
+ return modified;
+ }
+
+ /**
+ * Removes the first occurrence of the specified element in this ArrayList
+ * If the ArrayList does not contain the element, it is unchanged.
+ *
+ * @param o element to be removed from this ArrayList, if present.
+ * @return true if the ArrayList contained the specified element.
+ * @see java.util.ArrayList
+ */
+ public boolean remove(Object o) {
+ SCOHelper.debug(_ArrayList, "remove"); // NOI18N
+
+ // Because java.util.AbstractCollection.remove(Object)
+ // delegates remove() to remove(int) which is not supported,
+ // we cannot rely on jdk. We need to process remove here.
+
+ // Mark the field as dirty
+ this.makeDirty();
+
+ int i = super.indexOf(o);
+ Object obj = null;
+ if (i > -1) {
+ obj = super.remove(i);
+ if (added.remove(obj) == false) {
+ removed.add(obj);
+ }
+ // Apply updates
+ this.trackUpdates(true);
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Inserts the specified element at the specified position in this ArrayList.
+ *
+ * @param index index at which the specified element is to be inserted.
+ * @param element element to be inserted.
+ * @exception IndexOutOfBoundsException index is out of range
+ * (index < 0 || index > size()).
+ * @see java.util.ArrayList
+ */
+ public void add(int index, Object element) {
+ SCOHelper.debug(_ArrayList, "add by index"); // NOI18N
+
+ SCOHelper.assertNullsAllowed(element, allowNulls);
+ SCOHelper.assertElementType(element, elementType);
+
+ // Mark the field as dirty
+ this.makeDirty();
+
+ super.add(index, element);
+ if (removed.remove(element) == false) {
+ added.add(element);
+ }
+ // Apply updates
+ this.trackUpdates(true);
+
+ }
+
+ /**
+ * Removes the element at the specified position in this ArrayList.
+ * shifts any subsequent elements to the left (subtracts one from their
+ * indices). Returns the element that was removed from the ArrayList.
+ *
+ * @param index the index of the element to removed.
+ * @exception IndexOutOfBoundsException index out of range (index
+ * < 0 || index >= size()).
+ * @see java.util.ArrayList
+ */
+ public Object remove(int index) {
+ SCOHelper.debug(_ArrayList, "remove by index"); // NOI18N
+
+ // Mark the field as dirty
+ this.makeDirty();
+
+ Object obj = super.remove(index);
+ if (added.remove(obj) == false) {
+ removed.add(obj);
+ }
+ // Apply updates
+ this.trackUpdates(true);
+
+ return obj;
+ }
+
+ /**
+ * Removes all of the elements from this ArrayList. The ArrayList will
+ * be empty after this call returns (unless it throws an exception).
+ *
+ * @see java.util.ArrayList
+ */
+ public void clear() {
+ SCOHelper.debug(_ArrayList, "clear"); // NOI18N
+
+ // Mark the field as dirty
+ this.makeDirty();
+
+ for (Iterator iter = super.iterator(); iter.hasNext();) {
+ Object o = iter.next();
+ if (added.remove(o) == false) {
+ removed.add(o);
+ }
+ }
+ added.clear();
+ super.clear();
+
+ // Apply updates
+ this.trackUpdates(true);
+ }
+
+ /**
+ * Appends all of the elements in the specified Collection to the end of
+ * this ArrayList, in the order that they are returned by the specified
+ * Collection's Iterator.
+ *
+ * @param c elements to be inserted into this ArrayList.
+ * @exception IndexOutOfBoundsException index out of range (index
+ * < 0 || index > size()).
+ * @see java.util.ArrayList
+ */
+ public boolean addAll(Collection c) {
+ SCOHelper.debug(_ArrayList, "addAll"); // NOI18N
+
+ // iterate the collection and make a list of wrong elements.
+ Throwable[] err = new Throwable[c.size()];
+ int l = 0;
+
+ Iterator i = c.iterator();
+ while (i.hasNext()) {
+ Object o = i.next();
+ try {
+ SCOHelper.assertNullsAllowed(o, allowNulls);
+ SCOHelper.assertElementType(o, elementType);
+ } catch (Throwable e) {
+ err[l++] = e;
+ }
+ }
+ SCOHelper.validateResult(l, err);
+
+ // Mark the field as dirty
+ this.makeDirty();
+
+ removed.removeAll(c);
+ added.addAll(c);
+
+ boolean modified = super.addAll(c);
+
+ // Apply updates
+ this.trackUpdates(modified);
+
+ return modified;
+ }
+
+ /**
+ * Removes from this ArrayList all of its elements that are contained in the
+ * specified Collection.
+ *
+ * @return true if this ArrayList changed as a result of the call.
+ * @see java.util.ArrayList
+ */
+ public boolean removeAll(Collection c) {
+ SCOHelper.debug(_ArrayList, "removeAll"); // NOI18N
+
+ boolean modified = false;
+ // Mark the field as dirty
+ this.makeDirty();
+
+ Iterator e = c.iterator();
+ while (e.hasNext()) {
+ Object o = e.next();
+ if(super.contains(o)) {
+ removeInternal(o);
+ if (added.remove(o) == false) {
+ removed.add(o);
+ }
+ modified = true;
+ }
+ }
+
+ // Apply updates
+ this.trackUpdates(modified);
+
+ return modified;
+ }
+
+ /**
+ * Inserts all of the elements in in the specified Collection into this
+ * ArrayList at the specified position. Shifts the element currently at
+ * that position (if any) and any subsequent elements to the right
+ * (increases their indices). The new elements will appear in the ArrayList
+ * in the order that they are returned by the specified Collection's
+ * iterator.
+ *
+ * @param index index at which to insert first element
+ * from the specified collection.
+ * @param c elements to be inserted into this ArrayList.
+ * @exception IndexOutOfBoundsException index out of range (index
+ * < 0 || index > size()).
+ * @see java.util.ArrayList
+ */
+ public boolean addAll(int index, Collection c) {
+ SCOHelper.debug(_ArrayList, "addAll from index"); // NOI18N
+
+ // iterate the collection and make a list of wrong elements.
+ Throwable[] err = new Throwable[c.size()];
+ int l = 0;
+
+ Iterator i = c.iterator();
+ while (i.hasNext()) {
+ Object o = i.next();
+ try {
+ SCOHelper.assertNullsAllowed(o, allowNulls);
+ SCOHelper.assertElementType(o, elementType);
+ } catch (Throwable e) {
+ err[l++] = e;
+ }
+ }
+ SCOHelper.validateResult(l, err);
+
+ // Mark the field as dirty
+ this.makeDirty();
+
+ removed.removeAll(c);
+ added.addAll(c);
+
+ boolean modified = super.addAll(index, c);
+
+ // Apply updates
+ this.trackUpdates(modified);
+
+ return modified;
+ }
+
+ /**
+ * Retains only the elements in this ArrayList that are contained in the
+ * specified Collection.
+ *
+ * @return true if this ArrayList changed as a result of the call.
+ * @see java.util.ArrayList
+ */
+ public boolean retainAll(Collection c) {
+ SCOHelper.debug(_ArrayList, "retainAll"); // NOI18N
+
+ boolean modified = false;
+ java.util.ArrayList v = new java.util.ArrayList();
+
+ // Mark the field as dirty
+ this.makeDirty();
+
+ for (Iterator iter = super.iterator(); iter.hasNext();) {
+ Object o = iter.next();
+ if (!c.contains(o)) {
+ v.add(o);
+ if (added.remove(o) == false) {
+ removed.add(o);
+ }
+ modified = true;
+ }
+ }
+
+ // Now remove the rest (stored in "v")
+ for (Iterator iter = v.iterator(); iter.hasNext();) {
+ removeInternal(iter.next());
+ }
+
+ // Apply updates
+ this.trackUpdates(modified);
+
+ return modified;
+ }
+
+ /**
+ * Creates and returns a copy of this object.
+ *
+ * <P>Mutable Second Class Objects are required to provide a public
+ * clone method in order to allow for copying PersistenceCapable
+ * objects. In contrast to Object.clone(), this method must not throw a
+ * CloneNotSupportedException.
+ */
+ public Object clone() {
+ SCOHelper.debug(_ArrayList, "clone"); // NOI18N
+
+ Object obj = super.clone();
+ if (obj instanceof SCO)
+ ((SCO)obj).unsetOwner(owner, fieldNumber);
+
+ return obj;
+ }
+
+ /**
+ * @see SCOCollection#reset()
+ */
+ public void reset() {
+ added.clear();
+ removed.clear();
+ }
+
+ /**
+ * @see SCOCollection#addInternal(Object o)
+ */
+ public void addInternal(Object o) {
+ super.add(o);
+ }
+
+
+ /**
+ * @see SCOCollection#addAllInternal(Collection c)
+ */
+ public void addAllInternal(Collection c) {
+ super.addAll(c);
+ }
+
+ /**
+ * @see SCOCollection#getAdded()
+ */
+ public Collection getAdded() {
+ return (Collection)added;
+ }
+
+ /**
+ * @see SCOCollection#getRemoved()
+ */
+ public Collection getRemoved() {
+ return (Collection)removed;
+ }
+
+
+ /**
+ * @see SCOCollection#clearInternal()
+ */
+ public void clearInternal() {
+ super.clear();
+ this.reset();
+ }
+
+ /**
+ * @see SCOCollection#removeInternal(Object o)
+ */
+ public void removeInternal(Object o) {
+ int i = super.indexOf(o);
+ super.remove(i);
+ }
+
+ /**
+ * @see SCO#unsetOwner(Object owner, int fieldNumber)
+ */
+ public void unsetOwner(Object owner, int fieldNumber) {
+ // Unset only if owner and fieldNumber match.
+ if (this.owner == owner && this.fieldNumber == fieldNumber) {
+ this.owner = null;
+ this.fieldNumber = -1;
+ }
+ }
+
+ /**
+ * Marks object dirty
+ */
+ private void makeDirty() {
+ if (owner != null) {
+ owner.makeDirty(fieldNumber);
+ }
+ }
+
+ /**
+ * Apply changes
+ * @param modified true if content of this list has been changed.
+ */
+ private void trackUpdates(boolean modified) {
+ if (modified && owner != null) {
+ owner.trackUpdates(fieldNumber, this);
+ }
+ }
+
+ /**
+ * @see SCO#setOwner (Object owner, int fieldNumber)
+ */
+ public void setOwner (Object owner, int fieldNumber) {
+ // Set only if it was not set before.
+ if (this.owner == null && owner instanceof StateManagerInternal) {
+ this.owner = (StateManagerInternal)owner;
+ this.fieldNumber = fieldNumber;
+ }
+ }
+
+ /**
+ * @see SCO#getOwner ()
+ */
+ public Object getOwner() {
+ return SCOHelper.getOwner(owner);
+ }
+
+ /**
+ * @see SCO#getFieldName()
+ */
+ public String getFieldName() {
+ return SCOHelper.getFieldName(owner, fieldNumber);
+ }
+
+ /**
+ * @see SCOCollection#getElementType() {
+ */
+ public Class getElementType() {
+ return elementType;
+ }
+
+ /**
+ * @see SCOCollection#allowNulls() {
+ */
+ public boolean allowNulls() {
+ return allowNulls;
+ }
+
+ /** Get an iterator over the frozen elements of this collection.
+ * This class does not require freezing, so this method returns
+ * a standard iterator.
+ * @since 1.0.1
+ * @return an iterator over the elements.
+ */
+ public Iterator frozenIterator() {
+ return iterator();
+ }
+
+ /** Set the contents of this Collection from the frozen elements.
+ * This class does not support explicit frozen operations, and this method
+ * always throws an exception.
+ * @since 1.0.1
+ * @param elements not used.
+ */
+ public void setFrozen(Object[] elements) {
+ throw new JDOFatalInternalException(
+ msg.msg("EXC_UnsupportedFreezerOperation")); //NOI18N
+ }
+
+ /** Get an iterator regardless of whether the collection is frozen.
+ * This class does not support frozen operations and always returns
+ * a regular iterator.
+ * @since 1.0.1
+ * @return an iterator over the elements.
+ */
+ public Iterator eitherIterator() {
+ return iterator();
+ }
+
+}
Added: incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/sco/Bundle.properties
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/sco/Bundle.properties?view=auto&rev=158176
==============================================================================
--- incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/sco/Bundle.properties (added)
+++ incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/sco/Bundle.properties Fri Mar 18 17:02:29 2005
@@ -0,0 +1,34 @@
+#
+# 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.
+
+# Exceptions for allowNulls validation:
+EXC_ElementNullsNotAllowed=Nulls are not allowed as elements of this Collection.
+EXC_KeyNullsNotAllowed=Nulls are not allowed as keys of this Map.
+EXC_ValueNullsNotAllowed=Nulls are not allowed as values of this Map.
+
+# Exceptions for type validation:
+EXC_ElementClassCastException=New element cannot be cast to {0}.
+EXC_KeyClassCastException=New key cannot be cast to {0}.
+EXC_ValueClassCastException=New value cannot be cast to {0}.
+
+# Exception processing Collection or Map as an argument:
+EXC_FailedToProcessAll=Failed to process all parameters.
+
+# Exceptions for freezing Set and Map
+EXC_OidNotComparable=Object id classes must be comparable. Class {0} does not implement Comparable.
+EXC_ConcurrentModification=This collection was thawed during iteration of the frozen contents.
+EXC_RemoveNotSupported=Optional method remove() is not supported for frozen Iterator.
+EXC_UnsupportedFreezerOperation=This class does not support operations for freezing and thawing.
+
|