diff --git a/maven-resolver-api/src/main/java/org/eclipse/aether/AbstractForwardingRepositorySystemSession.java b/maven-resolver-api/src/main/java/org/eclipse/aether/AbstractForwardingRepositorySystemSession.java index a1a2083e1..4583b065c 100644 --- a/maven-resolver-api/src/main/java/org/eclipse/aether/AbstractForwardingRepositorySystemSession.java +++ b/maven-resolver-api/src/main/java/org/eclipse/aether/AbstractForwardingRepositorySystemSession.java @@ -87,6 +87,11 @@ public String getUpdatePolicy() { return getSession().getUpdatePolicy(); } + @Override + public String getMetadataUpdatePolicy() { + return getSession().getMetadataUpdatePolicy(); + } + @Override public LocalRepository getLocalRepository() { return getSession().getLocalRepository(); diff --git a/maven-resolver-api/src/main/java/org/eclipse/aether/DefaultRepositorySystemSession.java b/maven-resolver-api/src/main/java/org/eclipse/aether/DefaultRepositorySystemSession.java index a6e24fd57..9738d9a07 100644 --- a/maven-resolver-api/src/main/java/org/eclipse/aether/DefaultRepositorySystemSession.java +++ b/maven-resolver-api/src/main/java/org/eclipse/aether/DefaultRepositorySystemSession.java @@ -73,6 +73,8 @@ public final class DefaultRepositorySystemSession implements RepositorySystemSes private String updatePolicy; + private String metadataUpdatePolicy; + private LocalRepositoryManager localRepositoryManager; private FileTransformerManager fileTransformerManager; @@ -154,6 +156,7 @@ public DefaultRepositorySystemSession(RepositorySystemSession session) { setArtifactDescriptorPolicy(session.getArtifactDescriptorPolicy()); setChecksumPolicy(session.getChecksumPolicy()); setUpdatePolicy(session.getUpdatePolicy()); + setMetadataUpdatePolicy(session.getMetadataUpdatePolicy()); setLocalRepositoryManager(session.getLocalRepositoryManager()); setWorkspaceReader(session.getWorkspaceReader()); setRepositoryListener(session.getRepositoryListener()); @@ -293,6 +296,28 @@ public DefaultRepositorySystemSession setUpdatePolicy(String updatePolicy) { return this; } + @Override + public String getMetadataUpdatePolicy() { + return metadataUpdatePolicy; + } + + /** + * Sets the global metadata update policy. If set, the global update policy overrides the update policies of the remote + * repositories being used for resolution. + * + * @param metadataUpdatePolicy The global update policy, may be {@code null}/empty to apply the per-repository policies. + * @return This session for chaining, never {@code null}. + * @see RepositoryPolicy#UPDATE_POLICY_ALWAYS + * @see RepositoryPolicy#UPDATE_POLICY_DAILY + * @see RepositoryPolicy#UPDATE_POLICY_NEVER + * @since TBD + */ + public DefaultRepositorySystemSession setMetadataUpdatePolicy(String metadataUpdatePolicy) { + verifyStateForMutation(); + this.metadataUpdatePolicy = metadataUpdatePolicy; + return this; + } + @Override public LocalRepository getLocalRepository() { LocalRepositoryManager lrm = getLocalRepositoryManager(); diff --git a/maven-resolver-api/src/main/java/org/eclipse/aether/RepositorySystemSession.java b/maven-resolver-api/src/main/java/org/eclipse/aether/RepositorySystemSession.java index 31e99cd70..581161119 100644 --- a/maven-resolver-api/src/main/java/org/eclipse/aether/RepositorySystemSession.java +++ b/maven-resolver-api/src/main/java/org/eclipse/aether/RepositorySystemSession.java @@ -94,7 +94,7 @@ public interface RepositorySystemSession { String getChecksumPolicy(); /** - * Gets the global update policy. If set, the global update policy overrides the update policies of the remote + * Gets the global data update policy. If set, the global update policy overrides the update policies of the remote * repositories being used for resolution. * * @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 { */ String getUpdatePolicy(); + /** + * Gets the global metadata update policy. If set, the global update policy overrides the update policies of the remote + * repositories being used for resolution. + * + * @return The global update policy or {@code null}/empty if not set and the per-repository policies apply. + * @see RepositoryPolicy#UPDATE_POLICY_ALWAYS + * @see RepositoryPolicy#UPDATE_POLICY_DAILY + * @see RepositoryPolicy#UPDATE_POLICY_NEVER + * @since TBD + */ + String getMetadataUpdatePolicy(); + /** * Gets the local repository used during this session. This is a convenience method for * {@link LocalRepositoryManager#getRepository()}. diff --git a/maven-resolver-api/src/main/java/org/eclipse/aether/repository/RepositoryPolicy.java b/maven-resolver-api/src/main/java/org/eclipse/aether/repository/RepositoryPolicy.java index 14f44d44d..6adf28bf6 100644 --- a/maven-resolver-api/src/main/java/org/eclipse/aether/repository/RepositoryPolicy.java +++ b/maven-resolver-api/src/main/java/org/eclipse/aether/repository/RepositoryPolicy.java @@ -62,13 +62,23 @@ public final class RepositoryPolicy { private final String updatePolicy; + private final String metadataUpdatePolicy; + private final String checksumPolicy; /** * Creates a new policy with checksum warnings and daily update checks. */ public RepositoryPolicy() { - this(true, UPDATE_POLICY_DAILY, CHECKSUM_POLICY_WARN); + this(true, UPDATE_POLICY_DAILY, UPDATE_POLICY_DAILY, CHECKSUM_POLICY_WARN); + } + + /** + * Creates a new policy with the specified settings (uses same update policy for data and metadata, retains old + * resolver behaviour). + */ + public RepositoryPolicy(boolean enabled, String updatePolicy, String checksumPolicy) { + this(enabled, updatePolicy, updatePolicy, checksumPolicy); } /** @@ -76,12 +86,16 @@ public RepositoryPolicy() { * * @param enabled A flag whether the associated repository should be accessed or not. * @param updatePolicy The update interval after which locally cached data from the repository is considered stale - * and should be refetched, may be {@code null}. + * and should be re-fetched, may be {@code null}. + * @param metadataUpdatePolicy The update interval after which locally cached metadata from the repository is considered stale + * and should be re-fetched, may be {@code null}. * @param checksumPolicy The way checksum verification should be handled, may be {@code null}. + * @since TBD */ - public RepositoryPolicy(boolean enabled, String updatePolicy, String checksumPolicy) { + public RepositoryPolicy(boolean enabled, String updatePolicy, String metadataUpdatePolicy, String checksumPolicy) { this.enabled = enabled; this.updatePolicy = (updatePolicy != null) ? updatePolicy : ""; + this.metadataUpdatePolicy = (metadataUpdatePolicy != null) ? metadataUpdatePolicy : ""; this.checksumPolicy = (checksumPolicy != null) ? checksumPolicy : ""; } @@ -103,6 +117,16 @@ public String getUpdatePolicy() { return updatePolicy; } + /** + * Gets the update policy for locally cached metadata from the repository. + * + * @return The update policy, never {@code null}. + * @since TBD + */ + public String getMetadataUpdatePolicy() { + return metadataUpdatePolicy; + } + /** * Gets the policy for checksum validation. * @@ -114,11 +138,10 @@ public String getChecksumPolicy() { @Override public String toString() { - StringBuilder buffer = new StringBuilder(256); - buffer.append("enabled=").append(isEnabled()); - buffer.append(", checksums=").append(getChecksumPolicy()); - buffer.append(", updates=").append(getUpdatePolicy()); - return buffer.toString(); + return "enabled=" + isEnabled() + + ", checksums=" + getChecksumPolicy() + + ", updates=" + getUpdatePolicy() + + ", metadataUpdates=" + getMetadataUpdatePolicy(); } @Override diff --git a/maven-resolver-impl/src/main/java/org/eclipse/aether/impl/UpdateCheck.java b/maven-resolver-impl/src/main/java/org/eclipse/aether/impl/UpdateCheck.java index f689c12fe..f5a2454e9 100644 --- a/maven-resolver-impl/src/main/java/org/eclipse/aether/impl/UpdateCheck.java +++ b/maven-resolver-impl/src/main/java/org/eclipse/aether/impl/UpdateCheck.java @@ -43,6 +43,8 @@ public final class UpdateCheck { private String policy; + private String metadataPolicy; + private RemoteRepository repository; private RemoteRepository authoritativeRepository; @@ -147,19 +149,30 @@ public UpdateCheck setFileValid(boolean fileValid) { } /** - * Gets the policy to use for the check. + * Gets the policy to use for the data check. * - * @return The policy to use for the check. + * @return The policy to use for the data check. * @see org.eclipse.aether.repository.RepositoryPolicy */ public String getPolicy() { return policy; } + /** + * Gets the policy to use for the metadata check. + * + * @return The policy to use for the metadata check. + * @see org.eclipse.aether.repository.RepositoryPolicy + * @since TBD + */ + public String getMetadataPolicy() { + return metadataPolicy; + } + /** * Sets the policy to use for the check. * - * @param policy The policy to use for the check, may be {@code null}. + * @param policy The policy to use for the data check, may be {@code null}. * @return This object for chaining. * @see org.eclipse.aether.repository.RepositoryPolicy */ @@ -168,6 +181,19 @@ public UpdateCheck setPolicy(String policy) { return this; } + /** + * Sets the policy to use for the check. + * + * @param metadataPolicy The policy to use for the metadata check, may be {@code null}. + * @return This object for chaining. + * @see org.eclipse.aether.repository.RepositoryPolicy + * @since TBD + */ + public UpdateCheck setMetadataPolicy(String metadataPolicy) { + this.metadataPolicy = metadataPolicy; + return this; + } + /** * Gets the repository from which a potential update/download will performed. * @@ -256,6 +282,6 @@ public UpdateCheck setException(E exception) { @Override public String toString() { - return getPolicy() + ": " + getFile() + " < " + getRepository(); + return getPolicy() + "/" + getMetadataPolicy() + ": " + getFile() + " < " + getRepository(); } } diff --git a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultArtifactResolver.java b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultArtifactResolver.java index 044302461..164d42557 100644 --- a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultArtifactResolver.java +++ b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultArtifactResolver.java @@ -582,6 +582,7 @@ private List gatherDownloads(RepositorySystemSession session, check.setFileValid(false); check.setRepository(group.repository); check.setPolicy(policy.getUpdatePolicy()); + check.setMetadataPolicy(policy.getMetadataUpdatePolicy()); item.updateCheck = check; updateCheckManager.checkArtifact(session, check); if (!check.isRequired()) { diff --git a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultMetadataResolver.java b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultMetadataResolver.java index b0620cd7b..b26de1d8d 100644 --- a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultMetadataResolver.java +++ b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultMetadataResolver.java @@ -282,6 +282,8 @@ private List resolve( List> checks = new ArrayList<>(); Exception exception = null; for (RemoteRepository repo : repositories) { + RepositoryPolicy policy = getPolicy(session, repo, metadata.getNature()); + UpdateCheck check = new UpdateCheck<>(); check.setLocalLastUpdated((localLastUpdate != null) ? localLastUpdate : 0); check.setItem(metadata); @@ -294,8 +296,8 @@ private List resolve( check.setFile(checkFile); check.setRepository(repository); check.setAuthoritativeRepository(repo); - check.setPolicy( - getPolicy(session, repo, metadata.getNature()).getUpdatePolicy()); + check.setPolicy(policy.getUpdatePolicy()); + check.setMetadataPolicy(policy.getMetadataUpdatePolicy()); if (lrmResult.isStale()) { checks.add(check); diff --git a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultRemoteRepositoryManager.java b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultRemoteRepositoryManager.java index 9f8471ee4..7844bc57d 100644 --- a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultRemoteRepositoryManager.java +++ b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultRemoteRepositoryManager.java @@ -256,25 +256,41 @@ private RepositoryPolicy merge( if (policy2 == null) { if (globalPolicy) { - policy = merge(policy1, session.getUpdatePolicy(), session.getChecksumPolicy()); + policy = merge( + policy1, + session.getUpdatePolicy(), + session.getMetadataUpdatePolicy(), + session.getChecksumPolicy()); } else { policy = policy1; } } else if (policy1 == null) { if (globalPolicy) { - policy = merge(policy2, session.getUpdatePolicy(), session.getChecksumPolicy()); + policy = merge( + policy2, + session.getUpdatePolicy(), + session.getMetadataUpdatePolicy(), + session.getChecksumPolicy()); } else { policy = policy2; } } else if (!policy2.isEnabled()) { if (globalPolicy) { - policy = merge(policy1, session.getUpdatePolicy(), session.getChecksumPolicy()); + policy = merge( + policy1, + session.getUpdatePolicy(), + session.getMetadataUpdatePolicy(), + session.getChecksumPolicy()); } else { policy = policy1; } } else if (!policy1.isEnabled()) { if (globalPolicy) { - policy = merge(policy2, session.getUpdatePolicy(), session.getChecksumPolicy()); + policy = merge( + policy2, + session.getUpdatePolicy(), + session.getMetadataUpdatePolicy(), + session.getChecksumPolicy()); } else { policy = policy2; } @@ -296,24 +312,35 @@ private RepositoryPolicy merge( updates = updatePolicyAnalyzer.getEffectiveUpdatePolicy( session, policy1.getUpdatePolicy(), policy2.getUpdatePolicy()); } + String metadataUpdates = session.getMetadataUpdatePolicy(); + if (globalPolicy && metadataUpdates != null && !metadataUpdates.isEmpty()) { + // use global override + } else { + metadataUpdates = updatePolicyAnalyzer.getEffectiveUpdatePolicy( + session, policy1.getMetadataUpdatePolicy(), policy2.getMetadataUpdatePolicy()); + } - policy = new RepositoryPolicy(true, updates, checksums); + policy = new RepositoryPolicy(true, updates, metadataUpdates, checksums); } return policy; } - private RepositoryPolicy merge(RepositoryPolicy policy, String updates, String checksums) { + private RepositoryPolicy merge(RepositoryPolicy policy, String updates, String metadataUpdates, String checksums) { if (policy != null) { if (updates == null || updates.isEmpty()) { updates = policy.getUpdatePolicy(); } + if (metadataUpdates == null || metadataUpdates.isEmpty()) { + metadataUpdates = policy.getMetadataUpdatePolicy(); + } if (checksums == null || checksums.isEmpty()) { checksums = policy.getChecksumPolicy(); } if (!policy.getUpdatePolicy().equals(updates) + || !policy.getMetadataUpdatePolicy().equals(metadataUpdates) || !policy.getChecksumPolicy().equals(checksums)) { - policy = new RepositoryPolicy(policy.isEnabled(), updates, checksums); + policy = new RepositoryPolicy(policy.isEnabled(), updates, metadataUpdates, checksums); } } return policy; diff --git a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultUpdateCheckManager.java b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultUpdateCheckManager.java index 50a960bfa..27ec290fb 100644 --- a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultUpdateCheckManager.java +++ b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultUpdateCheckManager.java @@ -136,8 +136,9 @@ public DefaultUpdateCheckManager setUpdatePolicyAnalyzer(UpdatePolicyAnalyzer up public void checkArtifact(RepositorySystemSession session, UpdateCheck check) { requireNonNull(session, "session cannot be null"); requireNonNull(check, "check cannot be null"); + final String updatePolicy = check.getPolicy(); if (check.getLocalLastUpdated() != 0 - && !isUpdatedRequired(session, check.getLocalLastUpdated(), check.getPolicy())) { + && !isUpdatedRequired(session, check.getLocalLastUpdated(), updatePolicy)) { LOGGER.debug("Skipped remote request for {}, locally installed artifact up-to-date", check.getItem()); check.setRequired(false); @@ -187,7 +188,7 @@ public void checkArtifact(RepositorySystemSession session, UpdateCheck check) { requireNonNull(session, "session cannot be null"); requireNonNull(check, "check cannot be null"); + final String updatePolicy = check.getMetadataPolicy(); if (check.getLocalLastUpdated() != 0 - && !isUpdatedRequired(session, check.getLocalLastUpdated(), check.getPolicy())) { + && !isUpdatedRequired(session, check.getLocalLastUpdated(), updatePolicy)) { LOGGER.debug("Skipped remote request for {} locally installed metadata up-to-date", check.getItem()); check.setRequired(false); @@ -292,7 +294,7 @@ public void checkMetadata(RepositorySystemSession session, UpdateCheck newMetadataCheck() { check.setRepository(repository); check.setAuthoritativeRepository(repository); check.setPolicy(RepositoryPolicy.UPDATE_POLICY_INTERVAL + ":10"); + check.setMetadataPolicy(RepositoryPolicy.UPDATE_POLICY_INTERVAL + ":10"); return check; } @@ -298,6 +299,7 @@ public void testCheckMetadataErrorFromRepoCachingDisabled() { public void testCheckMetadataAtMostOnceDuringSessionEvenIfUpdatePolicyAlways() { UpdateCheck check = newMetadataCheck(); check.setPolicy(RepositoryPolicy.UPDATE_POLICY_ALWAYS); + check.setMetadataPolicy(RepositoryPolicy.UPDATE_POLICY_ALWAYS); // first check manager.checkMetadata(session, check); @@ -314,6 +316,7 @@ public void testCheckMetadataAtMostOnceDuringSessionEvenIfUpdatePolicyAlways() { public void testCheckMetadataSessionStateModes() { UpdateCheck check = newMetadataCheck(); check.setPolicy(RepositoryPolicy.UPDATE_POLICY_ALWAYS); + check.setMetadataPolicy(RepositoryPolicy.UPDATE_POLICY_ALWAYS); manager.touchMetadata(session, check); session.setConfigProperty(DefaultUpdateCheckManager.CONFIG_PROP_SESSION_STATE, "bypass"); @@ -338,6 +341,7 @@ public void testCheckMetadataSessionStateModes() { public void testCheckMetadataAtMostOnceDuringSessionEvenIfUpdatePolicyAlways_InvalidFile() { UpdateCheck check = newMetadataCheck(); check.setPolicy(RepositoryPolicy.UPDATE_POLICY_ALWAYS); + check.setMetadataPolicy(RepositoryPolicy.UPDATE_POLICY_ALWAYS); check.setFileValid(false); // first check @@ -364,6 +368,7 @@ public void testCheckMetadataAtMostOnceDuringSessionEvenIfUpdatePolicyAlways_Inv public void testCheckMetadataAtMostOnceDuringSessionEvenIfUpdatePolicyAlways_DifferentRepoIdSameUrl() { UpdateCheck check = newMetadataCheck(); check.setPolicy(RepositoryPolicy.UPDATE_POLICY_ALWAYS); + check.setMetadataPolicy(RepositoryPolicy.UPDATE_POLICY_ALWAYS); check.setFileValid(false); // first check @@ -427,6 +432,7 @@ public void testCheckMetadataWhenLocallyDeletedEvenIfTimestampUpToDate() { public void testCheckMetadataNotWhenUpdatePolicyIsNeverAndTimestampIsUnavailable() { UpdateCheck check = newMetadataCheck(); check.setPolicy(RepositoryPolicy.UPDATE_POLICY_NEVER); + check.setMetadataPolicy(RepositoryPolicy.UPDATE_POLICY_NEVER); session.setResolutionErrorPolicy(new SimpleResolutionErrorPolicy(true, false)); manager.checkMetadata(session, check);