[MNG-8016] Simplify ModelCache (#1377)

The `ModelCache` is now bloated and can be simplified a lot.

---

https://issues.apache.org/jira/browse/MNG-8016
This commit is contained in:
Guillaume Nodet 2024-01-13 14:02:40 +01:00 committed by GitHub
parent 0d046da6f1
commit 7f70467aa3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 29 additions and 214 deletions

View File

@ -118,14 +118,8 @@ under the License.
<exclude>org.apache.maven.model.building.DefaultModelProcessor#setModelLocator(org.apache.maven.model.locator.ModelLocator):METHOD_REMOVED</exclude>
<exclude>org.apache.maven.model.building.DefaultModelProcessor#setModelReader(org.apache.maven.model.io.ModelReader):METHOD_REMOVED</exclude>
<exclude>org.apache.maven.model.building.DefaultModelProcessor#DefaultModelProcessor():CONSTRUCTOR_REMOVED</exclude>
<exclude>org.apache.maven.model.building.ModelCache#get(org.apache.maven.building.Source,java.lang.String):METHOD_NEW_DEFAULT</exclude>
<exclude>org.apache.maven.model.building.ModelCache#get(org.apache.maven.building.Source,org.apache.maven.model.building.ModelCacheTag):METHOD_NEW_DEFAULT</exclude>
<exclude>org.apache.maven.model.building.ModelCache#get(java.lang.String,java.lang.String,java.lang.String,org.apache.maven.model.building.ModelCacheTag):METHOD_NEW_DEFAULT</exclude>
<exclude>org.apache.maven.model.building.ModelCache#put(org.apache.maven.building.Source,java.lang.String,java.lang.Object):METHOD_NEW_DEFAULT</exclude>
<exclude>org.apache.maven.model.building.ModelCache#put(org.apache.maven.building.Source,org.apache.maven.model.building.ModelCacheTag,java.lang.Object):METHOD_NEW_DEFAULT</exclude>
<exclude>org.apache.maven.model.building.ModelCache#put(java.lang.String,java.lang.String,java.lang.String,org.apache.maven.model.building.ModelCacheTag,java.lang.Object):METHOD_NEW_DEFAULT</exclude>
<exclude>org.apache.maven.model.building.ModelCache#computeIfAbsent(java.lang.String,java.lang.String,java.lang.String,org.apache.maven.model.building.ModelCacheTag,java.util.function.Supplier):METHOD_NEW_DEFAULT</exclude>
<exclude>org.apache.maven.model.building.ModelCache#computeIfAbsent(org.apache.maven.building.Source,org.apache.maven.model.building.ModelCacheTag,java.util.function.Supplier):METHOD_NEW_DEFAULT</exclude>
<exclude>org.apache.maven.model.building.ModelCache#get(java.lang.String,java.lang.String,java.lang.String,java.lang.String):METHOD_REMOVED</exclude>
<exclude>org.apache.maven.model.building.ModelCache#put(java.lang.String,java.lang.String,java.lang.String,java.lang.String,java.lang.Object):METHOD_REMOVED</exclude>
<exclude>org.apache.maven.model.composition.DependencyManagementImporter#importManagement(org.apache.maven.model.Model,java.util.List,org.apache.maven.model.building.ModelBuildingRequest,org.apache.maven.model.building.ModelProblemCollector):METHOD_REMOVED</exclude>
<exclude>org.apache.maven.model.composition.DefaultDependencyManagementImporter#importManagement(org.apache.maven.model.Model,java.util.List,org.apache.maven.model.building.ModelBuildingRequest,org.apache.maven.model.building.ModelProblemCollector):METHOD_REMOVED</exclude>
<exclude>org.apache.maven.model.inheritance.DefaultInheritanceAssembler</exclude>

View File

@ -1870,11 +1870,11 @@ public class DefaultModelBuilder implements ModelBuilder {
String version,
ModelCacheTag<T> tag,
Callable<T> supplier) {
return doWithCache(cache, supplier, s -> cache.computeIfAbsent(groupId, artifactId, version, tag, s));
return doWithCache(cache, supplier, s -> cache.computeIfAbsent(groupId, artifactId, version, tag.getName(), s));
}
private static <T> T cache(ModelCache cache, Source source, ModelCacheTag<T> tag, Callable<T> supplier) {
return doWithCache(cache, supplier, s -> cache.computeIfAbsent(source, tag, s));
return doWithCache(cache, supplier, s -> cache.computeIfAbsent(source, tag.getName(), s));
}
private static <T> T doWithCache(

View File

@ -26,122 +26,13 @@ import org.apache.maven.building.Source;
* Caches auxiliary data used during model building like already processed raw/effective models. The data in the cache
* is meant for exclusive consumption by the model builder and is opaque to the cache implementation. The cache key is
* formed by a combination of group id, artifact id, version and tag. The first three components generally refer to the
* identify of a model. The tag allows for further classification of the associated data on the sole discretion of the
* identity of a model. The tag allows for further classification of the associated data on the sole discretion of the
* model builder.
*
*/
public interface ModelCache {
/**
* Puts the specified data into the cache.
*
* @param path The path of the cache record, must not be {@code null}.
* @param tag The tag of the cache record, must not be {@code null}.
* @param data The data to store in the cache, must not be {@code null}.
* @since 4.0.0
*/
default void put(Source path, String tag, Object data) {
// only useful for ReactorModelCache
}
/**
* Gets the specified data from the cache.
*
* @param path The path of the cache record, must not be {@code null}.
* @param tag The tag of the cache record, must not be {@code null}.
* @return The requested data or {@code null} if none was present in the cache.
* @since 4.0.0
*/
default Object get(Source path, String tag) {
// only useful for ReactorModelCache
return null;
}
<T> T computeIfAbsent(String groupId, String artifactId, String version, String tag, Supplier<Supplier<T>> data);
/**
* Puts the specified data into the cache.
*
* @param groupId The group id of the cache record, must not be {@code null}.
* @param artifactId The artifact id of the cache record, must not be {@code null}.
* @param version The version of the cache record, must not be {@code null}.
* @param tag The tag of the cache record, must not be {@code null}.
* @param data The data to store in the cache, must not be {@code null}.
*/
void put(String groupId, String artifactId, String version, String tag, Object data);
/**
* Gets the specified data from the cache.
*
* @param groupId The group id of the cache record, must not be {@code null}.
* @param artifactId The artifact id of the cache record, must not be {@code null}.
* @param version The version of the cache record, must not be {@code null}.
* @param tag The tag of the cache record, must not be {@code null}.
* @return The requested data or {@code null} if none was present in the cache.
*/
Object get(String groupId, String artifactId, String version, String tag);
/**
* Puts the specified data into the cache.
*
* @param path The path of the cache record, must not be {@code null}.
* @param tag The tag of the cache record, must not be {@code null}.
* @param data The data to store in the cache, must not be {@code null}.
* @since 4.0.0
*/
default <T> void put(Source path, ModelCacheTag<T> tag, T data) {
put(path, tag.getName(), tag.intoCache(data));
}
/**
* Gets the specified data from the cache.
*
* @param path The path of the cache record, must not be {@code null}.
* @param tag The tag of the cache record, must not be {@code null}.
* @return The requested data or {@code null} if none was present in the cache.
* @since 4.0.0
*/
default <T> T get(Source path, ModelCacheTag<T> tag) {
Object obj = get(path, tag.getName());
return (obj != null) ? tag.fromCache(tag.getType().cast(obj)) : null;
}
/**
* Puts the specified data into the cache.
*
* @param groupId The group id of the cache record, must not be {@code null}.
* @param artifactId The artifact id of the cache record, must not be {@code null}.
* @param version The version of the cache record, must not be {@code null}.
* @param tag The tag of the cache record, must not be {@code null}.
* @param data The data to store in the cache, must not be {@code null}.
*/
default <T> void put(String groupId, String artifactId, String version, ModelCacheTag<T> tag, T data) {
put(groupId, artifactId, version, tag.getName(), tag.intoCache(data));
}
/**
* Gets the specified data from the cache.
*
* @param groupId The group id of the cache record, must not be {@code null}.
* @param artifactId The artifact id of the cache record, must not be {@code null}.
* @param version The version of the cache record, must not be {@code null}.
* @param tag The tag of the cache record, must not be {@code null}.
* @return The requested data or {@code null} if none was present in the cache.
*/
default <T> T get(String groupId, String artifactId, String version, ModelCacheTag<T> tag) {
Object obj = get(groupId, artifactId, version, tag.getName());
return (obj != null) ? tag.fromCache(tag.getType().cast(obj)) : null;
}
default <T> T computeIfAbsent(
String groupId, String artifactId, String version, ModelCacheTag<T> tag, Supplier<Supplier<T>> data) {
Object obj = computeIfAbsent(groupId, artifactId, version, tag.getName(), (Supplier) data);
return (obj != null) ? tag.fromCache(tag.getType().cast(obj)) : null;
}
default <T> T computeIfAbsent(Source path, ModelCacheTag<T> tag, Supplier<Supplier<T>> data) {
Object obj = computeIfAbsent(path, tag.getName(), (Supplier) data);
return (obj != null) ? tag.fromCache(tag.getType().cast(obj)) : null;
}
Object computeIfAbsent(String groupId, String artifactId, String version, String tag, Supplier<Supplier<?>> data);
Object computeIfAbsent(Source path, String tag, Supplier<Supplier<?>> data);
<T> T computeIfAbsent(Source path, String tag, Supplier<Supplier<T>> data);
}

View File

@ -43,24 +43,6 @@ interface ModelCacheTag<T> {
*/
Class<T> getType();
/**
* Creates a copy of the data suitable for storage in the cache. The original data to store can be mutated after the
* cache is populated but the state of the cache must not change so we need to make a copy.
*
* @param data The data to store in the cache, must not be {@code null}.
* @return The data being stored in the cache, never {@code null}.
*/
T intoCache(T data);
/**
* Creates a copy of the data suitable for retrieval from the cache. The retrieved data can be mutated after the
* cache is queried but the state of the cache must not change so we need to make a copy.
*
* @param data The data to retrieve from the cache, must not be {@code null}.
* @return The data being retrieved from the cache, never {@code null}.
*/
T fromCache(T data);
/**
* The tag used for the raw model without profile activation
*/
@ -75,16 +57,6 @@ interface ModelCacheTag<T> {
public Class<ModelData> getType() {
return ModelData.class;
}
@Override
public ModelData intoCache(ModelData data) {
return data;
}
@Override
public ModelData fromCache(ModelData data) {
return data;
}
};
/**
@ -101,16 +73,6 @@ interface ModelCacheTag<T> {
public Class<DependencyManagement> getType() {
return DependencyManagement.class;
}
@Override
public DependencyManagement intoCache(DependencyManagement data) {
return data;
}
@Override
public DependencyManagement fromCache(DependencyManagement data) {
return data;
}
};
/**
@ -127,15 +89,5 @@ interface ModelCacheTag<T> {
public Class<Model> getType() {
return Model.class;
}
@Override
public Model intoCache(Model data) {
return data;
}
@Override
public Model fromCache(Model data) {
return data;
}
};
}

View File

@ -18,79 +18,57 @@
*/
package org.apache.maven.repository.internal;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.function.Supplier;
import org.apache.maven.building.Source;
import org.apache.maven.model.building.ModelCache;
import org.eclipse.aether.RepositoryCache;
import org.eclipse.aether.RepositorySystemSession;
import static java.util.Objects.requireNonNull;
/**
* A model builder cache backed by the repository system cache.
*
*/
public class DefaultModelCache implements ModelCache {
private static final String KEY = DefaultModelCache.class.getName();
private final Map<Object, Supplier<?>> cache;
@SuppressWarnings("unchecked")
public static ModelCache newInstance(RepositorySystemSession session) {
Map<Object, Supplier<?>> cache;
if (session.getCache() == null) {
ConcurrentHashMap<Object, Supplier<?>> cache;
RepositoryCache repositoryCache = session.getCache();
if (repositoryCache == null) {
cache = new ConcurrentHashMap<>();
} else {
cache = (Map) session.getCache().get(session, KEY);
if (cache == null) {
cache = new ConcurrentHashMap<>();
session.getCache().put(session, KEY, cache);
}
cache = (ConcurrentHashMap<Object, Supplier<?>>)
repositoryCache.computeIfAbsent(session, KEY, ConcurrentHashMap::new);
}
return new DefaultModelCache(cache);
}
private DefaultModelCache(Map<Object, Supplier<?>> cache) {
this.cache = cache;
}
private final ConcurrentMap<Object, Supplier<?>> cache;
public Object get(Source path, String tag) {
return get(new SourceCacheKey(path, tag));
}
public void put(Source path, String tag, Object data) {
put(new SourceCacheKey(path, tag), data);
private DefaultModelCache(ConcurrentMap<Object, Supplier<?>> cache) {
this.cache = requireNonNull(cache);
}
@Override
public Object get(String groupId, String artifactId, String version, String tag) {
return get(new GavCacheKey(groupId, artifactId, version, tag));
@SuppressWarnings({"unchecked", "rawtypes"})
public <T> T computeIfAbsent(
String groupId, String artifactId, String version, String tag, Supplier<Supplier<T>> data) {
Object obj = computeIfAbsent(new GavCacheKey(groupId, artifactId, version, tag), (Supplier) data);
return (T) obj;
}
@Override
public void put(String groupId, String artifactId, String version, String tag, Object data) {
put(new GavCacheKey(groupId, artifactId, version, tag), data);
}
protected Object get(Object key) {
Supplier<?> s = cache.get(key);
return s != null ? s.get() : null;
}
protected void put(Object key, Object data) {
cache.put(key, () -> data);
}
@Override
public Object computeIfAbsent(
String groupId, String artifactId, String version, String tag, Supplier<Supplier<?>> data) {
return computeIfAbsent(new GavCacheKey(groupId, artifactId, version, tag), data);
}
@Override
public Object computeIfAbsent(Source path, String tag, Supplier<Supplier<?>> data) {
return computeIfAbsent(new SourceCacheKey(path, tag), data);
@SuppressWarnings({"unchecked", "rawtypes"})
public <T> T computeIfAbsent(Source path, String tag, Supplier<Supplier<T>> data) {
Object obj = computeIfAbsent(new SourceCacheKey(path, tag), (Supplier) data);
return (T) obj;
}
protected Object computeIfAbsent(Object key, Supplier<Supplier<?>> data) {