Skip to content

Commit 51bcd9b

Browse files
committed
bugfix for MMap with List value usage.(also performance related)
1 parent 201a1ca commit 51bcd9b

File tree

2 files changed

+72
-8
lines changed

2 files changed

+72
-8
lines changed

maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/manager/AbstractDependencyManager.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -151,23 +151,23 @@ public DependencyManager deriveChildManager(DependencyCollectionContext context)
151151
String version = artifact.getVersion();
152152
if (!version.isEmpty() && !managedVersions.containsKey(key)) {
153153
if (managedVersions == this.managedVersions) {
154-
managedVersions = MMap.copy(this.managedVersions);
154+
managedVersions = MMap.append(this.managedVersions);
155155
}
156156
managedVersions.put(key, new Holder<>(depth, version));
157157
}
158158

159159
String scope = managedDependency.getScope();
160160
if (!scope.isEmpty() && !managedScopes.containsKey(key)) {
161161
if (managedScopes == this.managedScopes) {
162-
managedScopes = MMap.copy(this.managedScopes);
162+
managedScopes = MMap.append(this.managedScopes);
163163
}
164164
managedScopes.put(key, new Holder<>(depth, scope));
165165
}
166166

167167
Boolean optional = managedDependency.getOptional();
168168
if (optional != null && !managedOptionals.containsKey(key)) {
169169
if (managedOptionals == this.managedOptionals) {
170-
managedOptionals = MMap.copy(this.managedOptionals);
170+
managedOptionals = MMap.append(this.managedOptionals);
171171
}
172172
managedOptionals.put(key, new Holder<>(depth, optional));
173173
}
@@ -177,15 +177,15 @@ public DependencyManager deriveChildManager(DependencyCollectionContext context)
177177
: systemDependencyScope.getSystemPath(managedDependency.getArtifact());
178178
if (localPath != null && !managedLocalPaths.containsKey(key)) {
179179
if (managedLocalPaths == this.managedLocalPaths) {
180-
managedLocalPaths = MMap.copy(this.managedLocalPaths);
180+
managedLocalPaths = MMap.append(this.managedLocalPaths);
181181
}
182182
managedLocalPaths.put(key, new Holder<>(depth, localPath));
183183
}
184184

185185
Collection<Exclusion> exclusions = managedDependency.getExclusions();
186186
if (!exclusions.isEmpty()) {
187187
if (managedExclusions == this.managedExclusions) {
188-
managedExclusions = MMap.copy(this.managedExclusions);
188+
managedExclusions = MMap.copyWithListValue(this.managedExclusions);
189189
}
190190
Collection<Holder<Collection<Exclusion>>> managed = managedExclusions.get(key);
191191
if (managed == null) {

maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/manager/MMap.java

Lines changed: 67 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,11 @@
1818
*/
1919
package org.eclipse.aether.util.graph.manager;
2020

21+
import java.util.ArrayList;
22+
import java.util.Collection;
2123
import java.util.HashMap;
24+
import java.util.Map;
25+
import java.util.Objects;
2226

2327
/**
2428
* Warning: this is a special map-like construct that suits only and should be used only in this package!
@@ -47,6 +51,18 @@ public static <K, V> MMap<K, V> copy(MMap<K, V> orig) {
4751
return new MMap<>(new HashMap<>(orig.delegate));
4852
}
4953

54+
public static <K, V> MMap<K, Collection<V>> copyWithListValue(MMap<K, Collection<V>> orig) {
55+
HashMap<K, Collection<V>> newMap = new HashMap<>((int) Math.ceil(orig.size() / 0.75D));
56+
for (Map.Entry<K, Collection<V>> entry : orig.delegate.entrySet()) {
57+
newMap.put(entry.getKey(), entry.getValue() == null ? null : new ArrayList<>(entry.getValue()));
58+
}
59+
return new MMap<>(newMap);
60+
}
61+
62+
public static <K, V> MMap<K, V> append(MMap<K, V> orig) {
63+
return new AppendMMap<>(orig);
64+
}
65+
5066
protected final HashMap<K, V> delegate;
5167

5268
private MMap(HashMap<K, V> delegate) {
@@ -69,6 +85,10 @@ public MMap<K, V> done() {
6985
return new DoneMMap<>(delegate);
7086
}
7187

88+
public MMap<K, V> append() {
89+
return new AppendMMap<>(this);
90+
}
91+
7292
@Override
7393
public int hashCode() {
7494
throw new IllegalStateException("MMap is not done yet");
@@ -79,12 +99,20 @@ public boolean equals(Object o) {
7999
throw new IllegalStateException("MMap is not done yet");
80100
}
81101

102+
public int size() {
103+
return delegate.size();
104+
}
105+
82106
private static class DoneMMap<K, V> extends MMap<K, V> {
83-
private final int hashCode;
107+
volatile long hashCode = Long.MAX_VALUE;
84108

85109
private DoneMMap(HashMap<K, V> delegate) {
86110
super(delegate);
87-
this.hashCode = delegate.hashCode();
111+
}
112+
113+
private DoneMMap(HashMap<K, V> delegate, long hashCode) {
114+
super(delegate);
115+
this.hashCode = hashCode;
88116
}
89117

90118
@Override
@@ -99,7 +127,12 @@ public MMap<K, V> done() {
99127

100128
@Override
101129
public int hashCode() {
102-
return hashCode;
130+
if (this.hashCode != Long.MAX_VALUE) {
131+
return (int) hashCode;
132+
}
133+
int result = delegate.hashCode();
134+
this.hashCode = result;
135+
return result;
103136
}
104137

105138
@Override
@@ -111,4 +144,35 @@ public boolean equals(Object o) {
111144
return delegate.equals(other.delegate);
112145
}
113146
}
147+
148+
private static class AppendMMap<K, V> extends DoneMMap<K, V> {
149+
150+
AppendMMap(MMap<K, V> orig) {
151+
super(new HashMap<>(orig.delegate));
152+
if (orig instanceof DoneMMap) {
153+
this.hashCode = ((DoneMMap<K, V>) orig).hashCode;
154+
} else {
155+
this.hashCode = Long.MAX_VALUE;
156+
}
157+
}
158+
159+
@Override
160+
public V put(K key, V value) {
161+
boolean ifPresent = delegate.containsKey(key);
162+
V originalValue = delegate.put(key, value);
163+
if (hashCode != Long.MAX_VALUE) {
164+
int keyHash = Objects.hashCode(key);
165+
if (ifPresent) {
166+
hashCode -= keyHash ^ Objects.hashCode(originalValue);
167+
}
168+
hashCode += keyHash ^ Objects.hashCode(value);
169+
}
170+
return originalValue;
171+
}
172+
173+
@Override
174+
public MMap<K, V> done() {
175+
return new DoneMMap<>(delegate, hashCode);
176+
}
177+
}
114178
}

0 commit comments

Comments
 (0)