This is an automated email from the ASF dual-hosted git repository.
cziegeler pushed a commit to branch master
in repository
https://gitbox.apache.org/repos/asf/sling-org-apache-sling-feature-extension-apiregions.git
The following commit(s) were added to refs/heads/master by this push:
new 7c82754 SLING-12821 : Allow enforceOn date for artifact rules
7c82754 is described below
commit 7c82754223af7f324d1636a5133e9708f250e56b
Author: Carsten Ziegeler <[email protected]>
AuthorDate: Thu Jun 5 07:25:59 2025 +0200
SLING-12821 : Allow enforceOn date for artifact rules
---
.../apiregions/analyser/CheckArtifactRules.java | 14 +++-
.../api/artifacts/InternalConstants.java | 3 +
.../apiregions/api/artifacts/VersionRule.java | 81 +++++++++++++++++++++-
.../apiregions/api/artifacts/package-info.java | 2 +-
.../analyser/CheckArtifactRulesTest.java | 69 +++++++++++++++++-
.../apiregions/api/artifacts/VersionRuleTest.java | 56 ++++++++++++++-
6 files changed, 216 insertions(+), 9 deletions(-)
diff --git
a/src/main/java/org/apache/sling/feature/extension/apiregions/analyser/CheckArtifactRules.java
b/src/main/java/org/apache/sling/feature/extension/apiregions/analyser/CheckArtifactRules.java
index d35cc25..e27d272 100644
---
a/src/main/java/org/apache/sling/feature/extension/apiregions/analyser/CheckArtifactRules.java
+++
b/src/main/java/org/apache/sling/feature/extension/apiregions/analyser/CheckArtifactRules.java
@@ -16,6 +16,7 @@
*/
package org.apache.sling.feature.extension.apiregions.analyser;
+import java.util.Calendar;
import java.util.List;
import org.apache.sling.feature.ArtifactId;
@@ -51,11 +52,16 @@ public class CheckArtifactRules implements AnalyserTask{
}
for(final ArtifactDescriptor desc :
context.getFeatureDescriptor().getArtifactDescriptors()) {
this.checkArtifact(context, rules.getArtifactVersionRules(),
rules.getMode(), desc.getArtifact().getId());
- }
+ }
}
}
void checkArtifact(final AnalyserTaskContext context, final
List<VersionRule> rules, final Mode defaultMode, final ArtifactId id) {
+ final Calendar now = Calendar.getInstance();
+ now.set(Calendar.HOUR_OF_DAY, 1);
+ now.set(Calendar.MINUTE, 0);
+ now.set(Calendar.SECOND, 0);
+ now.set(Calendar.MILLISECOND, 0);
for(final VersionRule rule : rules) {
if ( rule.getArtifactId() != null &&
rule.getArtifactId().isSame(id)) {
if ( ! rule.isAllowed(id.getOSGiVersion())) {
@@ -63,11 +69,15 @@ public class CheckArtifactRules implements AnalyserTask{
if ( msg == null ) {
msg = "Artifact with version " + id.getVersion() + "
is not allowed.";
}
+ if ( rule.getEnforceOn() != null ) {
+ msg = msg.concat(" Enforce on: " +
rule.getEnforceOn());
+ }
+ final boolean enforce =
!rule.getEnforceOnDate().after(now);
Mode m = defaultMode;
if ( rule.getMode() != null ) {
m = rule.getMode();
}
- if ( m == Mode.LENIENT ) {
+ if ( m == Mode.LENIENT || !enforce) {
context.reportArtifactWarning(id, msg);
} else {
context.reportArtifactError(id, msg);
diff --git
a/src/main/java/org/apache/sling/feature/extension/apiregions/api/artifacts/InternalConstants.java
b/src/main/java/org/apache/sling/feature/extension/apiregions/api/artifacts/InternalConstants.java
index eb3ac01..880240d 100755
---
a/src/main/java/org/apache/sling/feature/extension/apiregions/api/artifacts/InternalConstants.java
+++
b/src/main/java/org/apache/sling/feature/extension/apiregions/api/artifacts/InternalConstants.java
@@ -34,4 +34,7 @@ abstract class InternalConstants {
static final String KEY_BUNDLE_VERSION_RULES = "bundle-version-rules";
static final String KEY_ARTIFACT_VERSION_RULES = "artifact-version-rules";
+
+ /** @since 2.10 */
+ static final String KEY_ENFORCE_ON = "enforce-on";
}
diff --git
a/src/main/java/org/apache/sling/feature/extension/apiregions/api/artifacts/VersionRule.java
b/src/main/java/org/apache/sling/feature/extension/apiregions/api/artifacts/VersionRule.java
index 72d12ac..9da1f83 100755
---
a/src/main/java/org/apache/sling/feature/extension/apiregions/api/artifacts/VersionRule.java
+++
b/src/main/java/org/apache/sling/feature/extension/apiregions/api/artifacts/VersionRule.java
@@ -17,6 +17,7 @@
package org.apache.sling.feature.extension.apiregions.api.artifacts;
import java.io.IOException;
+import java.util.Calendar;
import jakarta.json.JsonException;
import jakarta.json.JsonObject;
@@ -48,6 +49,13 @@ public class VersionRule extends AttributeableEntity {
/** The denied version ranges */
private VersionRange[] deniedVersionRanges;
+ /**
+ * Optional enforce on information.
+ * @since 2.1.0
+ */
+ private String enforceOn;
+
+
/**
* Create a new rules object
*/
@@ -66,6 +74,7 @@ public class VersionRule extends AttributeableEntity {
this.setMessage(null);
this.setAllowedVersionRanges(null);
this.setDeniedVersionRanges(null);
+ this.setEnforceOn(null);
}
/**
@@ -103,6 +112,8 @@ public class VersionRule extends AttributeableEntity {
this.setStringArray(objBuilder,
InternalConstants.KEY_DENIED_VERSION_RANGES, arr);
}
+ this.setString(objBuilder, InternalConstants.KEY_ENFORCE_ON,
this.getEnforceOn());
+
return objBuilder;
}
@@ -121,7 +132,7 @@ public class VersionRule extends AttributeableEntity {
if ( val != null ) {
this.setMode(Mode.valueOf(val.toUpperCase()));
}
-
+
val = this.getString(InternalConstants.KEY_ARTIFACT_ID);
if ( val != null ) {
this.setArtifactId(ArtifactId.parse(val));
@@ -154,6 +165,8 @@ public class VersionRule extends AttributeableEntity {
}
this.setDeniedVersionRanges(ranges);
}
+
+
this.setEnforceOn(this.getString(InternalConstants.KEY_ENFORCE_ON));
} catch (final JsonException | IllegalArgumentException e) {
throw new IOException(e);
}
@@ -266,4 +279,70 @@ public class VersionRule extends AttributeableEntity {
return result;
}
+
+ private Calendar parseDate(final String value) {
+ final String[] parts = value.split("-");
+ if ( parts.length == 3 ) {
+ if ( parts[0].length() == 4 && parts[1].length() == 2 &&
parts[2].length() == 2 ) {
+ try {
+ final int year = Integer.parseInt(parts[0]);
+ final int month = Integer.parseInt(parts[1]);
+ final int day = Integer.parseInt(parts[2]);
+
+ final Calendar c = Calendar.getInstance();
+ c.set(Calendar.YEAR, year);
+ c.set(Calendar.MONTH, month - 1);
+ c.set(Calendar.DAY_OF_MONTH, day);
+
+ c.set(Calendar.HOUR_OF_DAY, 1);
+ c.set(Calendar.MINUTE, 0);
+ c.set(Calendar.SECOND, 0);
+ c.set(Calendar.MILLISECOND, 0);
+
+ return c;
+ } catch ( final NumberFormatException ignore ) {
+ // ignore
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Get the optional enforce on information. This must be a date in the
format 'YYYY-MM-DD'.
+ * @return The since information or {@code null}
+ * @since 2.1.0
+ */
+ public String getEnforceOn() {
+ return enforceOn;
+ }
+
+ /**
+ * Set the enforce on information. This must be a date in the format
'YYYY-MM-DD'.
+ * @param enforceOn The new info or {@code null} to remove it
+ * @since 2.1.0
+ * @throw IllegalArgumentException If the format is not correct
+ */
+ public void setEnforceOn(final String enforceOn) {
+ if (enforceOn == null || parseDate(enforceOn) != null) {
+ this.enforceOn = enforceOn;
+ } else {
+ throw new IllegalArgumentException("Enforce on date must be in the
format 'YYYY-MM-DD'");
+ }
+ }
+
+ /**
+ * Return a date by which this rule is enforced
+ * @return A calendar if the value from {@link #getEnforceOn()} is set or
yesterday
+ * @since 2.1.0
+ */
+ public Calendar getEnforceOnDate() {
+ Calendar result = this.enforceOn == null ? null :
this.parseDate(this.enforceOn);
+ if ( result == null ) {
+ // if not set, return yesterday
+ result = Calendar.getInstance();
+ result.add(Calendar.DAY_OF_YEAR, -1);
+ }
+ return result;
+ }
}
diff --git
a/src/main/java/org/apache/sling/feature/extension/apiregions/api/artifacts/package-info.java
b/src/main/java/org/apache/sling/feature/extension/apiregions/api/artifacts/package-info.java
index 03ef7f2..f45cfd5 100755
---
a/src/main/java/org/apache/sling/feature/extension/apiregions/api/artifacts/package-info.java
+++
b/src/main/java/org/apache/sling/feature/extension/apiregions/api/artifacts/package-info.java
@@ -17,7 +17,7 @@
* under the License.
*/
[email protected]("2.0.0")
[email protected]("2.1.0")
package org.apache.sling.feature.extension.apiregions.api.artifacts;
diff --git
a/src/test/java/org/apache/sling/feature/extension/apiregions/analyser/CheckArtifactRulesTest.java
b/src/test/java/org/apache/sling/feature/extension/apiregions/analyser/CheckArtifactRulesTest.java
index 96814e1..401c045 100644
---
a/src/test/java/org/apache/sling/feature/extension/apiregions/analyser/CheckArtifactRulesTest.java
+++
b/src/test/java/org/apache/sling/feature/extension/apiregions/analyser/CheckArtifactRulesTest.java
@@ -18,6 +18,10 @@ package
org.apache.sling.feature.extension.apiregions.analyser;
import static org.mockito.Mockito.when;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+
import org.apache.sling.feature.Artifact;
import org.apache.sling.feature.ArtifactId;
import org.apache.sling.feature.Extension;
@@ -36,7 +40,7 @@ import org.junit.Test;
import org.mockito.Mockito;
public class CheckArtifactRulesTest {
-
+
private CheckArtifactRules analyser = new CheckArtifactRules();
private AnalyserTaskContext newContext(final Feature f) {
@@ -57,7 +61,7 @@ public class CheckArtifactRulesTest {
for(final Artifact a : ext.getArtifacts()) {
final ArtifactDescriptor bd =
Mockito.mock(ArtifactDescriptor.class);
when(bd.getArtifact()).thenReturn(a);
- fd.getArtifactDescriptors().add(bd);
+ fd.getArtifactDescriptors().add(bd);
}
}
}
@@ -98,7 +102,7 @@ public class CheckArtifactRulesTest {
final ArtifactRules rules = new ArtifactRules();
rules.getBundleVersionRules().add(r);
rules.getArtifactVersionRules().add(r2);
-
+
ArtifactRules.setArtifactRules(f, rules);
final AnalyserTaskContext context = newContext(f);
analyser.execute(context);
@@ -106,4 +110,63 @@ public class CheckArtifactRulesTest {
Mockito.verify(context,
Mockito.atLeastOnce()).reportArtifactError(Mockito.eq(bundle.getId()),
Mockito.eq(r.getMessage()));
Mockito.verify(context,
Mockito.atLeastOnce()).reportArtifactError(Mockito.eq(artifact.getId()),
Mockito.eq(r2.getMessage()));
}
+
+ @Test public void testValidateFeatureEnforceOnNotReached() throws
Exception {
+ final Feature f = new Feature(ArtifactId.parse("g:a:1"));
+ final Artifact bundle = new Artifact(ArtifactId.parse("g:b:1.1"));
+ f.getBundles().add(bundle);
+
+ final Calendar tomorrow = Calendar.getInstance();
+ final DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
+ tomorrow.add(Calendar.DAY_OF_MONTH, 1);
+ final VersionRule r = new VersionRule();
+ r.setArtifactId(bundle.getId());
+ r.setMode(Mode.STRICT);
+ r.setMessage("foo");
+ r.setEnforceOn(df.format(tomorrow.getTime()));
+
+ final ArtifactRules rules = new ArtifactRules();
+ rules.getBundleVersionRules().add(r);
+
+ ArtifactRules.setArtifactRules(f, rules);
+ final AnalyserTaskContext context = newContext(f);
+ analyser.execute(context);
+
+ final String reportMsg = r.getMessage().concat(" Enforce on:
").concat(r.getEnforceOn());
+ Mockito.verify(context,
Mockito.atLeastOnce()).reportArtifactWarning(Mockito.eq(bundle.getId()),
Mockito.eq(reportMsg));
+ }
+
+ @Test public void testValidateFeatureEnforceOnReached() throws Exception {
+ final Feature f = new Feature(ArtifactId.parse("g:a:1"));
+ final Artifact bundle = new Artifact(ArtifactId.parse("g:b:1.1"));
+ f.getBundles().add(bundle);
+
+ final Calendar tomorrow = Calendar.getInstance();
+ final DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
+ tomorrow.add(Calendar.DAY_OF_MONTH, -5);
+ final VersionRule r = new VersionRule();
+ r.setArtifactId(bundle.getId());
+ r.setMode(Mode.STRICT);
+ r.setMessage("foo");
+ r.setEnforceOn(df.format(tomorrow.getTime()));
+
+ final ArtifactRules rules = new ArtifactRules();
+ rules.getBundleVersionRules().add(r);
+
+ ArtifactRules.setArtifactRules(f, rules);
+ final AnalyserTaskContext context = newContext(f);
+ analyser.execute(context);
+
+ final String reportMsg = r.getMessage().concat(" Enforce on:
").concat(r.getEnforceOn());
+ Mockito.verify(context,
Mockito.atLeastOnce()).reportArtifactError(Mockito.eq(bundle.getId()),
Mockito.eq(reportMsg));
+
+ // test again with date of today
+ r.setEnforceOn(df.format(Calendar.getInstance().getTime()));
+ ArtifactRules.setArtifactRules(f, rules);
+ final AnalyserTaskContext context2 = newContext(f);
+ analyser.execute(context2);
+
+ final String reportMsg2 = r.getMessage().concat(" Enforce on:
").concat(r.getEnforceOn());
+ Mockito.verify(context2,
Mockito.atLeastOnce()).reportArtifactError(Mockito.eq(bundle.getId()),
Mockito.eq(reportMsg2));
+ }
}
diff --git
a/src/test/java/org/apache/sling/feature/extension/apiregions/api/artifacts/VersionRuleTest.java
b/src/test/java/org/apache/sling/feature/extension/apiregions/api/artifacts/VersionRuleTest.java
index e0d2dc0..6497eb5 100644
---
a/src/test/java/org/apache/sling/feature/extension/apiregions/api/artifacts/VersionRuleTest.java
+++
b/src/test/java/org/apache/sling/feature/extension/apiregions/api/artifacts/VersionRuleTest.java
@@ -22,6 +22,7 @@ import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import java.io.IOException;
+import java.util.Calendar;
import jakarta.json.Json;
@@ -43,6 +44,7 @@ public class VersionRuleTest {
entity.setMode(Mode.LENIENT);
entity.setMessage("msg");
entity.setArtifactId(ArtifactId.parse("g:a:1"));
+ entity.setEnforceOn("2024-01-01");
entity.clear();
assertTrue(entity.getAttributes().isEmpty());
assertNull(entity.getAllowedVersionRanges());
@@ -50,11 +52,12 @@ public class VersionRuleTest {
assertNull(entity.getMessage());
assertNull(entity.getArtifactId());
assertNull(entity.getMode());
+ assertNull(entity.getEnforceOn());
}
@Test public void testFromJSONObject() throws IOException {
final Extension ext = new Extension(ExtensionType.JSON, "a",
ExtensionState.OPTIONAL);
- ext.setJSON("{ \"mode\" : \"LENIENT\", \"message\" : \"msg\",
\"artifact-id\":\"g:a:1\","
+ ext.setJSON("{ \"mode\" : \"LENIENT\", \"message\" : \"msg\",
\"artifact-id\":\"g:a:1\","
+
"\"allowed-version-ranges\":[\"1.0\"],\"denied-version-ranges\":[\"2.0\"]}");
final VersionRule entity = new VersionRule();
@@ -66,6 +69,7 @@ public class VersionRuleTest {
assertEquals(new VersionRange("1.0"),
entity.getAllowedVersionRanges()[0]);
assertEquals(1, entity.getDeniedVersionRanges().length);
assertEquals(new VersionRange("2.0"),
entity.getDeniedVersionRanges()[0]);
+ assertNull(entity.getEnforceOn());
}
@Test public void testToJSONObject() throws IOException {
@@ -77,12 +81,45 @@ public class VersionRuleTest {
entity.setDeniedVersionRanges(new VersionRange[] {new
VersionRange("2.0.0")});
final Extension ext = new Extension(ExtensionType.JSON, "a",
ExtensionState.OPTIONAL);
- ext.setJSON("{ \"mode\" : \"LENIENT\", \"artifact-id\":\"g:a:1\",
\"message\" : \"msg\","
+ ext.setJSON("{ \"mode\" : \"LENIENT\", \"artifact-id\":\"g:a:1\",
\"message\" : \"msg\","
+
"\"allowed-version-ranges\":[\"1.0.0\"],\"denied-version-ranges\":[\"2.0.0\"]}");
assertEquals(ext.getJSONStructure().asJsonObject(),
entity.toJSONObject());
}
+ @Test public void testFromJSONObjectWithEnforceOn() throws IOException {
+ final Extension ext = new Extension(ExtensionType.JSON, "a",
ExtensionState.OPTIONAL);
+ ext.setJSON("{ \"mode\" : \"LENIENT\", \"message\" : \"msg\",
\"artifact-id\":\"g:a:1\","
+ +
"\"allowed-version-ranges\":[\"1.0\"],\"denied-version-ranges\":[\"2.0\"],\"enforce-on\":\"2024-02-02\"}");
+
+ final VersionRule entity = new VersionRule();
+ entity.fromJSONObject(ext.getJSONStructure().asJsonObject());
+ assertEquals(Mode.LENIENT, entity.getMode());
+ assertEquals("msg", entity.getMessage());
+ assertEquals(ArtifactId.parse("g:a:1"), entity.getArtifactId());
+ assertEquals(1, entity.getAllowedVersionRanges().length);
+ assertEquals(new VersionRange("1.0"),
entity.getAllowedVersionRanges()[0]);
+ assertEquals(1, entity.getDeniedVersionRanges().length);
+ assertEquals(new VersionRange("2.0"),
entity.getDeniedVersionRanges()[0]);
+ assertEquals("2024-02-02", entity.getEnforceOn());
+ }
+
+ @Test public void testToJSONObjectWithEnforceOn() throws IOException {
+ final VersionRule entity = new VersionRule();
+ entity.setMode(Mode.LENIENT);
+ entity.setMessage("msg");
+ entity.setArtifactId(ArtifactId.parse("g:a:1"));
+ entity.setAllowedVersionRanges(new VersionRange[] {new
VersionRange("1.0.0")});
+ entity.setDeniedVersionRanges(new VersionRange[] {new
VersionRange("2.0.0")});
+ entity.setEnforceOn("2024-02-02");
+
+ final Extension ext = new Extension(ExtensionType.JSON, "a",
ExtensionState.OPTIONAL);
+ ext.setJSON("{ \"mode\" : \"LENIENT\", \"artifact-id\":\"g:a:1\",
\"message\" : \"msg\","
+ +
"\"allowed-version-ranges\":[\"1.0.0\"],\"denied-version-ranges\":[\"2.0.0\"],\"enforce-on\":\"2024-02-02\"}");
+
+ assertEquals(ext.getJSONStructure().asJsonObject(),
entity.toJSONObject());
+ }
+
@Test public void testIsAllowedNoRanges() {
final VersionRule entity = new VersionRule();
assertFalse(entity.isAllowed(new Version("1.0")));
@@ -108,4 +145,19 @@ public class VersionRuleTest {
assertTrue(entity.isAllowed(new Version("1.3.2")));
assertFalse(entity.isAllowed(new Version("2.1")));
}
+
+ @Test public void testSetEnforceOn() {
+ final VersionRule entity = new VersionRule();
+ entity.setEnforceOn("2024-01-01");
+ assertEquals("2024-01-01", entity.getEnforceOn());
+ final Calendar c = entity.getEnforceOnDate();
+ assertEquals(2024, c.get(Calendar.YEAR));
+ assertEquals(0, c.get(Calendar.MONTH));
+ assertEquals(1, c.get(Calendar.DAY_OF_MONTH));
+ }
+
+ @Test(expected = IllegalArgumentException.class) public void
testSetEnforceOnInvalid() {
+ final VersionRule entity = new VersionRule();
+ entity.setEnforceOn("invalid-date");
+ }
}