Skip to content

Commit

Permalink
[MNG-8016] Simplify ModelCache (#1377)
Browse files Browse the repository at this point in the history
The `ModelCache` is now bloated and can be simplified a lot.

---

https://issues.apache.org/jira/browse/MNG-8016
  • Loading branch information
gnodet committed Jan 13, 2024
1 parent 0d046da commit 7f70467
Show file tree
Hide file tree
Showing 5 changed files with 29 additions and 214 deletions.
10 changes: 2 additions & 8 deletions maven-model-builder/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1870,11 +1870,11 @@ private static <T> T cache(
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(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,122 +26,13 @@
* 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);
}
Original file line number Diff line number Diff line change
Expand Up @@ -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
*/
Expand All @@ -75,16 +57,6 @@ public String getName() {
public Class<ModelData> getType() {
return ModelData.class;
}

@Override
public ModelData intoCache(ModelData data) {
return data;
}

@Override
public ModelData fromCache(ModelData data) {
return data;
}
};

/**
Expand All @@ -101,16 +73,6 @@ public String getName() {
public Class<DependencyManagement> getType() {
return DependencyManagement.class;
}

@Override
public DependencyManagement intoCache(DependencyManagement data) {
return data;
}

@Override
public DependencyManagement fromCache(DependencyManagement data) {
return data;
}
};

/**
Expand All @@ -127,15 +89,5 @@ public String getName() {
public Class<Model> getType() {
return Model.class;
}

@Override
public Model intoCache(Model data) {
return data;
}

@Override
public Model fromCache(Model data) {
return data;
}
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

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);
}

@Override
public Object get(String groupId, String artifactId, String version, String tag) {
return get(new GavCacheKey(groupId, artifactId, version, tag));
}

@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;
}
private final ConcurrentMap<Object, Supplier<?>> cache;

protected void put(Object key, Object data) {
cache.put(key, () -> data);
private DefaultModelCache(ConcurrentMap<Object, Supplier<?>> cache) {
this.cache = requireNonNull(cache);
}

@Override
public Object computeIfAbsent(
String groupId, String artifactId, String version, String tag, Supplier<Supplier<?>> data) {
return computeIfAbsent(new GavCacheKey(groupId, artifactId, version, tag), data);
@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 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) {
Expand Down

0 comments on commit 7f70467

Please sign in to comment.