SLING-6707 - LoginAdminWhitelist.fragment metatype descriptor not as intended
- add description for whitelist.bundles.regexp
- remove whitelist.bundles.default and whitelist.bundles.additional from metatype
and handle them separately
- refactor handling of backwards compatibility for above properties
git-svn-id: https://svn.apache.org/repos/asf/sling/trunk@1788436 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/src/main/java/org/apache/sling/jcr/base/internal/LoginAdminWhitelist.java b/src/main/java/org/apache/sling/jcr/base/internal/LoginAdminWhitelist.java
index 104d13f..5bd5d38 100644
--- a/src/main/java/org/apache/sling/jcr/base/internal/LoginAdminWhitelist.java
+++ b/src/main/java/org/apache/sling/jcr/base/internal/LoginAdminWhitelist.java
@@ -19,6 +19,8 @@
package org.apache.sling.jcr.base.internal;
import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.regex.Pattern;
@@ -36,6 +38,8 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import static org.apache.sling.commons.osgi.PropertiesUtil.toStringArray;
+
/**
* Whitelist that defines which bundles can use the
* {@link SlingRepository#loginAdministrative} method.
@@ -59,13 +63,15 @@
private volatile ConfigurationState config;
- // for backwards compatibility only
- private volatile WhitelistFragment defaultFragment;
+ private final List<WhitelistFragment> whitelistFragments = new CopyOnWriteArrayList<WhitelistFragment>();
- // for backwards compatibility only
- private volatile WhitelistFragment additionalFragment;
+ // for backwards compatibility only (read properties directly to prevent them from appearing in the metatype)
+ private static final String PROP_WHITELIST_BUNDLES_DEFAULT = "whitelist.bundles.default";
- private final List<WhitelistFragment> whitelistFragments = new CopyOnWriteArrayList<>();
+ private static final String PROP_WHITELIST_BUNDLES_ADDITIONAL = "whitelist.bundles.additional";
+
+ private final Map<String, WhitelistFragment> backwardsCompatibleFragments =
+ new ConcurrentHashMap<String, WhitelistFragment>();
@Reference(
cardinality = ReferenceCardinality.MULTIPLE,
@@ -84,9 +90,10 @@
}
@Activate @Modified @SuppressWarnings("unused")
- void configure(LoginAdminWhitelistConfiguration configuration) {
+ void configure(LoginAdminWhitelistConfiguration configuration, Map<String, Object> properties) {
this.config = new ConfigurationState(configuration);
- backwardsCompatibility(configuration);
+ ensureBackwardsCompatibility(properties, PROP_WHITELIST_BUNDLES_DEFAULT);
+ ensureBackwardsCompatibility(properties, PROP_WHITELIST_BUNDLES_ADDITIONAL);
}
public boolean allowLoginAdministrative(Bundle b) {
@@ -130,7 +137,7 @@
final String regexp = config.whitelist_bundles_regexp();
if(regexp.trim().length() > 0) {
whitelistRegexp = Pattern.compile(regexp);
- LOG.warn("A whitelist.bundles.regexp is configured, this is NOT RECOMMENDED for production: {}",
+ LOG.warn("A 'whitelist.bundles.regexp' is configured, this is NOT RECOMMENDED for production: {}",
whitelistRegexp);
} else {
whitelistRegexp = null;
@@ -139,7 +146,7 @@
bypassWhitelist = config.whitelist_bypass();
if(bypassWhitelist) {
LOG.info("bypassWhitelist=true, whitelisted BSNs=<ALL>");
- LOG.warn("All bundles are allowed to use loginAdministrative due to the 'bypass whitelist' " +
+ LOG.warn("All bundles are allowed to use loginAdministrative due to the 'whitelist.bypass' " +
"configuration of this service. This is NOT RECOMMENDED, for security reasons."
);
}
@@ -147,25 +154,19 @@
}
@SuppressWarnings("deprecated")
- private void backwardsCompatibility(final LoginAdminWhitelistConfiguration configuration) {
- if (defaultFragment != null) {
- unbindWhitelistFragment(defaultFragment);
+ private void ensureBackwardsCompatibility(final Map<String, Object> properties, final String propertyName) {
+ final WhitelistFragment oldFragment = backwardsCompatibleFragments.remove(propertyName);
+
+ final String[] bsns = toStringArray(properties.get(propertyName), new String[0]);
+ if (bsns.length != 0) {
+ LOG.warn("Using deprecated configuration property '{}'", propertyName);
+ final WhitelistFragment fragment = new WhitelistFragment("deprecated-" + propertyName, bsns);
+ bindWhitelistFragment(fragment);
+ backwardsCompatibleFragments.put(propertyName, fragment);
}
- if (additionalFragment != null) {
- unbindWhitelistFragment(additionalFragment);
- }
- final String[] defaultBsns = configuration.whitelist_bundles_default();
- if (defaultBsns != null && defaultBsns.length != 0) {
- LOG.warn("Using deprecated configuration property 'whitelist.bundles.default'");
- defaultFragment = new WhitelistFragment("deprecated-whitelist.bundles.default", defaultBsns);
- bindWhitelistFragment(defaultFragment);
- }
-
- final String[] additionalBsns = configuration.whitelist_bundles_additional();
- if (additionalBsns != null && additionalBsns.length != 0) {
- LOG.warn("Using deprecated configuration property 'whitelist.bundles.additional'");
- additionalFragment = new WhitelistFragment("deprecated-whitelist.bundles.additional", additionalBsns);
- bindWhitelistFragment(additionalFragment);
+
+ if (oldFragment != null) {
+ unbindWhitelistFragment(oldFragment);
}
}
}
diff --git a/src/main/java/org/apache/sling/jcr/base/internal/LoginAdminWhitelistConfiguration.java b/src/main/java/org/apache/sling/jcr/base/internal/LoginAdminWhitelistConfiguration.java
index 8c96c3f..62df245 100644
--- a/src/main/java/org/apache/sling/jcr/base/internal/LoginAdminWhitelistConfiguration.java
+++ b/src/main/java/org/apache/sling/jcr/base/internal/LoginAdminWhitelistConfiguration.java
@@ -53,23 +53,11 @@
*
* @return The configured regular exression.
*/
+ @AttributeDefinition(
+ name = "Whitelist regexp",
+ description = "Regular expression for bundle symbolic names for which loginAdministrative() " +
+ "is allowed. NOT recommended for production use, but useful for testing with " +
+ "generated bundles."
+ )
String whitelist_bundles_regexp() default "";
-
- /**
- * Default list of bundle symbolic names for which loginAdministrative() is allowed.
- *
- * @return The default whitelisted BSNs
- * @deprecated use {@link WhitelistFragment} configurations instead
- */
- @Deprecated
- String[] whitelist_bundles_default() default {};
-
- /**
- * Additional list of bundle symbolic names for which loginAdministrative() is allowed.
- *
- * @return Additional whitelisted BSNs
- * @deprecated use {@link WhitelistFragment} configurations instead
- */
- @Deprecated
- String[] whitelist_bundles_additional() default {};
}
diff --git a/src/main/java/org/apache/sling/jcr/base/internal/WhitelistFragment.java b/src/main/java/org/apache/sling/jcr/base/internal/WhitelistFragment.java
index 6ff49a9..81184a4 100644
--- a/src/main/java/org/apache/sling/jcr/base/internal/WhitelistFragment.java
+++ b/src/main/java/org/apache/sling/jcr/base/internal/WhitelistFragment.java
@@ -25,7 +25,9 @@
import org.osgi.service.metatype.annotations.Designate;
import org.osgi.service.metatype.annotations.ObjectClassDefinition;
-import java.util.List;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
import static java.util.Arrays.asList;
@@ -62,23 +64,24 @@
private String name;
- private List<String> bundles;
+ private Set<String> bundles;
@SuppressWarnings("unused")
public WhitelistFragment() {
// default constructor for SCR
}
+ // constructor for tests and for backwards compatible deprecated fragments
WhitelistFragment(String name, String[] bundles) {
this.name = name;
- this.bundles = asList(bundles);
+ this.bundles = asSet(bundles);
}
@Activate
@SuppressWarnings("unused")
void activate(Configuration config) {
name = config.whitelist_name();
- bundles = asList(config.whitelist_bundles() == null ? new String[0] : config.whitelist_bundles());
+ bundles = asSet(config.whitelist_bundles());
}
boolean allows(String bsn) {
@@ -89,4 +92,28 @@
public String toString() {
return name + ": " + bundles + "";
}
+
+ @Override
+ public boolean equals(final Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (!(o instanceof WhitelistFragment)) {
+ return false;
+ }
+ final WhitelistFragment that = (WhitelistFragment) o;
+ return name.equals(that.name)
+ && bundles.equals(that.bundles);
+ }
+
+ @Override
+ public int hashCode() {
+ int result = name.hashCode();
+ result = 31 * result + bundles.hashCode();
+ return result;
+ }
+
+ private Set<String> asSet(final String[] values) {
+ return Collections.unmodifiableSet(new HashSet<String>(asList(values)));
+ }
}
diff --git a/src/test/java/org/apache/sling/jcr/base/internal/LoginAdminWhitelistTest.java b/src/test/java/org/apache/sling/jcr/base/internal/LoginAdminWhitelistTest.java
index 48359a5..bf08545 100644
--- a/src/test/java/org/apache/sling/jcr/base/internal/LoginAdminWhitelistTest.java
+++ b/src/test/java/org/apache/sling/jcr/base/internal/LoginAdminWhitelistTest.java
@@ -59,7 +59,7 @@
@Test
public void testBypassWhitelist() throws ConfigurationException {
- whitelist.configure(config(true, null, null, null));
+ configure(whitelist, true, null, null, null);
for(String bsn : randomBsn()) {
assertAdminLogin(bsn, true);
@@ -71,7 +71,7 @@
final String [] allowed = {
"bundle1", "bundle2"
};
- whitelist.configure(config(null, null, allowed, null));
+ configure(whitelist, null, null, allowed, null);
assertAdminLogin("foo.1.bar", false);
@@ -89,8 +89,7 @@
final String [] allowed = {
"bundle5", "bundle6"
};
- final LoginAdminWhitelistConfiguration config = config(null, null, null, allowed);
- whitelist.configure(config);
+ configure(whitelist, null, null, null, allowed);
assertAdminLogin("foo.1.bar", false);
@@ -105,7 +104,7 @@
@Test
public void testDefaultAndAdditionalConfig() throws ConfigurationException {
- whitelist.configure(config(null, null, new String [] { "defB"}, new String [] { "addB"}));
+ configure(whitelist, null, null, new String [] { "defB"}, new String [] { "addB"});
assertAdminLogin("defB", true);
assertAdminLogin("addB", true);
@@ -121,7 +120,7 @@
final String [] allowed = {
"bundle3", "bundle4"
};
- whitelist.configure(config(null, "foo.*bar", allowed, null));
+ configure(whitelist, null, "foo.*bar", allowed, null);
assertAdminLogin("foo.2.bar", true);
assertAdminLogin("foo.somethingElse.bar", true);
@@ -144,7 +143,7 @@
final WhitelistFragment testFragment1 = new WhitelistFragment("test1", allowed1);
final WhitelistFragment testFragment2 = new WhitelistFragment("test2", allowed2);
- whitelist.configure(config(null, null, null, null));
+ configure(whitelist, null, null, null, null);
whitelist.bindWhitelistFragment(testFragment1);
whitelist.bindWhitelistFragment(testFragment2);
@@ -171,8 +170,7 @@
}
}
-
- private LoginAdminWhitelistConfiguration config(final Boolean bypass, final String regexp, final String[] defaultBSNs, final String[] additionalBSNs) throws ConfigurationException {
+ private void configure(final LoginAdminWhitelist whitelist, final Boolean bypass, final String regexp, final String[] defaultBSNs, final String[] additionalBSNs) throws ConfigurationException {
final Hashtable<String, Object> props = new Hashtable<>();
if (bypass != null) {
props.put("whitelist.bypass", bypass);
@@ -186,6 +184,8 @@
if (additionalBSNs != null) {
props.put("whitelist.bundles.additional", additionalBSNs);
}
- return ConfigAnnotationUtil.fromDictionary(LoginAdminWhitelistConfiguration.class, props);
+ LoginAdminWhitelistConfiguration configuration =
+ ConfigAnnotationUtil.fromDictionary(LoginAdminWhitelistConfiguration.class, props);
+ whitelist.configure(configuration, props);
}
}
\ No newline at end of file