diff options
author | Caspar De Groot | 2010-06-15 03:54:24 +0000 |
---|---|---|
committer | Caspar De Groot | 2010-06-15 03:54:24 +0000 |
commit | e9cfb00d5f650abcebf577cb4b5049c770aadcdb (patch) | |
tree | 7c16c2aabfa553a6602e0e9640f97c92affcfb40 | |
parent | 9dccc5f76e1831d335dc7ecdfbaa36cfc853ea91 (diff) | |
download | cdo-e9cfb00d5f650abcebf577cb4b5049c770aadcdb.tar.gz cdo-e9cfb00d5f650abcebf577cb4b5049c770aadcdb.tar.xz cdo-e9cfb00d5f650abcebf577cb4b5049c770aadcdb.zip |
[302414] ArrayIndexOutOfBoundsException in CDOListFeatureDeltaImpl
https://bugs.eclipse.org/bugs/show_bug.cgi?id=302414
3 files changed, 104 insertions, 33 deletions
diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/revision/delta/CDOListFeatureDeltaImpl.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/revision/delta/CDOListFeatureDeltaImpl.java index a839f5598b..e4f5b5ce0a 100644 --- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/revision/delta/CDOListFeatureDeltaImpl.java +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/revision/delta/CDOListFeatureDeltaImpl.java @@ -40,11 +40,11 @@ public class CDOListFeatureDeltaImpl extends CDOFeatureDeltaImpl implements CDOL { private List<CDOFeatureDelta> featureDeltas = new ArrayList<CDOFeatureDelta>(); - private transient int[] cacheIndices; + private transient int[] cachedIndices; - private transient IListTargetAdding[] cacheSources; + private transient IListTargetAdding[] cachedSources; - private transient List<CDOFeatureDelta> notProcessedFeatureDelta; + private transient List<CDOFeatureDelta> unprocessedFeatureDeltas; public CDOListFeatureDeltaImpl(EStructuralFeature feature) { @@ -102,57 +102,61 @@ public class CDOListFeatureDeltaImpl extends CDOFeatureDeltaImpl implements CDOL public Pair<IListTargetAdding[], int[]> reconstructAddedIndices() { reconstructAddedIndicesWithNoCopy(); - return new Pair<IListTargetAdding[], int[]>(copyOf(cacheSources, cacheSources.length, cacheSources.getClass()), - copyOf(cacheIndices, cacheIndices.length)); + return new Pair<IListTargetAdding[], int[]>(copyOf(cachedSources, cachedSources.length, cachedSources.getClass()), + copyOf(cachedIndices, cachedIndices.length)); } private void reconstructAddedIndicesWithNoCopy() { - if (cacheIndices == null || notProcessedFeatureDelta != null) + if (cachedIndices == null || unprocessedFeatureDeltas != null) { - if (cacheIndices == null) + List<CDOFeatureDelta> featureDeltasToBeProcessed = unprocessedFeatureDeltas == null ? featureDeltas + : unprocessedFeatureDeltas; + + // Actually the required capacity is the number of ListTargetAdding instances in the + // featureDeltasToBeProcessed.. so this is an overestimate + int requiredCapacity = featureDeltasToBeProcessed.size() + 1; + + if (cachedIndices == null) { - cacheIndices = new int[1 + featureDeltas.size()]; + cachedIndices = new int[1 + featureDeltas.size()]; } - else if (cacheIndices.length <= 1 + featureDeltas.size()) + else if (cachedIndices.length < requiredCapacity) { - int newCapacity = Math.max(10, cacheIndices.length * 3 / 2 + 1); + int newCapacity = Math.max(requiredCapacity, cachedIndices.length * 3 / 2); int[] newElements = new int[newCapacity]; - System.arraycopy(cacheIndices, 0, newElements, 0, cacheIndices.length); - cacheIndices = newElements; + System.arraycopy(cachedIndices, 0, newElements, 0, cachedIndices.length); + cachedIndices = newElements; } - if (cacheSources == null) + if (cachedSources == null) { - cacheSources = new IListTargetAdding[1 + featureDeltas.size()]; + cachedSources = new IListTargetAdding[requiredCapacity]; } - else if (cacheSources.length <= 1 + featureDeltas.size()) + else if (cachedSources.length <= requiredCapacity) { - int newCapacity = Math.max(10, cacheSources.length * 3 / 2 + 1); + int newCapacity = Math.max(requiredCapacity, cachedSources.length * 3 / 2); IListTargetAdding[] newElements = new IListTargetAdding[newCapacity]; - System.arraycopy(cacheSources, 0, newElements, 0, cacheSources.length); - cacheSources = newElements; + System.arraycopy(cachedSources, 0, newElements, 0, cachedSources.length); + cachedSources = newElements; } - List<CDOFeatureDelta> featureDeltasToBeProcess = notProcessedFeatureDelta == null ? featureDeltas - : notProcessedFeatureDelta; - - for (CDOFeatureDelta featureDelta : featureDeltasToBeProcess) + for (CDOFeatureDelta featureDelta : featureDeltasToBeProcessed) { if (featureDelta instanceof IListIndexAffecting) { IListIndexAffecting affecting = (IListIndexAffecting)featureDelta; - affecting.affectIndices(cacheSources, cacheIndices); + affecting.affectIndices(cachedSources, cachedIndices); } if (featureDelta instanceof IListTargetAdding) { - cacheIndices[++cacheIndices[0]] = ((IListTargetAdding)featureDelta).getIndex(); - cacheSources[cacheIndices[0]] = (IListTargetAdding)featureDelta; + cachedIndices[++cachedIndices[0]] = ((IListTargetAdding)featureDelta).getIndex(); + cachedSources[cachedIndices[0]] = (IListTargetAdding)featureDelta; } } - notProcessedFeatureDelta = null; + unprocessedFeatureDeltas = null; } } @@ -165,25 +169,25 @@ public class CDOListFeatureDeltaImpl extends CDOFeatureDeltaImpl implements CDOL int indexToRemove = ((CDORemoveFeatureDelta)featureDelta).getIndex(); reconstructAddedIndicesWithNoCopy(); - for (int i = 1; i <= cacheIndices[0]; i++) + for (int i = 1; i <= cachedIndices[0]; i++) { - int index = cacheIndices[i]; + int index = cachedIndices[i]; if (indexToRemove == index) { - cacheSources[i].clear(); + cachedSources[i].clear(); break; } } } - if (cacheIndices != null) + if (cachedIndices != null) { - if (notProcessedFeatureDelta == null) + if (unprocessedFeatureDeltas == null) { - notProcessedFeatureDelta = new ArrayList<CDOFeatureDelta>(); + unprocessedFeatureDeltas = new ArrayList<CDOFeatureDelta>(); } - notProcessedFeatureDelta.add(featureDelta); + unprocessedFeatureDeltas.add(featureDelta); } } diff --git a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/AllTestsAllConfigs.java b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/AllTestsAllConfigs.java index bf328ca1fe..1a56903b88 100644 --- a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/AllTestsAllConfigs.java +++ b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/AllTestsAllConfigs.java @@ -62,6 +62,7 @@ import org.eclipse.emf.cdo.tests.bugzilla.Bugzilla_294850_Test; import org.eclipse.emf.cdo.tests.bugzilla.Bugzilla_294859_Test; import org.eclipse.emf.cdo.tests.bugzilla.Bugzilla_299190_Test; import org.eclipse.emf.cdo.tests.bugzilla.Bugzilla_301671_Test; +import org.eclipse.emf.cdo.tests.bugzilla.Bugzilla_302414_Test; import org.eclipse.emf.cdo.tests.bugzilla.Bugzilla_316175_Test; import org.eclipse.emf.cdo.tests.config.impl.ConfigTest; import org.eclipse.emf.cdo.tests.config.impl.ConfigTestSuite; @@ -173,6 +174,7 @@ public abstract class AllTestsAllConfigs extends ConfigTestSuite testClasses.add(Bugzilla_294859_Test.class); testClasses.add(Bugzilla_299190_Test.class); testClasses.add(Bugzilla_301671_Test.class); + testClasses.add(Bugzilla_302414_Test.class); testClasses.add(Bugzilla_316175_Test.class); // TODO testClasses.add(NonCDOResourceTest.class); diff --git a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_302414_Test.java b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_302414_Test.java new file mode 100644 index 0000000000..ab1f1453e0 --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_302414_Test.java @@ -0,0 +1,65 @@ +/** + * Copyright (c) 2004 - 2010 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Caspar De Groot - initial API and implementation + */ +package org.eclipse.emf.cdo.tests.bugzilla; + +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.Company; +import org.eclipse.emf.cdo.tests.model1.Model1Factory; +import org.eclipse.emf.cdo.tests.model1.PurchaseOrder; +import org.eclipse.emf.cdo.transaction.CDOTransaction; + +import java.util.List; + +/** + * @author Caspar De Groot + */ +public class Bugzilla_302414_Test extends AbstractCDOTest +{ + public void test() + { + CDOSession session = openSession(); + CDOTransaction tx = session.openTransaction(); + CDOResource r1 = tx.createResource("/r1"); //$NON-NLS-1$ + + Company company = Model1Factory.eINSTANCE.createCompany(); + r1.getContents().add(company); + tx.commit(); + + List<PurchaseOrder> list = company.getPurchaseOrders(); + + PurchaseOrder foo = Model1Factory.eINSTANCE.createPurchaseOrder(); + list.add(foo); + list.remove(foo); + + PurchaseOrder bar = Model1Factory.eINSTANCE.createPurchaseOrder(); + list.add(bar); + + for (int i = 0; i < 10; i++) + { + company.getPurchaseOrders().add(Model1Factory.eINSTANCE.createPurchaseOrder()); + } + + try + { + list.remove(bar); + } + catch (ArrayIndexOutOfBoundsException e) + { + e.printStackTrace(); + fail("Should not have thrown " + e.getClass().getName()); + } + + tx.close(); + session.close(); + } +} |