diff options
3 files changed, 76 insertions, 9 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 122ae5a1a6..0963c31688 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 @@ -162,13 +162,20 @@ public class CDOListFeatureDeltaImpl extends CDOFeatureDeltaImpl implements CDOL { if (cachedIndices == null || unprocessedFeatureDeltas != 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) { cachedIndices = new int[1 + featureDeltas.size()]; } - else if (cachedIndices.length <= 1 + featureDeltas.size()) + else if (cachedIndices.length < requiredCapacity) { - int newCapacity = Math.max(10, cachedIndices.length * 3 / 2 + 1); + int newCapacity = Math.max(requiredCapacity, cachedIndices.length * 3 / 2); int[] newElements = new int[newCapacity]; System.arraycopy(cachedIndices, 0, newElements, 0, cachedIndices.length); cachedIndices = newElements; @@ -176,20 +183,17 @@ public class CDOListFeatureDeltaImpl extends CDOFeatureDeltaImpl implements CDOL if (cachedSources == null) { - cachedSources = new ListTargetAdding[1 + featureDeltas.size()]; + cachedSources = new ListTargetAdding[requiredCapacity]; } - else if (cachedSources.length <= 1 + featureDeltas.size()) + else if (cachedSources.length <= requiredCapacity) { - int newCapacity = Math.max(10, cachedSources.length * 3 / 2 + 1); + int newCapacity = Math.max(requiredCapacity, cachedSources.length * 3 / 2); ListTargetAdding[] newElements = new ListTargetAdding[newCapacity]; System.arraycopy(cachedSources, 0, newElements, 0, cachedSources.length); cachedSources = newElements; } - List<CDOFeatureDelta> featureDeltasToBeProcess = unprocessedFeatureDeltas == null ? featureDeltas - : unprocessedFeatureDeltas; - - for (CDOFeatureDelta featureDelta : featureDeltasToBeProcess) + for (CDOFeatureDelta featureDelta : featureDeltasToBeProcessed) { if (featureDelta instanceof ListIndexAffecting) { diff --git a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/AllConfigs.java b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/AllConfigs.java index a567850cef..67b147e88c 100644 --- a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/AllConfigs.java +++ b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/AllConfigs.java @@ -67,6 +67,7 @@ import org.eclipse.emf.cdo.tests.bugzilla.Bugzilla_296561_Test; import org.eclipse.emf.cdo.tests.bugzilla.Bugzilla_298561_Test; import org.eclipse.emf.cdo.tests.bugzilla.Bugzilla_299190_Test; import org.eclipse.emf.cdo.tests.bugzilla.Bugzilla_302233_Test; +import org.eclipse.emf.cdo.tests.bugzilla.Bugzilla_302414_Test; import org.eclipse.emf.cdo.tests.bugzilla.Bugzilla_303466_Test; import org.eclipse.emf.cdo.tests.bugzilla.Bugzilla_303807_Test; import org.eclipse.emf.cdo.tests.bugzilla.Bugzilla_306710_Test; @@ -203,6 +204,7 @@ public abstract class AllConfigs extends ConfigTestSuite testClasses.add(Bugzilla_298561_Test.class); testClasses.add(Bugzilla_299190_Test.class); testClasses.add(Bugzilla_302233_Test.class); + testClasses.add(Bugzilla_302414_Test.class); testClasses.add(Bugzilla_303466_Test.class); testClasses.add(Bugzilla_303807_Test.class); testClasses.add(Bugzilla_306710_Test.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..32fdcba5c1 --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_302414_Test.java @@ -0,0 +1,61 @@ +/** + * 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 org.eclipse.emf.cdo.util.CommitException; + +import java.util.List; + +/** + * Bug 302414, bug 316713 - ArrayIndexOutOfBoundsException in CDOListFeatureDeltaImpl + * + * @author Caspar De Groot + */ +public class Bugzilla_302414_Test extends AbstractCDOTest +{ + public void test() throws CommitException + { + 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()); + } + + // The following statement must not fail! + list.remove(bar); + + tx.close(); + session.close(); + } +} |