Skip to content

Commit aa3945e

Browse files
authored
[MRESOLVER-377] Introduce metadataUpdatePolicy (#308)
Split the policies applied in case of data and metadata, allowing greater control of their updates. Still, work "as before" in case of applications that migrate from 1.x resolver (they should receive no behavior change). The crux of this change is really just to introduce two policies (to co-exist in parallel), but if application using resolver decides to use same policy for both, the original behavior of resolver returns and will seemingly behave as before (ie. like 1.9.x does). Maven relies on metadata in these cases ONLY: * resolving maven plugin prefix to maven plugin groupId (G level md) * resolving snapshot version to timestamped version (V level md) Resolver OTOH provides one more use case: * "discovery" of existing versions for given GA (this use case is NOT used in Maven Core) (A level md) Now, while Maven Core itself does NOT use 3rd use case, some plugins does, most notably the versions-maven-plugin. Today, everyone on Earth use this plugin along with `-U` Maven switch to pick up new stuff from remote repository, but this is total overkill, as it refreshes _everything_ (yes, even the immutable release artifacts!). The `-U` is simply a "must", to make Maven "refresh metadata" (as well, along with all the Artifacts) to pick up new versions on remote. Versions plugin did implement a ["hack" to overcome this limitation](mojohaus/versions@82e2450), that is still a hack, as it still applies to everything. Proper solution is to have means to express `-U but for metadata only`. This PR makes this possible on resolver side. --- https://issues.apache.org/jira/browse/MRESOLVER-377
1 parent 0b919cd commit aa3945e

File tree

10 files changed

+155
-26
lines changed

10 files changed

+155
-26
lines changed

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,11 @@ public String getUpdatePolicy() {
8787
return getSession().getUpdatePolicy();
8888
}
8989

90+
@Override
91+
public String getMetadataUpdatePolicy() {
92+
return getSession().getMetadataUpdatePolicy();
93+
}
94+
9095
@Override
9196
public LocalRepository getLocalRepository() {
9297
return getSession().getLocalRepository();

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

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,8 @@ public final class DefaultRepositorySystemSession implements RepositorySystemSes
7373

7474
private String updatePolicy;
7575

76+
private String metadataUpdatePolicy;
77+
7678
private LocalRepositoryManager localRepositoryManager;
7779

7880
private FileTransformerManager fileTransformerManager;
@@ -154,6 +156,7 @@ public DefaultRepositorySystemSession(RepositorySystemSession session) {
154156
setArtifactDescriptorPolicy(session.getArtifactDescriptorPolicy());
155157
setChecksumPolicy(session.getChecksumPolicy());
156158
setUpdatePolicy(session.getUpdatePolicy());
159+
setMetadataUpdatePolicy(session.getMetadataUpdatePolicy());
157160
setLocalRepositoryManager(session.getLocalRepositoryManager());
158161
setWorkspaceReader(session.getWorkspaceReader());
159162
setRepositoryListener(session.getRepositoryListener());
@@ -293,6 +296,28 @@ public DefaultRepositorySystemSession setUpdatePolicy(String updatePolicy) {
293296
return this;
294297
}
295298

299+
@Override
300+
public String getMetadataUpdatePolicy() {
301+
return metadataUpdatePolicy;
302+
}
303+
304+
/**
305+
* Sets the global metadata update policy. If set, the global update policy overrides the update policies of the remote
306+
* repositories being used for resolution.
307+
*
308+
* @param metadataUpdatePolicy The global update policy, may be {@code null}/empty to apply the per-repository policies.
309+
* @return This session for chaining, never {@code null}.
310+
* @see RepositoryPolicy#UPDATE_POLICY_ALWAYS
311+
* @see RepositoryPolicy#UPDATE_POLICY_DAILY
312+
* @see RepositoryPolicy#UPDATE_POLICY_NEVER
313+
* @since TBD
314+
*/
315+
public DefaultRepositorySystemSession setMetadataUpdatePolicy(String metadataUpdatePolicy) {
316+
verifyStateForMutation();
317+
this.metadataUpdatePolicy = metadataUpdatePolicy;
318+
return this;
319+
}
320+
296321
@Override
297322
public LocalRepository getLocalRepository() {
298323
LocalRepositoryManager lrm = getLocalRepositoryManager();

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

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ public interface RepositorySystemSession {
9494
String getChecksumPolicy();
9595

9696
/**
97-
* Gets the global update policy. If set, the global update policy overrides the update policies of the remote
97+
* Gets the global data update policy. If set, the global update policy overrides the update policies of the remote
9898
* repositories being used for resolution.
9999
*
100100
* @return The global update policy or {@code null}/empty if not set and the per-repository policies apply.
@@ -104,6 +104,18 @@ public interface RepositorySystemSession {
104104
*/
105105
String getUpdatePolicy();
106106

107+
/**
108+
* Gets the global metadata update policy. If set, the global update policy overrides the update policies of the remote
109+
* repositories being used for resolution.
110+
*
111+
* @return The global update policy or {@code null}/empty if not set and the per-repository policies apply.
112+
* @see RepositoryPolicy#UPDATE_POLICY_ALWAYS
113+
* @see RepositoryPolicy#UPDATE_POLICY_DAILY
114+
* @see RepositoryPolicy#UPDATE_POLICY_NEVER
115+
* @since TBD
116+
*/
117+
String getMetadataUpdatePolicy();
118+
107119
/**
108120
* Gets the local repository used during this session. This is a convenience method for
109121
* {@link LocalRepositoryManager#getRepository()}.

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

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -62,26 +62,40 @@ public final class RepositoryPolicy {
6262

6363
private final String updatePolicy;
6464

65+
private final String metadataUpdatePolicy;
66+
6567
private final String checksumPolicy;
6668

6769
/**
6870
* Creates a new policy with checksum warnings and daily update checks.
6971
*/
7072
public RepositoryPolicy() {
71-
this(true, UPDATE_POLICY_DAILY, CHECKSUM_POLICY_WARN);
73+
this(true, UPDATE_POLICY_DAILY, UPDATE_POLICY_DAILY, CHECKSUM_POLICY_WARN);
74+
}
75+
76+
/**
77+
* Creates a new policy with the specified settings (uses same update policy for data and metadata, retains old
78+
* resolver behaviour).
79+
*/
80+
public RepositoryPolicy(boolean enabled, String updatePolicy, String checksumPolicy) {
81+
this(enabled, updatePolicy, updatePolicy, checksumPolicy);
7282
}
7383

7484
/**
7585
* Creates a new policy with the specified settings.
7686
*
7787
* @param enabled A flag whether the associated repository should be accessed or not.
7888
* @param updatePolicy The update interval after which locally cached data from the repository is considered stale
79-
* and should be refetched, may be {@code null}.
89+
* and should be re-fetched, may be {@code null}.
90+
* @param metadataUpdatePolicy The update interval after which locally cached metadata from the repository is considered stale
91+
* and should be re-fetched, may be {@code null}.
8092
* @param checksumPolicy The way checksum verification should be handled, may be {@code null}.
93+
* @since TBD
8194
*/
82-
public RepositoryPolicy(boolean enabled, String updatePolicy, String checksumPolicy) {
95+
public RepositoryPolicy(boolean enabled, String updatePolicy, String metadataUpdatePolicy, String checksumPolicy) {
8396
this.enabled = enabled;
8497
this.updatePolicy = (updatePolicy != null) ? updatePolicy : "";
98+
this.metadataUpdatePolicy = (metadataUpdatePolicy != null) ? metadataUpdatePolicy : "";
8599
this.checksumPolicy = (checksumPolicy != null) ? checksumPolicy : "";
86100
}
87101

@@ -103,6 +117,16 @@ public String getUpdatePolicy() {
103117
return updatePolicy;
104118
}
105119

120+
/**
121+
* Gets the update policy for locally cached metadata from the repository.
122+
*
123+
* @return The update policy, never {@code null}.
124+
* @since TBD
125+
*/
126+
public String getMetadataUpdatePolicy() {
127+
return metadataUpdatePolicy;
128+
}
129+
106130
/**
107131
* Gets the policy for checksum validation.
108132
*
@@ -114,11 +138,10 @@ public String getChecksumPolicy() {
114138

115139
@Override
116140
public String toString() {
117-
StringBuilder buffer = new StringBuilder(256);
118-
buffer.append("enabled=").append(isEnabled());
119-
buffer.append(", checksums=").append(getChecksumPolicy());
120-
buffer.append(", updates=").append(getUpdatePolicy());
121-
return buffer.toString();
141+
return "enabled=" + isEnabled()
142+
+ ", checksums=" + getChecksumPolicy()
143+
+ ", updates=" + getUpdatePolicy()
144+
+ ", metadataUpdates=" + getMetadataUpdatePolicy();
122145
}
123146

124147
@Override

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

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ public final class UpdateCheck<T, E extends RepositoryException> {
4343

4444
private String policy;
4545

46+
private String metadataPolicy;
47+
4648
private RemoteRepository repository;
4749

4850
private RemoteRepository authoritativeRepository;
@@ -147,19 +149,30 @@ public UpdateCheck<T, E> setFileValid(boolean fileValid) {
147149
}
148150

149151
/**
150-
* Gets the policy to use for the check.
152+
* Gets the policy to use for the data check.
151153
*
152-
* @return The policy to use for the check.
154+
* @return The policy to use for the data check.
153155
* @see org.eclipse.aether.repository.RepositoryPolicy
154156
*/
155157
public String getPolicy() {
156158
return policy;
157159
}
158160

161+
/**
162+
* Gets the policy to use for the metadata check.
163+
*
164+
* @return The policy to use for the metadata check.
165+
* @see org.eclipse.aether.repository.RepositoryPolicy
166+
* @since TBD
167+
*/
168+
public String getMetadataPolicy() {
169+
return metadataPolicy;
170+
}
171+
159172
/**
160173
* Sets the policy to use for the check.
161174
*
162-
* @param policy The policy to use for the check, may be {@code null}.
175+
* @param policy The policy to use for the data check, may be {@code null}.
163176
* @return This object for chaining.
164177
* @see org.eclipse.aether.repository.RepositoryPolicy
165178
*/
@@ -168,6 +181,19 @@ public UpdateCheck<T, E> setPolicy(String policy) {
168181
return this;
169182
}
170183

184+
/**
185+
* Sets the policy to use for the check.
186+
*
187+
* @param metadataPolicy The policy to use for the metadata check, may be {@code null}.
188+
* @return This object for chaining.
189+
* @see org.eclipse.aether.repository.RepositoryPolicy
190+
* @since TBD
191+
*/
192+
public UpdateCheck<T, E> setMetadataPolicy(String metadataPolicy) {
193+
this.metadataPolicy = metadataPolicy;
194+
return this;
195+
}
196+
171197
/**
172198
* Gets the repository from which a potential update/download will performed.
173199
*
@@ -256,6 +282,6 @@ public UpdateCheck<T, E> setException(E exception) {
256282

257283
@Override
258284
public String toString() {
259-
return getPolicy() + ": " + getFile() + " < " + getRepository();
285+
return getPolicy() + "/" + getMetadataPolicy() + ": " + getFile() + " < " + getRepository();
260286
}
261287
}

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -582,6 +582,7 @@ private List<ArtifactDownload> gatherDownloads(RepositorySystemSession session,
582582
check.setFileValid(false);
583583
check.setRepository(group.repository);
584584
check.setPolicy(policy.getUpdatePolicy());
585+
check.setMetadataPolicy(policy.getMetadataUpdatePolicy());
585586
item.updateCheck = check;
586587
updateCheckManager.checkArtifact(session, check);
587588
if (!check.isRequired()) {

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,8 @@ private List<MetadataResult> resolve(
282282
List<UpdateCheck<Metadata, MetadataTransferException>> checks = new ArrayList<>();
283283
Exception exception = null;
284284
for (RemoteRepository repo : repositories) {
285+
RepositoryPolicy policy = getPolicy(session, repo, metadata.getNature());
286+
285287
UpdateCheck<Metadata, MetadataTransferException> check = new UpdateCheck<>();
286288
check.setLocalLastUpdated((localLastUpdate != null) ? localLastUpdate : 0);
287289
check.setItem(metadata);
@@ -294,8 +296,8 @@ private List<MetadataResult> resolve(
294296
check.setFile(checkFile);
295297
check.setRepository(repository);
296298
check.setAuthoritativeRepository(repo);
297-
check.setPolicy(
298-
getPolicy(session, repo, metadata.getNature()).getUpdatePolicy());
299+
check.setPolicy(policy.getUpdatePolicy());
300+
check.setMetadataPolicy(policy.getMetadataUpdatePolicy());
299301

300302
if (lrmResult.isStale()) {
301303
checks.add(check);

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

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -256,25 +256,41 @@ private RepositoryPolicy merge(
256256

257257
if (policy2 == null) {
258258
if (globalPolicy) {
259-
policy = merge(policy1, session.getUpdatePolicy(), session.getChecksumPolicy());
259+
policy = merge(
260+
policy1,
261+
session.getUpdatePolicy(),
262+
session.getMetadataUpdatePolicy(),
263+
session.getChecksumPolicy());
260264
} else {
261265
policy = policy1;
262266
}
263267
} else if (policy1 == null) {
264268
if (globalPolicy) {
265-
policy = merge(policy2, session.getUpdatePolicy(), session.getChecksumPolicy());
269+
policy = merge(
270+
policy2,
271+
session.getUpdatePolicy(),
272+
session.getMetadataUpdatePolicy(),
273+
session.getChecksumPolicy());
266274
} else {
267275
policy = policy2;
268276
}
269277
} else if (!policy2.isEnabled()) {
270278
if (globalPolicy) {
271-
policy = merge(policy1, session.getUpdatePolicy(), session.getChecksumPolicy());
279+
policy = merge(
280+
policy1,
281+
session.getUpdatePolicy(),
282+
session.getMetadataUpdatePolicy(),
283+
session.getChecksumPolicy());
272284
} else {
273285
policy = policy1;
274286
}
275287
} else if (!policy1.isEnabled()) {
276288
if (globalPolicy) {
277-
policy = merge(policy2, session.getUpdatePolicy(), session.getChecksumPolicy());
289+
policy = merge(
290+
policy2,
291+
session.getUpdatePolicy(),
292+
session.getMetadataUpdatePolicy(),
293+
session.getChecksumPolicy());
278294
} else {
279295
policy = policy2;
280296
}
@@ -296,24 +312,35 @@ private RepositoryPolicy merge(
296312
updates = updatePolicyAnalyzer.getEffectiveUpdatePolicy(
297313
session, policy1.getUpdatePolicy(), policy2.getUpdatePolicy());
298314
}
315+
String metadataUpdates = session.getMetadataUpdatePolicy();
316+
if (globalPolicy && metadataUpdates != null && !metadataUpdates.isEmpty()) {
317+
// use global override
318+
} else {
319+
metadataUpdates = updatePolicyAnalyzer.getEffectiveUpdatePolicy(
320+
session, policy1.getMetadataUpdatePolicy(), policy2.getMetadataUpdatePolicy());
321+
}
299322

300-
policy = new RepositoryPolicy(true, updates, checksums);
323+
policy = new RepositoryPolicy(true, updates, metadataUpdates, checksums);
301324
}
302325

303326
return policy;
304327
}
305328

306-
private RepositoryPolicy merge(RepositoryPolicy policy, String updates, String checksums) {
329+
private RepositoryPolicy merge(RepositoryPolicy policy, String updates, String metadataUpdates, String checksums) {
307330
if (policy != null) {
308331
if (updates == null || updates.isEmpty()) {
309332
updates = policy.getUpdatePolicy();
310333
}
334+
if (metadataUpdates == null || metadataUpdates.isEmpty()) {
335+
metadataUpdates = policy.getMetadataUpdatePolicy();
336+
}
311337
if (checksums == null || checksums.isEmpty()) {
312338
checksums = policy.getChecksumPolicy();
313339
}
314340
if (!policy.getUpdatePolicy().equals(updates)
341+
|| !policy.getMetadataUpdatePolicy().equals(metadataUpdates)
315342
|| !policy.getChecksumPolicy().equals(checksums)) {
316-
policy = new RepositoryPolicy(policy.isEnabled(), updates, checksums);
343+
policy = new RepositoryPolicy(policy.isEnabled(), updates, metadataUpdates, checksums);
317344
}
318345
}
319346
return policy;

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

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -136,8 +136,9 @@ public DefaultUpdateCheckManager setUpdatePolicyAnalyzer(UpdatePolicyAnalyzer up
136136
public void checkArtifact(RepositorySystemSession session, UpdateCheck<Artifact, ArtifactTransferException> check) {
137137
requireNonNull(session, "session cannot be null");
138138
requireNonNull(check, "check cannot be null");
139+
final String updatePolicy = check.getPolicy();
139140
if (check.getLocalLastUpdated() != 0
140-
&& !isUpdatedRequired(session, check.getLocalLastUpdated(), check.getPolicy())) {
141+
&& !isUpdatedRequired(session, check.getLocalLastUpdated(), updatePolicy)) {
141142
LOGGER.debug("Skipped remote request for {}, locally installed artifact up-to-date", check.getItem());
142143

143144
check.setRequired(false);
@@ -187,7 +188,7 @@ public void checkArtifact(RepositorySystemSession session, UpdateCheck<Artifact,
187188
if (error != null) {
188189
check.setException(newException(error, artifact, repository));
189190
}
190-
} else if (isUpdatedRequired(session, lastUpdated, check.getPolicy())) {
191+
} else if (isUpdatedRequired(session, lastUpdated, updatePolicy)) {
191192
check.setRequired(true);
192193
} else if (fileExists) {
193194
LOGGER.debug("Skipped remote request for {}, locally cached artifact up-to-date", check.getItem());
@@ -241,8 +242,9 @@ private ArtifactTransferException newException(String error, Artifact artifact,
241242
public void checkMetadata(RepositorySystemSession session, UpdateCheck<Metadata, MetadataTransferException> check) {
242243
requireNonNull(session, "session cannot be null");
243244
requireNonNull(check, "check cannot be null");
245+
final String updatePolicy = check.getMetadataPolicy();
244246
if (check.getLocalLastUpdated() != 0
245-
&& !isUpdatedRequired(session, check.getLocalLastUpdated(), check.getPolicy())) {
247+
&& !isUpdatedRequired(session, check.getLocalLastUpdated(), updatePolicy)) {
246248
LOGGER.debug("Skipped remote request for {} locally installed metadata up-to-date", check.getItem());
247249

248250
check.setRequired(false);
@@ -292,7 +294,7 @@ public void checkMetadata(RepositorySystemSession session, UpdateCheck<Metadata,
292294
if (error != null) {
293295
check.setException(newException(error, metadata, repository));
294296
}
295-
} else if (isUpdatedRequired(session, lastUpdated, check.getPolicy())) {
297+
} else if (isUpdatedRequired(session, lastUpdated, updatePolicy)) {
296298
check.setRequired(true);
297299
} else if (fileExists) {
298300
LOGGER.debug("Skipped remote request for {}, locally cached metadata up-to-date", check.getItem());

0 commit comments

Comments
 (0)