Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

resource: Defer SHA-256 calculation into the future #5323

Merged
merged 4 commits into from Jul 19, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
10 changes: 10 additions & 0 deletions biz.aQute.bnd.util/src/aQute/bnd/unmodifiable/Lists.java
@@ -1,8 +1,11 @@
package aQute.bnd.unmodifiable;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.function.Supplier;
import java.util.stream.Collector;

@SuppressWarnings("unchecked")
public class Lists {
Expand Down Expand Up @@ -71,4 +74,11 @@ public static <E> List<E> copyOf(Collection<? extends E> collection) {
}
return new ImmutableList<E>(collection.toArray());
}

public static <E> Collector<E, ?, List<E>> toList() {
return Collector.of((Supplier<List<E>>) ArrayList::new, List::add, (l, r) -> {
l.addAll(r);
return l;
}, Lists::copyOf);
}
}
13 changes: 13 additions & 0 deletions biz.aQute.bnd.util/src/aQute/bnd/unmodifiable/Sets.java
Expand Up @@ -2,7 +2,10 @@

import java.util.Arrays;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.function.Supplier;
import java.util.stream.Collector;

@SuppressWarnings("unchecked")
public class Sets {
Expand Down Expand Up @@ -69,8 +72,18 @@ public static <E> Set<E> copyOf(Collection<? extends E> collection) {
if (collection.isEmpty()) {
return of();
}
if (collection instanceof Set) {
return new ImmutableSet<E>(collection.toArray());
}
return new ImmutableSet<E>(collection.stream()
.distinct()
.toArray());
}

public static <E> Collector<E, ?, Set<E>> toSet() {
return Collector.of((Supplier<Set<E>>) LinkedHashSet::new, Set::add, (l, r) -> {
l.addAll(r);
return l;
}, Sets::copyOf);
}
}
@@ -1,4 +1,4 @@
@Version("2.0.0")
@Version("2.1.0")
package aQute.bnd.unmodifiable;

import org.osgi.annotation.versioning.Version;
19 changes: 19 additions & 0 deletions biz.aQute.bnd.util/test/aQute/bnd/unmodifiable/ListsTest.java
Expand Up @@ -550,4 +550,23 @@ public void spliterator() throws Exception {
Spliterator.SUBSIZED, Spliterator.NONNULL);
}

@Test
public void collector() {
List<String> source = new ArrayList<>();
source.add("e1");
source.add("e2");
source.add("e1");
List<String> list = source.stream()
.collect(Lists.toList());
source.set(0, "changed");
assertThat(list).hasSize(3)
.containsExactly("e1", "e2", "e1");
assertThat(list.stream()).hasSize(3)
.containsExactly("e1", "e2", "e1");
assertThatExceptionOfType(UnsupportedOperationException.class).isThrownBy(() -> list.add("a"));
assertThatExceptionOfType(UnsupportedOperationException.class).isThrownBy(() -> list.remove("a"));
assertThatExceptionOfType(UnsupportedOperationException.class).isThrownBy(() -> list.remove("e1"));
assertThatExceptionOfType(UnsupportedOperationException.class).isThrownBy(() -> list.clear());
}

}
51 changes: 35 additions & 16 deletions biz.aQute.bnd.util/test/aQute/bnd/unmodifiable/SetsTest.java
Expand Up @@ -40,7 +40,7 @@ public void zero() {
public void one() {
Set<String> set = Sets.of("e1");
assertThat(set).hasSize(1)
.containsExactlyInAnyOrder("e1");
.containsExactly("e1");
assertThat(set.stream()).hasSize(1)
.containsExactly("e1");
assertThatExceptionOfType(UnsupportedOperationException.class).isThrownBy(() -> set.add("a"));
Expand All @@ -53,7 +53,7 @@ public void one() {
public void two() {
Set<String> set = Sets.of("e1", "e2");
assertThat(set).hasSize(2)
.containsExactlyInAnyOrder("e1", "e2");
.containsExactly("e1", "e2");
assertThat(set.stream()).hasSize(2)
.containsExactly("e1", "e2");
assertThatExceptionOfType(UnsupportedOperationException.class).isThrownBy(() -> set.add("a"));
Expand All @@ -66,7 +66,7 @@ public void two() {
public void three() {
Set<String> set = Sets.of("e1", "e2", "e3");
assertThat(set).hasSize(3)
.containsExactlyInAnyOrder("e1", "e2", "e3");
.containsExactly("e1", "e2", "e3");
assertThat(set.stream()).hasSize(3)
.containsExactly("e1", "e2", "e3");
assertThatExceptionOfType(UnsupportedOperationException.class).isThrownBy(() -> set.add("a"));
Expand All @@ -79,7 +79,7 @@ public void three() {
public void four() {
Set<String> set = Sets.of("e1", "e2", "e3", "e4");
assertThat(set).hasSize(4)
.containsExactlyInAnyOrder("e1", "e2", "e3", "e4");
.containsExactly("e1", "e2", "e3", "e4");
assertThat(set.stream()).hasSize(4)
.containsExactly("e1", "e2", "e3", "e4");
assertThatExceptionOfType(UnsupportedOperationException.class).isThrownBy(() -> set.add("a"));
Expand All @@ -92,7 +92,7 @@ public void four() {
public void five() {
Set<String> set = Sets.of("e1", "e2", "e3", "e4", "e5");
assertThat(set).hasSize(5)
.containsExactlyInAnyOrder("e1", "e2", "e3", "e4", "e5");
.containsExactly("e1", "e2", "e3", "e4", "e5");
assertThat(set.stream()).hasSize(5)
.containsExactly("e1", "e2", "e3", "e4", "e5");
assertThatExceptionOfType(UnsupportedOperationException.class).isThrownBy(() -> set.add("a"));
Expand All @@ -105,7 +105,7 @@ public void five() {
public void six() {
Set<String> set = Sets.of("e1", "e2", "e3", "e4", "e5", "e6");
assertThat(set).hasSize(6)
.containsExactlyInAnyOrder("e1", "e2", "e3", "e4", "e5", "e6");
.containsExactly("e1", "e2", "e3", "e4", "e5", "e6");
assertThat(set.stream()).hasSize(6)
.containsExactly("e1", "e2", "e3", "e4", "e5", "e6");
assertThatExceptionOfType(UnsupportedOperationException.class).isThrownBy(() -> set.add("a"));
Expand All @@ -118,7 +118,7 @@ public void six() {
public void seven() {
Set<String> set = Sets.of("e1", "e2", "e3", "e4", "e5", "e6", "e7");
assertThat(set).hasSize(7)
.containsExactlyInAnyOrder("e1", "e2", "e3", "e4", "e5", "e6", "e7");
.containsExactly("e1", "e2", "e3", "e4", "e5", "e6", "e7");
assertThat(set.stream()).hasSize(7)
.containsExactly("e1", "e2", "e3", "e4", "e5", "e6", "e7");
assertThatExceptionOfType(UnsupportedOperationException.class).isThrownBy(() -> set.add("a"));
Expand All @@ -131,7 +131,7 @@ public void seven() {
public void eight() {
Set<String> set = Sets.of("e1", "e2", "e3", "e4", "e5", "e6", "e7", "e8");
assertThat(set).hasSize(8)
.containsExactlyInAnyOrder("e1", "e2", "e3", "e4", "e5", "e6", "e7", "e8");
.containsExactly("e1", "e2", "e3", "e4", "e5", "e6", "e7", "e8");
assertThat(set.stream()).hasSize(8)
.containsExactly("e1", "e2", "e3", "e4", "e5", "e6", "e7", "e8");
assertThatExceptionOfType(UnsupportedOperationException.class).isThrownBy(() -> set.add("a"));
Expand All @@ -144,7 +144,7 @@ public void eight() {
public void nine() {
Set<String> set = Sets.of("e1", "e2", "e3", "e4", "e5", "e6", "e7", "e8", "e9");
assertThat(set).hasSize(9)
.containsExactlyInAnyOrder("e1", "e2", "e3", "e4", "e5", "e6", "e7", "e8", "e9");
.containsExactly("e1", "e2", "e3", "e4", "e5", "e6", "e7", "e8", "e9");
assertThat(set.stream()).hasSize(9)
.containsExactly("e1", "e2", "e3", "e4", "e5", "e6", "e7", "e8", "e9");
assertThatExceptionOfType(UnsupportedOperationException.class).isThrownBy(() -> set.add("a"));
Expand All @@ -157,7 +157,7 @@ public void nine() {
public void ten() {
Set<String> set = Sets.of("e1", "e2", "e3", "e4", "e5", "e6", "e7", "e8", "e9", "e10");
assertThat(set).hasSize(10)
.containsExactlyInAnyOrder("e1", "e2", "e3", "e4", "e5", "e6", "e7", "e8", "e9", "e10");
.containsExactly("e1", "e2", "e3", "e4", "e5", "e6", "e7", "e8", "e9", "e10");
assertThat(set.stream()).hasSize(10)
.containsExactly("e1", "e2", "e3", "e4", "e5", "e6", "e7", "e8", "e9", "e10");
assertThatExceptionOfType(UnsupportedOperationException.class).isThrownBy(() -> set.add("a"));
Expand All @@ -174,7 +174,7 @@ public void entries() {
Set<String> set = Sets.of(entries);
entries[0] = "changed";
assertThat(set).hasSize(11)
.containsExactlyInAnyOrder("e1", "e2", "e3", "e4", "e5", "e6", "e7", "e8", "e9", "e10", "e11");
.containsExactly("e1", "e2", "e3", "e4", "e5", "e6", "e7", "e8", "e9", "e10", "e11");
assertThat(set.stream()).hasSize(11)
.containsExactly("e1", "e2", "e3", "e4", "e5", "e6", "e7", "e8", "e9", "e10", "e11");
assertThatExceptionOfType(UnsupportedOperationException.class).isThrownBy(() -> set.add("a"));
Expand Down Expand Up @@ -209,7 +209,7 @@ public void copy() {
Set<String> set = Sets.copyOf(source);
source.set(0, "changed");
assertThat(set).hasSize(2)
.containsExactlyInAnyOrder("e1", "e2");
.containsExactly("e1", "e2");
assertThat(set.stream()).hasSize(2)
.containsExactly("e1", "e2");
assertThatExceptionOfType(UnsupportedOperationException.class).isThrownBy(() -> set.add("a"));
Expand All @@ -230,7 +230,7 @@ public void array() {
Set<String> source = Sets.of("e1", "e2", "e3", "e4", "e5");
Object[] array = source.toArray();
assertThat(array).hasSize(5)
.containsExactlyInAnyOrder("e1", "e2", "e3", "e4", "e5");
.containsExactly("e1", "e2", "e3", "e4", "e5");
}

@Test
Expand All @@ -240,12 +240,12 @@ public void array_string() {
String[] array = source.toArray(target);
assertThat(array).isNotSameAs(target)
.hasSize(5)
.containsExactlyInAnyOrder("e1", "e2", "e3", "e4", "e5");
.containsExactly("e1", "e2", "e3", "e4", "e5");

target = new String[source.size() + 1];
array = source.toArray(target);
assertThat(array).isSameAs(target)
.containsExactlyInAnyOrder("e1", "e2", "e3", "e4", "e5", null);
.containsExactly("e1", "e2", "e3", "e4", "e5", null);
assertThat(array[target.length - 1]).isNull();
}

Expand Down Expand Up @@ -295,7 +295,7 @@ public void hash_min_value() {

Set<String> set = Sets.of("e1", "polygenelubricants", "GydZG_", "DESIGNING WORKHOUSES", "e5");

assertThat(set).containsExactlyInAnyOrder("e5", "polygenelubricants", "GydZG_", "DESIGNING WORKHOUSES", "e1");
assertThat(set).containsExactly("e1", "polygenelubricants", "GydZG_", "DESIGNING WORKHOUSES", "e5");
}

@Test
Expand Down Expand Up @@ -393,4 +393,23 @@ public void iterator_empty() {
assertThat(holder.set).isFalse();
}

@Test
public void collector() {
List<String> source = new ArrayList<>();
source.add("e1");
source.add("e2");
source.add("e1");
Set<String> set = source.stream()
.collect(Sets.toSet());
source.set(0, "changed");
assertThat(set).hasSize(2)
.containsExactly("e1", "e2");
assertThat(set.stream()).hasSize(2)
.containsExactly("e1", "e2");
assertThatExceptionOfType(UnsupportedOperationException.class).isThrownBy(() -> set.add("a"));
assertThatExceptionOfType(UnsupportedOperationException.class).isThrownBy(() -> set.remove("a"));
assertThatExceptionOfType(UnsupportedOperationException.class).isThrownBy(() -> set.remove("e1"));
assertThatExceptionOfType(UnsupportedOperationException.class).isThrownBy(() -> set.clear());
}

}
8 changes: 4 additions & 4 deletions biz.aQute.bndlib/src/aQute/bnd/osgi/resource/CapReq.java
@@ -1,16 +1,16 @@
package aQute.bnd.osgi.resource;

import static java.util.Collections.unmodifiableMap;
import static java.util.Objects.requireNonNull;

import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

import org.osgi.resource.Capability;
import org.osgi.resource.Requirement;
import org.osgi.resource.Resource;

import aQute.bnd.unmodifiable.Maps;

abstract class CapReq {
private final String namespace;
private final Resource resource;
Expand All @@ -21,8 +21,8 @@ abstract class CapReq {
CapReq(String namespace, Resource resource, Map<String, String> directives, Map<String, Object> attributes) {
this.namespace = requireNonNull(namespace);
this.resource = resource;
this.directives = unmodifiableMap(new HashMap<>(directives));
this.attributes = unmodifiableMap(new HashMap<>(attributes));
this.directives = Maps.copyOf(directives);
this.attributes = new DeferredValueMap<>(Maps.copyOf(attributes));
}

public String getNamespace() {
Expand Down
Expand Up @@ -150,7 +150,14 @@ private boolean isVersion(Object value, Class<?> versionClass) {
}

public CapReqBuilder addAttributes(Map<? extends String, ? extends Object> attributes) {
attributes.forEach(this::addAttribute);
for (Entry<? extends String, ? extends Object> entry : attributes.entrySet()) {
if (entry instanceof DeferredValueEntry) {
DeferredValueEntry<? extends String, ? extends Object> deferred = (DeferredValueEntry<? extends String, ? extends Object>) entry;
addAttribute(deferred.getKey(), deferred.getDeferredValue());
} else {
addAttribute(entry.getKey(), entry.getValue());
}
}
return this;
}

Expand Down
@@ -0,0 +1,19 @@
package aQute.bnd.osgi.resource;

import java.util.function.Supplier;

class DeferredComparableValue<T extends Comparable<T>> extends DeferredValue<T> implements Comparable<T> {

DeferredComparableValue(Class<T> type, Supplier<? extends T> supplier, int hashCode) {
super(type, supplier, hashCode);
}

@SuppressWarnings("unchecked")
@Override
public int compareTo(T o) {
if (o instanceof DeferredComparableValue) {
o = ((DeferredComparableValue<T>) o).get();
}
return get().compareTo(o);
}
}
50 changes: 50 additions & 0 deletions biz.aQute.bndlib/src/aQute/bnd/osgi/resource/DeferredValue.java
@@ -0,0 +1,50 @@
package aQute.bnd.osgi.resource;

import static java.util.Objects.requireNonNull;

import java.util.function.Supplier;

class DeferredValue<T> implements Supplier<T> {
private final Class<T> type;
private final Supplier<? extends T> supplier;
private final int hashCode;
private T value;

DeferredValue(Class<T> type, Supplier<? extends T> supplier, int hashCode) {
this.type = requireNonNull(type);
this.supplier = requireNonNull(supplier);
this.hashCode = hashCode;
}

@Override
public T get() {
T v = value;
if (v == null) {
return value = supplier.get();
}
return v;
}

Class<T> type() {
return type;
}

@Override
public int hashCode() {
return hashCode;
}

@SuppressWarnings("unchecked")
@Override
public boolean equals(Object obj) {
if (obj instanceof DeferredValue) {
obj = ((DeferredValue<T>) obj).get();
}
return get().equals(obj);
}

@Override
public String toString() {
return String.valueOf(get());
}
}