Skip to content

Commit 7907f20

Browse files
authored
[MRESOLVER-420] Cache prioritized components (#348)
Cache them, as creating of those is not cheap, but detect (dynamic injected) map changes. Allow users to disable this feature, in case of fire. --- https://issues.apache.org/jira/browse/MRESOLVER-420
1 parent 9bf157c commit 7907f20

File tree

10 files changed

+62
-26
lines changed

10 files changed

+62
-26
lines changed

maven-resolver-api/src/main/java/org/eclipse/aether/ConfigurationProperties.java

+15
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,21 @@ public final class ConfigurationProperties {
5555
*/
5656
public static final boolean DEFAULT_IMPLICIT_PRIORITIES = false;
5757

58+
/**
59+
* A flag indicating whether the created ordered components should be cached or not.
60+
*
61+
* @see #DEFAULT_CACHED_PRIORITIES
62+
* @since TBD
63+
*/
64+
public static final String CACHED_PRIORITIES = PREFIX_PRIORITY + "cached";
65+
66+
/**
67+
* The default caching of priority components if {@link #CACHED_PRIORITIES} isn't set. Default value is {@code true}.
68+
*
69+
* @since TBD
70+
*/
71+
public static final boolean DEFAULT_CACHED_PRIORITIES = true;
72+
5873
/**
5974
* A flag indicating whether interaction with the user is allowed.
6075
*

maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultDeployer.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,7 @@ private DeployResult deploy(SyncContext syncContext, RepositorySystemSession ses
234234
private List<? extends MetadataGenerator> getMetadataGenerators(
235235
RepositorySystemSession session, DeployRequest request) {
236236
PrioritizedComponents<MetadataGeneratorFactory> factories =
237-
Utils.sortMetadataGeneratorFactories(session, this.metadataFactories.values());
237+
Utils.sortMetadataGeneratorFactories(session, metadataFactories);
238238

239239
List<MetadataGenerator> generators = new ArrayList<>();
240240

maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultInstaller.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ private InstallResult install(SyncContext syncContext, RepositorySystemSession s
151151
private List<? extends MetadataGenerator> getMetadataGenerators(
152152
RepositorySystemSession session, InstallRequest request) {
153153
PrioritizedComponents<MetadataGeneratorFactory> factories =
154-
Utils.sortMetadataGeneratorFactories(session, this.metadataFactories.values());
154+
Utils.sortMetadataGeneratorFactories(session, metadataFactories);
155155

156156
List<MetadataGenerator> generators = new ArrayList<>();
157157

maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultLocalRepositoryProvider.java

+3-4
Original file line numberDiff line numberDiff line change
@@ -58,10 +58,9 @@ public LocalRepositoryManager newLocalRepositoryManager(RepositorySystemSession
5858
throws NoLocalRepositoryManagerException {
5959
requireNonNull(session, "session cannot be null");
6060
requireNonNull(repository, "repository cannot be null");
61-
PrioritizedComponents<LocalRepositoryManagerFactory> factories = new PrioritizedComponents<>(session);
62-
for (LocalRepositoryManagerFactory factory : this.localRepositoryManagerFactories.values()) {
63-
factories.add(factory, factory.getPriority());
64-
}
61+
62+
PrioritizedComponents<LocalRepositoryManagerFactory> factories = PrioritizedComponents.reuseOrCreate(
63+
session, localRepositoryManagerFactories, LocalRepositoryManagerFactory::getPriority);
6564

6665
List<NoLocalRepositoryManagerException> errors = new ArrayList<>();
6766
for (PrioritizedComponent<LocalRepositoryManagerFactory> factory : factories.getEnabled()) {

maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultRepositoryConnectorProvider.java

+3-6
Original file line numberDiff line numberDiff line change
@@ -77,13 +77,10 @@ public RepositoryConnector newRepositoryConnector(RepositorySystemSession sessio
7777
}
7878
}
7979

80-
RemoteRepositoryFilter filter = remoteRepositoryFilterManager.getRemoteRepositoryFilter(session);
81-
82-
PrioritizedComponents<RepositoryConnectorFactory> factories = new PrioritizedComponents<>(session);
83-
for (RepositoryConnectorFactory factory : this.connectorFactories.values()) {
84-
factories.add(factory, factory.getPriority());
85-
}
80+
PrioritizedComponents<RepositoryConnectorFactory> factories = PrioritizedComponents.reuseOrCreate(
81+
session, connectorFactories, RepositoryConnectorFactory::getPriority);
8682

83+
RemoteRepositoryFilter filter = remoteRepositoryFilterManager.getRemoteRepositoryFilter(session);
8784
List<NoRepositoryConnectorException> errors = new ArrayList<>();
8885
for (PrioritizedComponent<RepositoryConnectorFactory> factory : factories.getEnabled()) {
8986
try {

maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultRepositoryLayoutProvider.java

+2-4
Original file line numberDiff line numberDiff line change
@@ -59,10 +59,8 @@ public RepositoryLayout newRepositoryLayout(RepositorySystemSession session, Rem
5959
requireNonNull(session, "session cannot be null");
6060
requireNonNull(repository, "remote repository cannot be null");
6161

62-
PrioritizedComponents<RepositoryLayoutFactory> factories = new PrioritizedComponents<>(session);
63-
for (RepositoryLayoutFactory factory : this.layoutFactories.values()) {
64-
factories.add(factory, factory.getPriority());
65-
}
62+
PrioritizedComponents<RepositoryLayoutFactory> factories =
63+
PrioritizedComponents.reuseOrCreate(session, layoutFactories, RepositoryLayoutFactory::getPriority);
6664

6765
List<NoRepositoryLayoutException> errors = new ArrayList<>();
6866
for (PrioritizedComponent<RepositoryLayoutFactory> factory : factories.getEnabled()) {

maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultTransporterProvider.java

+2-4
Original file line numberDiff line numberDiff line change
@@ -59,10 +59,8 @@ public Transporter newTransporter(RepositorySystemSession session, RemoteReposit
5959
requireNonNull(session, "session cannot be null");
6060
requireNonNull(repository, "repository cannot be null");
6161

62-
PrioritizedComponents<TransporterFactory> factories = new PrioritizedComponents<>(session);
63-
for (TransporterFactory factory : this.transporterFactories.values()) {
64-
factories.add(factory, factory.getPriority());
65-
}
62+
PrioritizedComponents<TransporterFactory> factories =
63+
PrioritizedComponents.reuseOrCreate(session, transporterFactories, TransporterFactory::getPriority);
6664

6765
List<NoTransporterException> errors = new ArrayList<>();
6866
for (PrioritizedComponent<TransporterFactory> factory : factories.getEnabled()) {

maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/PrioritizedComponents.java

+31
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import java.util.Collections;
2323
import java.util.List;
2424
import java.util.Map;
25+
import java.util.function.Function;
2526

2627
import org.eclipse.aether.ConfigurationProperties;
2728
import org.eclipse.aether.RepositorySystemSession;
@@ -31,6 +32,36 @@
3132
* Helps to sort pluggable components by their priority.
3233
*/
3334
final class PrioritizedComponents<T> {
35+
/**
36+
* Reuses or creates and stores (if session data does not contain yet) prioritized components under this key into
37+
* given session. Same session is used to configure prioritized components.
38+
* <p>
39+
* The {@code components} are expected to be Sisu injected {@link Map<String, C>}-like component maps. There is a
40+
* simple "change detection" in place, as injected maps are dynamic, they are atomically expanded or contracted
41+
* as components are dynamically discovered or unloaded.
42+
*
43+
* @since TBD
44+
*/
45+
@SuppressWarnings("unchecked")
46+
public static <C> PrioritizedComponents<C> reuseOrCreate(
47+
RepositorySystemSession session, Map<String, C> components, Function<C, Float> priorityFunction) {
48+
boolean cached = ConfigUtils.getBoolean(
49+
session, ConfigurationProperties.DEFAULT_CACHED_PRIORITIES, ConfigurationProperties.CACHED_PRIORITIES);
50+
if (cached) {
51+
String key = PrioritizedComponents.class.getName() + ".pc" + Integer.toHexString(components.hashCode());
52+
return (PrioritizedComponents<C>)
53+
session.getData().computeIfAbsent(key, () -> create(session, components, priorityFunction));
54+
} else {
55+
return create(session, components, priorityFunction);
56+
}
57+
}
58+
59+
private static <C> PrioritizedComponents<C> create(
60+
RepositorySystemSession session, Map<String, C> components, Function<C, Float> priorityFunction) {
61+
PrioritizedComponents<C> newInstance = new PrioritizedComponents<>(session);
62+
components.values().forEach(c -> newInstance.add(c, priorityFunction.apply(c)));
63+
return newInstance;
64+
}
3465

3566
private static final String FACTORY_SUFFIX = "Factory";
3667

maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/Utils.java

+3-6
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import java.util.ArrayList;
2222
import java.util.Collection;
2323
import java.util.List;
24+
import java.util.Map;
2425

2526
import org.eclipse.aether.RepositorySystemSession;
2627
import org.eclipse.aether.artifact.Artifact;
@@ -39,12 +40,8 @@
3940
final class Utils {
4041

4142
public static PrioritizedComponents<MetadataGeneratorFactory> sortMetadataGeneratorFactories(
42-
RepositorySystemSession session, Collection<? extends MetadataGeneratorFactory> factories) {
43-
PrioritizedComponents<MetadataGeneratorFactory> result = new PrioritizedComponents<>(session);
44-
for (MetadataGeneratorFactory factory : factories) {
45-
result.add(factory, factory.getPriority());
46-
}
47-
return result;
43+
RepositorySystemSession session, Map<String, MetadataGeneratorFactory> factories) {
44+
return PrioritizedComponents.reuseOrCreate(session, factories, MetadataGeneratorFactory::getPriority);
4845
}
4946

5047
public static List<Metadata> prepareMetadata(

src/site/markdown/configuration.md

+1
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ Option | Type | Description | Default Value | Supports Repo ID Suffix
8585
`aether.metadataResolver.threads` | int | Number of threads to use in parallel for resolving metadata. | `4` | no
8686
`aether.offline.protocols` | String | Comma-separated list of protocols which are supposed to be resolved offline. | - | no
8787
`aether.offline.hosts` | String | Comma-separated list of hosts which are supposed to be resolved offline. | - | no
88+
`aether.priority.cached` | boolean | Whether the created ordered list of components should be cached (in session) or not. | `true` | no
8889
`aether.priority.<class>` | float | The priority to use for a certain extension class. `class` can either be the fully qualified name or the simple name stands for fully qualified class name. If the class name ends with `Factory` that suffix could optionally be left out. | - | no
8990
`aether.priority.implicit` | boolean | Flag indicating whether the priorities of pluggable extensions are implicitly given by their iteration order such that the first extension has the highest priority. If set, an extension's built-in priority as well as any corresponding `aether.priority.<class>` configuration properties are ignored when searching for a suitable implementation among the available extensions. This priority mode is meant for cases where the application will present/inject extensions in the desired search order. | `false` | no
9091
`aether.remoteRepositoryFilter.groupId` | boolean | Enable `groupId` remote repository filter. | `false` | no

0 commit comments

Comments
 (0)