Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHannes Wellmann2021-08-23 17:38:45 -0400
committerThomas Watson2021-09-07 13:38:58 -0400
commit4a50ef251a105c56fcd68c3acdbbcf57fdf94345 (patch)
treed3a2b680e7940a2129ed71ae733b83788415ee74
parent7e6f8c449ddaee2d942bfccfdc39ad1aaaaa4d28 (diff)
downloadrt.equinox.framework-4a50ef251a105c56fcd68c3acdbbcf57fdf94345.tar.gz
rt.equinox.framework-4a50ef251a105c56fcd68c3acdbbcf57fdf94345.tar.xz
rt.equinox.framework-4a50ef251a105c56fcd68c3acdbbcf57fdf94345.zip
Bug 575580 - Return a copy-on-first-write List in InternalUtils.asCopy()I20210907-1800
Change-Id: Ie1e4f915bdf12b0a46d1567938b382eb5077b639 Signed-off-by: Hannes Wellmann <wellmann.hannes1@gmx.net> Reviewed-on: https://git.eclipse.org/r/c/equinox/rt.equinox.framework/+/184339 Tested-by: Equinox Bot <equinox-bot@eclipse.org> Reviewed-by: Thomas Watson <tjwatson@us.ibm.com>
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/container/InternalUtils.java67
1 files changed, 66 insertions, 1 deletions
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/container/InternalUtils.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/container/InternalUtils.java
index e8ced172e..9f3c7be25 100644
--- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/container/InternalUtils.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/container/InternalUtils.java
@@ -15,11 +15,13 @@ package org.eclipse.osgi.internal.container;
import java.security.Permission;
import java.security.SecureRandom;
+import java.util.AbstractList;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
+import java.util.RandomAccess;
import java.util.UUID;
import org.eclipse.osgi.internal.framework.EquinoxConfiguration;
import org.osgi.framework.Bundle;
@@ -33,8 +35,71 @@ import org.osgi.framework.wiring.BundleCapability;
public class InternalUtils {
+ /**
+ * Returns a mutable wrapped around the given list, that creates a copy of the
+ * given list only if the list is about to be modified.
+ * <p>
+ * This method assumes that the given List is immutable and a
+ * {@link RandomAccess} list.
+ * </p>
+ *
+ * @param list the list to be copied.
+ * @return an effectively mutable and lazy copy of the given list.
+ */
public static <T> List<T> asCopy(List<? extends T> list) {
- return new ArrayList<>(list);
+ if (!(list instanceof RandomAccess)) {
+ throw new IllegalArgumentException("Only RandomAccess lists are supported"); //$NON-NLS-1$
+ }
+ return new CopyOnFirstWriteList<>(list);
+ }
+
+ private static final class CopyOnFirstWriteList<T> extends AbstractList<T> implements RandomAccess {
+ private List<T> copy;
+ private boolean copied = false;
+
+ CopyOnFirstWriteList(List<? extends T> list) {
+ copy = asList(list);
+ }
+
+ @Override
+ public T get(int index) {
+ return copy.get(index);
+ }
+
+ @Override
+ public int size() {
+ return copy.size();
+ }
+
+ @Override
+ public void add(int index, T element) {
+ ensureCopied();
+ copy.add(index, element);
+ modCount++;
+ }
+
+ @Override
+ public T remove(int index) {
+ ensureCopied();
+ T removed = copy.remove(index);
+ modCount++;
+ return removed;
+ }
+
+ @Override
+ public T set(int index, T element) {
+ ensureCopied();
+ T set = copy.set(index, element);
+ modCount++;
+ return set;
+ }
+
+ private void ensureCopied() {
+ if (!copied) {
+ copy = new ArrayList<>(copy);
+ copied = true;
+ }
+ }
}
/**

Back to the top