Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEsteban Dugueperoux2015-04-14 12:13:10 +0000
committerEike Stepper2015-05-07 09:04:31 +0000
commit4be6279b1f41bc414fc8d901f020f7f81bfa99da (patch)
tree766dab2521e0db97c7e0f818fdc6a7c254851e75 /plugins
parent17e98cecfe9487f4440125cbd1b26650872f14d5 (diff)
downloadcdo-4be6279b1f41bc414fc8d901f020f7f81bfa99da.tar.gz
cdo-4be6279b1f41bc414fc8d901f020f7f81bfa99da.tar.xz
cdo-4be6279b1f41bc414fc8d901f020f7f81bfa99da.zip
[462953] ArrayIndexOutOfBoundsException on EObject.eIsSet() call after
rollback - Have RollbackTransition called on CDOTransaction.rollback() for new objects to have InternalCDOObject.cdoInternalPostDetach() called and have CDOObjectImpl.eSettings recomputed for Transient state - Add Bugzilla_462953_Test to test EObject.eIsSet() call during and after a CDOTransaction.rollback() Change-Id: If02bd34c5ca73fc8360068f328720f2a59576b7d Task-Url: https://bugs.eclipse.org/bugs/show_bug.cgi?id=462953 Signed-off-by: Esteban Dugueperoux <esteban.dugueperoux@obeo.fr>
Diffstat (limited to 'plugins')
-rw-r--r--plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/StateMachineTest.java5
-rw-r--r--plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_462953_Test.java116
-rw-r--r--plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/transaction/CDOTransactionImpl.java38
-rw-r--r--plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/view/CDOStateMachine.java16
-rw-r--r--plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/spi/cdo/AbstractObjectConflictResolver.java4
5 files changed, 155 insertions, 24 deletions
diff --git a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/StateMachineTest.java b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/StateMachineTest.java
index b86536c17b..bc3d538dbf 100644
--- a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/StateMachineTest.java
+++ b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/StateMachineTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008-2014 Eike Stepper (Berlin, Germany) and others.
+ * Copyright (c) 2008-2015 Eike Stepper (Berlin, Germany) and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -30,6 +30,7 @@ import org.eclipse.net4j.util.io.IOUtil;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.spi.cdo.InternalCDOObject;
+import org.eclipse.emf.spi.cdo.InternalCDOTransaction;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
@@ -428,7 +429,7 @@ public class StateMachineTest extends AbstractCDOTest
CDOObject cdoObject = CDOUtil.getCDOObject(object);
if (cdoObject != null)
{
- CDOStateMachine.INSTANCE.rollback((InternalCDOObject)cdoObject);
+ CDOStateMachine.INSTANCE.rollback((InternalCDOObject)cdoObject, (InternalCDOTransaction)cdoObject.cdoView());
}
}
diff --git a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_462953_Test.java b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_462953_Test.java
new file mode 100644
index 0000000000..e5b9500550
--- /dev/null
+++ b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_462953_Test.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2015 Obeo and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Esteban Dugueperoux - initial API and implementation
+ */
+package org.eclipse.emf.cdo.tests.bugzilla;
+
+import org.eclipse.emf.cdo.CDOObject;
+import org.eclipse.emf.cdo.CDOState;
+import org.eclipse.emf.cdo.eresource.CDOResource;
+import org.eclipse.emf.cdo.session.CDOSession;
+import org.eclipse.emf.cdo.tests.AbstractCDOTest;
+import org.eclipse.emf.cdo.tests.model1.Category;
+import org.eclipse.emf.cdo.tests.model1.Company;
+import org.eclipse.emf.cdo.transaction.CDOTransaction;
+import org.eclipse.emf.cdo.util.CDOUtil;
+
+import org.eclipse.emf.common.notify.Notification;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EReference;
+import org.eclipse.emf.ecore.util.EContentAdapter;
+import org.eclipse.emf.ecore.util.ECrossReferenceAdapter;
+
+/**
+ * Bug 462953 : ArrayIndexOutOfBoundsException on EObject.eIsSet() call after rollback.
+ *
+ * @author Esteban Dugueperoux
+ */
+public class Bugzilla_462953_Test extends AbstractCDOTest
+{
+ private static final String RESOURCE_NAME = "test1.model1";
+
+ /**
+ * Test {@link CDOTransaction#rollback()} with a custom {@link EContentAdapter} which call {@link EObject#eIsSet(org.eclipse.emf.ecore.EStructuralFeature)}.
+ */
+ public void testRollBackWithACustomEContentAdapter() throws Exception
+ {
+ CDOSession session1 = openSession();
+ CDOTransaction transaction1 = session1.openTransaction();
+ CDOResource resource1 = transaction1.createResource(getResourcePath(RESOURCE_NAME));
+ Company company = getModel1Factory().createCompany();
+ company.getCategories().add(getModel1Factory().createCategory());
+ resource1.getContents().add(company);
+ transaction1.commit();
+ transaction1.close();
+ session1.close();
+
+ session1 = openSession();
+ transaction1 = session1.openTransaction();
+ resource1 = transaction1.getResource(getResourcePath(RESOURCE_NAME));
+ // To test EObject.eIsSet() during rollback
+ resource1.eAdapters().add(new CustomECrossReferenceAdapter());
+
+ company = (Company)resource1.getContents().get(0);
+ Category category = getModel1Factory().createCategory();
+
+ // Test EObject.eIsSet() before category attachement to the CDOResource
+ for (EReference eReference : category.eClass().getEReferences())
+ {
+ category.eIsSet(eReference);
+ }
+
+ company.getCategories().add(category);
+
+ // Test EObject.eIsSet() before rollback
+ for (EReference eReference : category.eClass().getEReferences())
+ {
+ category.eIsSet(eReference);
+ }
+
+ transaction1.rollback();
+
+ // Test EObject.eIsSet() after rollback
+ for (EReference eReference : category.eClass().getEReferences())
+ {
+ category.eIsSet(eReference);
+ }
+
+ CDOObject cdoObject = CDOUtil.getCDOObject(category);
+ assertEquals(CDOState.TRANSIENT, cdoObject.cdoState());
+ assertNull(cdoObject.cdoID());
+ assertNull(cdoObject.cdoView());
+ }
+
+ private static class CustomECrossReferenceAdapter extends ECrossReferenceAdapter
+ {
+
+ @Override
+ protected void handleContainment(Notification notification)
+ {
+ super.handleContainment(notification);
+ switch (notification.getEventType())
+ {
+ case Notification.REMOVE:
+ {
+ Object oldValue = notification.getOldValue();
+ if (oldValue instanceof EObject)
+ {
+ EObject eObject = (EObject)oldValue;
+ for (EReference eReference : eObject.eClass().getEReferences())
+ {
+ eObject.eIsSet(eReference);
+ }
+ }
+ break;
+ }
+ }
+ }
+ }
+
+}
diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/transaction/CDOTransactionImpl.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/transaction/CDOTransactionImpl.java
index 5eea5e796e..b7a397796a 100644
--- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/transaction/CDOTransactionImpl.java
+++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/transaction/CDOTransactionImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009-2014 Eike Stepper (Berlin, Germany) and others.
+ * Copyright (c) 2009-2015 Eike Stepper (Berlin, Germany) and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -1332,16 +1332,12 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa
}
});
}
-
- InternalCDOObject internal = (InternalCDOObject)object;
- internal.cdoInternalSetView(null);
- internal.cdoInternalSetID(null);
- internal.cdoInternalSetState(CDOState.TRANSIENT);
}
private Set<CDOID> rollbackCompletely(CDOUserSavepoint savepoint)
{
Set<CDOID> idsOfNewObjectsWithDeltas = new HashSet<CDOID>();
+ Set<InternalCDOObject> newObjects = new HashSet<InternalCDOObject>();
// Start from the last savepoint and come back up to the active
for (InternalCDOSavepoint itrSavepoint = lastSavepoint; itrSavepoint != null; itrSavepoint = itrSavepoint
@@ -1353,11 +1349,13 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa
Map<CDOID, CDOObject> newObjectsMap = itrSavepoint.getNewObjects();
for (CDOID id : newObjectsMap.keySet())
{
- CDOObject object = newObjectsMap.get(id);
+ InternalCDOObject object = (InternalCDOObject)newObjectsMap.get(id);
+
toBeDetached.add(id);
toBeDetached.add(object);
- toBeDetached.add(((InternalCDOObject)object).cdoInternalInstance());
+ toBeDetached.add(object.cdoInternalInstance());
removeObject(id, object);
+ newObjects.add(object);
}
// Rollback new objects re-attached after the save point
@@ -1368,10 +1366,16 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa
CDOID id = reattachedObject.cdoID();
if (!detachedIDs.contains(id))
{
+ InternalCDOObject internal = (InternalCDOObject)reattachedObject;
+
toBeDetached.add(id);
- toBeDetached.add(reattachedObject);
- toBeDetached.add(((InternalCDOObject)reattachedObject).cdoInternalInstance());
- removeObject(id, reattachedObject);
+ toBeDetached.add(internal);
+ toBeDetached.add(internal.cdoInternalInstance());
+ removeObject(id, internal);
+
+ internal.cdoInternalSetView(null);
+ internal.cdoInternalSetID(null);
+ internal.cdoInternalSetState(CDOState.TRANSIENT);
}
}
@@ -1445,7 +1449,7 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa
// they were already reset to TRANSIENT earlier in this method
if (!reattachedObjectsMap.values().contains(internalDirtyObject))
{
- CDOStateMachine.INSTANCE.rollback(internalDirtyObject);
+ CDOStateMachine.INSTANCE.rollback(internalDirtyObject, this);
}
}
}
@@ -1456,6 +1460,16 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa
}
}
+ for (InternalCDOObject internalCDOObject : newObjects)
+ {
+ if (FSMUtil.isNew(internalCDOObject))
+ {
+ CDOStateMachine.INSTANCE.rollback(internalCDOObject, this);
+ internalCDOObject.cdoInternalSetID(null);
+ internalCDOObject.cdoInternalSetView(null);
+ }
+ }
+
return idsOfNewObjectsWithDeltas;
}
diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/view/CDOStateMachine.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/view/CDOStateMachine.java
index e69dbef5e6..396afc43be 100644
--- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/view/CDOStateMachine.java
+++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/view/CDOStateMachine.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011-2014 Eike Stepper (Berlin, Germany) and others.
+ * Copyright (c) 2011-2015 Eike Stepper (Berlin, Germany) and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -124,7 +124,7 @@ public final class CDOStateMachine extends FiniteStateMachine<CDOState, CDOEvent
init(CDOState.NEW, CDOEvent.INVALIDATE, DetachRemoteTransition.INSTANCE);
init(CDOState.NEW, CDOEvent.DETACH_REMOTE, FAIL);
init(CDOState.NEW, CDOEvent.COMMIT, new CommitTransition(false));
- init(CDOState.NEW, CDOEvent.ROLLBACK, FAIL);
+ init(CDOState.NEW, CDOEvent.ROLLBACK, new RollbackTransition());
init(CDOState.CLEAN, CDOEvent.PREPARE, FAIL);
init(CDOState.CLEAN, CDOEvent.ATTACH, FAIL);
@@ -416,7 +416,7 @@ public final class CDOStateMachine extends FiniteStateMachine<CDOState, CDOEvent
}
}
- public void rollback(InternalCDOObject object)
+ public void rollback(InternalCDOObject object, InternalCDOTransaction transaction)
{
synchronized (getMonitor(object))
{
@@ -425,7 +425,7 @@ public final class CDOStateMachine extends FiniteStateMachine<CDOState, CDOEvent
trace(object, CDOEvent.ROLLBACK);
}
- process(object, CDOEvent.ROLLBACK, null);
+ process(object, CDOEvent.ROLLBACK, transaction);
}
}
@@ -901,15 +901,15 @@ public final class CDOStateMachine extends FiniteStateMachine<CDOState, CDOEvent
/**
* @author Eike Stepper
*/
- private final class RollbackTransition implements ITransition<CDOState, CDOEvent, InternalCDOObject, Object>
+ private final class RollbackTransition implements
+ ITransition<CDOState, CDOEvent, InternalCDOObject, InternalCDOTransaction>
{
- public void execute(InternalCDOObject object, CDOState state, CDOEvent event, Object NULL)
+ public void execute(InternalCDOObject object, CDOState state, CDOEvent event, InternalCDOTransaction transaction)
{
- InternalCDOTransaction transaction = object.cdoView().toTransaction();
if (transaction.getLastSavepoint().isNewObject(object.cdoID()))
{
- changeState(object, CDOState.TRANSIENT);
object.cdoInternalPostDetach(false);
+ changeState(object, CDOState.TRANSIENT);
}
else
{
diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/spi/cdo/AbstractObjectConflictResolver.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/spi/cdo/AbstractObjectConflictResolver.java
index e806f97c9a..a161f5c41c 100644
--- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/spi/cdo/AbstractObjectConflictResolver.java
+++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/spi/cdo/AbstractObjectConflictResolver.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009-2013 Eike Stepper (Berlin, Germany) and others.
+ * Copyright (c) 2009-2015 Eike Stepper (Berlin, Germany) and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -129,7 +129,7 @@ public abstract class AbstractObjectConflictResolver extends AbstractConflictRes
@Deprecated
public static void rollbackObject(CDOObject object)
{
- CDOStateMachine.INSTANCE.rollback((InternalCDOObject)object);
+ CDOStateMachine.INSTANCE.rollback((InternalCDOObject)object, (InternalCDOTransaction)object.cdoView());
}
public static void readObject(CDOObject object)

Back to the top