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-resourceresolver.git
The following commit(s) were added to refs/heads/master by this push: new 5cd101b Issues/sling 11742 (#97) 5cd101b is described below commit 5cd101ba7257445cf2accea4d508e4c4ccba0584 Author: Carsten Ziegeler <cziege...@apache.org> AuthorDate: Wed Sep 13 14:39:43 2023 +0200 Issues/sling 11742 (#97) * [SLING-11742] Provide alternative equitable terminology for properties * Implement PR feedback. * Implement PR feedback. * Remove metatype info for old properties, move vanity path confiuguration to separate configurer * Update logging and configuration handling * Move vanity configuration to configurer class * Use separate annotation for old properties * Fix handling of missing config properties, improve logging * Switch to allow/deny list everywhere --------- Co-authored-by: cristian cioriia <cior...@adobe.com> --- .../impl/CommonResourceResolverFactoryImpl.java | 33 ++--- .../impl/ResourceResolverFactoryActivator.java | 114 ++++------------- .../impl/ResourceResolverFactoryConfig.java | 13 +- .../impl/ResourceResolverFactoryImpl.java | 2 +- .../impl/VanityPathConfigurer.java | 142 +++++++++++++++++++++ .../impl/mapping/MapConfigurationProvider.java | 2 +- .../resourceresolver/impl/mapping/MapEntries.java | 4 +- .../impl/MockedResourceResolverImplTest.java | 6 +- .../impl/VanityPathConfigurerTest.java | 72 +++++++++++ 9 files changed, 263 insertions(+), 125 deletions(-) diff --git a/src/main/java/org/apache/sling/resourceresolver/impl/CommonResourceResolverFactoryImpl.java b/src/main/java/org/apache/sling/resourceresolver/impl/CommonResourceResolverFactoryImpl.java index 43d2683..d04942f 100644 --- a/src/main/java/org/apache/sling/resourceresolver/impl/CommonResourceResolverFactoryImpl.java +++ b/src/main/java/org/apache/sling/resourceresolver/impl/CommonResourceResolverFactoryImpl.java @@ -388,12 +388,12 @@ public class CommonResourceResolverFactoryImpl implements MapConfigurationProvid @Override public int getDefaultVanityPathRedirectStatus() { - return this.activator.getDefaultVanityPathRedirectStatus(); + return this.activator.getVanityPathConfigurer().getDefaultVanityPathRedirectStatus(); } @Override public boolean isVanityPathCacheInitInBackground() { - return this.activator.isVanityPathCacheInitInBackground(); + return this.activator.getVanityPathConfigurer().isVanityPathCacheInitInBackground(); } /** @@ -415,22 +415,22 @@ public class CommonResourceResolverFactoryImpl implements MapConfigurationProvid @Override public boolean isVanityPathEnabled() { - return this.activator.isVanityPathEnabled(); + return this.activator.getVanityPathConfigurer().isVanityPathEnabled(); } @Override public long getMaxCachedVanityPathEntries() { - return this.activator.getMaxCachedVanityPathEntries(); + return this.activator.getVanityPathConfigurer().getMaxCachedVanityPathEntries(); } @Override public boolean isMaxCachedVanityPathEntriesStartup() { - return this.activator.isMaxCachedVanityPathEntriesStartup(); + return this.activator.getVanityPathConfigurer().isMaxCachedVanityPathEntriesStartup(); } @Override public int getVanityBloomFilterMaxBytes() { - return this.activator.getVanityBloomFilterMaxBytes(); + return this.activator.getVanityPathConfigurer().getVanityBloomFilterMaxBytes(); } @Override @@ -440,7 +440,7 @@ public class CommonResourceResolverFactoryImpl implements MapConfigurationProvid @Override public boolean hasVanityPathPrecedence() { - return this.activator.hasVanityPathPrecedence(); + return this.activator.getVanityPathConfigurer().hasVanityPathPrecedence(); } @Override @@ -450,24 +450,7 @@ public class CommonResourceResolverFactoryImpl implements MapConfigurationProvid @Override public List<VanityPathConfig> getVanityPathConfig() { - final String[] includes = this.activator.getVanityPathWhiteList(); - final String[] excludes = this.activator.getVanityPathBlackList(); - if ( includes == null && excludes == null ) { - return null; - } - final List<VanityPathConfig> configs = new ArrayList<>(); - if ( includes != null ) { - for(final String val : includes) { - configs.add(new VanityPathConfig(val, false)); - } - } - if ( excludes != null ) { - for(final String val : excludes) { - configs.add(new VanityPathConfig(val, true)); - } - } - Collections.sort(configs); - return configs; + return this.activator.getVanityPathConfigurer().getVanityPathConfig(); } @Override diff --git a/src/main/java/org/apache/sling/resourceresolver/impl/ResourceResolverFactoryActivator.java b/src/main/java/org/apache/sling/resourceresolver/impl/ResourceResolverFactoryActivator.java index 9e727c7..1f14e3c 100644 --- a/src/main/java/org/apache/sling/resourceresolver/impl/ResourceResolverFactoryActivator.java +++ b/src/main/java/org/apache/sling/resourceresolver/impl/ResourceResolverFactoryActivator.java @@ -21,8 +21,16 @@ package org.apache.sling.resourceresolver.impl; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; -import java.util.*; - +import java.util.ArrayList; +import java.util.Collections; +import java.util.Dictionary; +import java.util.HashSet; +import java.util.Hashtable; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Set; +import java.util.TreeSet; import org.apache.commons.collections4.BidiMap; import org.apache.commons.collections4.bidimap.TreeBidiMap; @@ -68,7 +76,6 @@ import org.slf4j.LoggerFactory; @Component(name = "org.apache.sling.jcr.resource.internal.JcrResourceResolverFactoryImpl") public class ResourceResolverFactoryActivator { - private static final class FactoryRegistration { /** Registration .*/ public volatile ServiceRegistration<ResourceResolverFactory> factoryRegistration; @@ -79,7 +86,6 @@ public class ResourceResolverFactoryActivator { public volatile CommonResourceResolverFactoryImpl commonFactory; } - /** Logger. */ private final Logger logger = LoggerFactory.getLogger(this.getClass()); @@ -131,12 +137,6 @@ public class ResourceResolverFactoryActivator { @SuppressWarnings("java:S3077") private volatile Set<String> allowedAliasLocations = Collections.emptySet(); - /** Vanity path whitelist */ - private volatile String[] vanityPathWhiteList; - - /** Vanity path blacklist */ - private volatile String[] vanityPathBlackList; - /** Observation paths */ private volatile Path[] observationPaths; @@ -145,6 +145,11 @@ public class ResourceResolverFactoryActivator { /** Factory registration. */ private volatile FactoryRegistration factoryRegistration; + private final VanityPathConfigurer vanityPathConfigurer = new VanityPathConfigurer(); + { + vanityPathConfigurer.setConfiguration(DEFAULT_CONFIG, null); + } + /** * Get the resource decorator tracker. */ @@ -200,18 +205,6 @@ public class ResourceResolverFactoryActivator { || path.startsWith(this.mapRootPrefix); } - public int getDefaultVanityPathRedirectStatus() { - return config.resource_resolver_default_vanity_redirect_status(); - } - - public boolean isVanityPathEnabled() { - return this.config.resource_resolver_enable_vanitypath(); - } - - public boolean isVanityPathCacheInitInBackground() { - return this.config.resource_resolver_vanitypath_cache_in_background(); - } - public boolean isOptimizeAliasResolutionEnabled() { return this.config.resource_resolver_optimize_alias_resolution(); } @@ -224,30 +217,6 @@ public class ResourceResolverFactoryActivator { return this.config.resource_resolver_log_unclosed(); } - public String[] getVanityPathWhiteList() { - return this.vanityPathWhiteList; - } - - public String[] getVanityPathBlackList() { - return this.vanityPathBlackList; - } - - public boolean hasVanityPathPrecedence() { - return this.config.resource_resolver_vanity_precedence(); - } - - public long getMaxCachedVanityPathEntries() { - return this.config.resource_resolver_vanitypath_maxEntries(); - } - - public boolean isMaxCachedVanityPathEntriesStartup() { - return this.config.resource_resolver_vanitypath_maxEntries_startup(); - } - - public int getVanityBloomFilterMaxBytes() { - return this.config.resource_resolver_vanitypath_bloomfilter_maxBytes(); - } - public boolean shouldLogResourceResolverClosing() { return this.config.resource_resolver_log_closing(); } @@ -256,13 +225,20 @@ public class ResourceResolverFactoryActivator { return this.observationPaths; } + public VanityPathConfigurer getVanityPathConfigurer() { + return this.vanityPathConfigurer; + } + // ---------- SCR Integration --------------------------------------------- /** * Activates this component (called by SCR before) */ @Activate - protected void activate(final BundleContext bundleContext, final ResourceResolverFactoryConfig config) { + protected void activate(final BundleContext bundleContext, + final ResourceResolverFactoryConfig config, + final VanityPathConfigurer.DeprecatedVanityConfig deprecatedVanityConfig) { + this.vanityPathConfigurer.setConfiguration(config, deprecatedVanityConfig); this.bundleContext = bundleContext; this.config = config; @@ -339,43 +315,6 @@ public class ResourceResolverFactoryActivator { } } - // vanity path white list - this.vanityPathWhiteList = null; - String[] vanityPathPrefixes = config.resource_resolver_vanitypath_whitelist(); - if ( vanityPathPrefixes != null ) { - final List<String> prefixList = new ArrayList<>(); - for(final String value : vanityPathPrefixes) { - if ( value.trim().length() > 0 ) { - if ( value.trim().endsWith("/") ) { - prefixList.add(value.trim()); - } else { - prefixList.add(value.trim() + "/"); - } - } - } - if ( prefixList.size() > 0 ) { - this.vanityPathWhiteList = prefixList.toArray(new String[prefixList.size()]); - } - } - // vanity path black list - this.vanityPathBlackList = null; - vanityPathPrefixes = config.resource_resolver_vanitypath_blacklist(); - if ( vanityPathPrefixes != null ) { - final List<String> prefixList = new ArrayList<>(); - for(final String value : vanityPathPrefixes) { - if ( value.trim().length() > 0 ) { - if ( value.trim().endsWith("/") ) { - prefixList.add(value.trim()); - } else { - prefixList.add(value.trim() + "/"); - } - } - } - if ( prefixList.size() > 0 ) { - this.vanityPathBlackList = prefixList.toArray(new String[prefixList.size()]); - } - } - // check for required property Set<String> requiredResourceProvidersLegacy = getStringSet(config.resource_resolver_required_providers()); Set<String> requiredResourceProviderNames = getStringSet(config.resource_resolver_required_providernames()); @@ -454,9 +393,11 @@ public class ResourceResolverFactoryActivator { * Modifies this component (called by SCR to update this component) */ @Modified - protected void modified(final BundleContext bundleContext, final ResourceResolverFactoryConfig config) { + protected void modified(final BundleContext bundleContext, + final ResourceResolverFactoryConfig config, + final VanityPathConfigurer.DeprecatedVanityConfig deprecatedVanityConfig) { this.deactivate(); - this.activate(bundleContext, config); + this.activate(bundleContext, config, deprecatedVanityConfig); } /** @@ -468,6 +409,7 @@ public class ResourceResolverFactoryActivator { this.bundleContext = null; this.config = DEFAULT_CONFIG; + this.vanityPathConfigurer.setConfiguration(DEFAULT_CONFIG, null); this.changeListenerWhiteboard.deactivate(); this.changeListenerWhiteboard = null; this.resourceProviderTracker.deactivate(); diff --git a/src/main/java/org/apache/sling/resourceresolver/impl/ResourceResolverFactoryConfig.java b/src/main/java/org/apache/sling/resourceresolver/impl/ResourceResolverFactoryConfig.java index 0d00498..1c16e96 100644 --- a/src/main/java/org/apache/sling/resourceresolver/impl/ResourceResolverFactoryConfig.java +++ b/src/main/java/org/apache/sling/resourceresolver/impl/ResourceResolverFactoryConfig.java @@ -159,18 +159,17 @@ public @interface ResourceResolverFactoryConfig { "are considered. If the list is empty, all paths are used.)") String[] resource_resolver_allowed_alias_locations(); - @AttributeDefinition(name = "Allowed Vanity Path Location", description ="This setting can contain a list of path prefixes, e.g. /libs/, /content/. If " + - "such a list is configured, only vanity paths from resources starting with this prefix " + - " are considered. If the list is empty, all vanity paths are used.") - String[] resource_resolver_vanitypath_whitelist(); + "such a list is configured, only vanity paths from resources starting with this prefix " + + " are considered. If the list is empty, all vanity paths are used.") + String[] resource_resolver_vanitypath_allowlist(); @AttributeDefinition(name = "Denied Vanity Path Location", description ="This setting can contain a list of path prefixes, e.g. /misc/. If " + - "such a list is configured,vanity paths from resources starting with this prefix " + - " are not considered. If the list is empty, all vanity paths are used.") - String[] resource_resolver_vanitypath_blacklist(); + "such a list is configured,vanity paths from resources starting with this prefix " + + " are not considered. If the list is empty, all vanity paths are used.") + String[] resource_resolver_vanitypath_denylist(); @AttributeDefinition(name = "Vanity Path Precedence", description ="This flag controls whether vanity paths" + diff --git a/src/main/java/org/apache/sling/resourceresolver/impl/ResourceResolverFactoryImpl.java b/src/main/java/org/apache/sling/resourceresolver/impl/ResourceResolverFactoryImpl.java index 4b9c6f6..9850563 100644 --- a/src/main/java/org/apache/sling/resourceresolver/impl/ResourceResolverFactoryImpl.java +++ b/src/main/java/org/apache/sling/resourceresolver/impl/ResourceResolverFactoryImpl.java @@ -104,7 +104,7 @@ public class ResourceResolverFactoryImpl implements ResourceResolverFactory { @Override public ResourceResolver getAdministrativeResourceResolver( Map<String, Object> authenticationInfo) throws LoginException { - // usingBundle is required as bundles must now be whitelisted to use this method + // usingBundle is required as bundles must now be allow listed to use this method if (usingBundle == null) { throw new LoginException("usingBundle is null"); } diff --git a/src/main/java/org/apache/sling/resourceresolver/impl/VanityPathConfigurer.java b/src/main/java/org/apache/sling/resourceresolver/impl/VanityPathConfigurer.java new file mode 100644 index 0000000..f6808f1 --- /dev/null +++ b/src/main/java/org/apache/sling/resourceresolver/impl/VanityPathConfigurer.java @@ -0,0 +1,142 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.sling.resourceresolver.impl; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.apache.sling.resourceresolver.impl.mapping.MapConfigurationProvider.VanityPathConfig; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +class VanityPathConfigurer { + + public @interface DeprecatedVanityConfig { + + /** This is the deprecated fallback configuration for resource_resolver_vanitypath_allowlist() */ + String[] resource_resolver_vanitypath_whitelist(); + + /** This is the deprecated fallback configuration for resource_resolver_vanitypath_denylist() */ + String[] resource_resolver_vanitypath_blacklist(); + } + + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + private volatile ResourceResolverFactoryConfig config; + + private volatile List<VanityPathConfig> vanityPathConfig; + + public void setConfiguration(final ResourceResolverFactoryConfig c, final DeprecatedVanityConfig deprecatedConfig) { + this.config = c; + this.vanityPathConfig = null; + + final List<String> includes = this.configureVanityPathPrefixes(c.resource_resolver_vanitypath_allowlist(), + deprecatedConfig == null ? null : deprecatedConfig.resource_resolver_vanitypath_whitelist(), + "resource.resolver.vanitypath.allowlist", + "resource.resolver.vanitypath.whitelist"); + + final List<String> excludes = this.configureVanityPathPrefixes(c.resource_resolver_vanitypath_denylist(), + deprecatedConfig == null ? null : deprecatedConfig.resource_resolver_vanitypath_blacklist(), + "resource.resolver.vanitypath.denylist", + "resource.resolver.vanitypath.blacklist"); + if ( includes != null || excludes != null ) { + this.vanityPathConfig = new ArrayList<>(); + if ( includes != null ) { + for(final String val : includes) { + this.vanityPathConfig.add(new VanityPathConfig(val, false)); + } + } + if ( excludes != null ) { + for(final String val : excludes) { + this.vanityPathConfig.add(new VanityPathConfig(val, true)); + } + } + Collections.sort(this.vanityPathConfig); + } + } + + public int getDefaultVanityPathRedirectStatus() { + return config.resource_resolver_default_vanity_redirect_status(); + } + + public boolean isVanityPathEnabled() { + return this.config.resource_resolver_enable_vanitypath(); + } + + public boolean isVanityPathCacheInitInBackground() { + return this.config.resource_resolver_vanitypath_cache_in_background(); + } + + public List<VanityPathConfig> getVanityPathConfig() { + return this.vanityPathConfig; + } + + + public boolean hasVanityPathPrecedence() { + return this.config.resource_resolver_vanity_precedence(); + } + + public long getMaxCachedVanityPathEntries() { + return this.config.resource_resolver_vanitypath_maxEntries(); + } + + public boolean isMaxCachedVanityPathEntriesStartup() { + return this.config.resource_resolver_vanitypath_maxEntries_startup(); + } + + public int getVanityBloomFilterMaxBytes() { + return this.config.resource_resolver_vanitypath_bloomfilter_maxBytes(); + } + + private boolean isDefined(final String[] value) { + return value != null && value.length > 0; + } + + List<String> configureVanityPathPrefixes(final String[] pathPrefixes, final String[] pathPrefixesFallback, + String pathPrefixesPropertyName, String pathPrefixesFallbackPropertyName) { + if (isDefined(pathPrefixes) && isDefined(pathPrefixesFallback) ) { + logger.error("Both properties, " + pathPrefixesPropertyName + " and " + pathPrefixesFallbackPropertyName + + ", were defined. Using " + pathPrefixesPropertyName + " for configuring vanity paths. " + + "Please remove the other property from your configuration."); + return filterVanityPathPrefixes(pathPrefixes); + } else if (isDefined(pathPrefixes)) { + return filterVanityPathPrefixes(pathPrefixes); + } else if (isDefined(pathPrefixesFallback)) { + logger.warn("The property " + pathPrefixesPropertyName + " was not set. Using the " + + pathPrefixesFallbackPropertyName + " instead. Please update your configuration to use " + pathPrefixesPropertyName); + return filterVanityPathPrefixes(pathPrefixesFallback); + } + return null; + } + + private static List<String> filterVanityPathPrefixes(final String[] vanityPathPrefixes) { + final List<String> prefixList = new ArrayList<>(); + for (final String value : vanityPathPrefixes) { + if (value.trim().length() > 0) { + if (value.trim().endsWith("/")) { + prefixList.add(value.trim()); + } else { + prefixList.add(value.trim().concat("/")); + } + } + } + return prefixList.isEmpty() ? null : prefixList; + } +} \ No newline at end of file diff --git a/src/main/java/org/apache/sling/resourceresolver/impl/mapping/MapConfigurationProvider.java b/src/main/java/org/apache/sling/resourceresolver/impl/mapping/MapConfigurationProvider.java index d5ab6bd..26bebd6 100644 --- a/src/main/java/org/apache/sling/resourceresolver/impl/mapping/MapConfigurationProvider.java +++ b/src/main/java/org/apache/sling/resourceresolver/impl/mapping/MapConfigurationProvider.java @@ -77,7 +77,7 @@ public interface MapConfigurationProvider extends ResourceResolverFactory { } /** - * A list of white and black list prefixes all ending with a slash. + * A list of allow and deny list prefixes all ending with a slash. * If <code>null</code> is returned, all paths are allowed. */ List<VanityPathConfig> getVanityPathConfig(); diff --git a/src/main/java/org/apache/sling/resourceresolver/impl/mapping/MapEntries.java b/src/main/java/org/apache/sling/resourceresolver/impl/mapping/MapEntries.java index 57ab83a..84b64fd 100644 --- a/src/main/java/org/apache/sling/resourceresolver/impl/mapping/MapEntries.java +++ b/src/main/java/org/apache/sling/resourceresolver/impl/mapping/MapEntries.java @@ -1002,7 +1002,7 @@ public class MapEntries implements return false; } - // check white list + // check allow/deny list if ( this.factory.getVanityPathConfig() != null ) { boolean allowed = false; for(final VanityPathConfig config : this.factory.getVanityPathConfig()) { @@ -1012,7 +1012,7 @@ public class MapEntries implements } } if ( !allowed ) { - log.debug("isValidVanityPath: not valid as not in white list {}", path); + log.debug("isValidVanityPath: not valid as not in allow list {}", path); return false; } } diff --git a/src/test/java/org/apache/sling/resourceresolver/impl/MockedResourceResolverImplTest.java b/src/test/java/org/apache/sling/resourceresolver/impl/MockedResourceResolverImplTest.java index 2594e88..8cfd4e0 100644 --- a/src/test/java/org/apache/sling/resourceresolver/impl/MockedResourceResolverImplTest.java +++ b/src/test/java/org/apache/sling/resourceresolver/impl/MockedResourceResolverImplTest.java @@ -196,7 +196,7 @@ public class MockedResourceResolverImplTest { } @Override - public String[] resource_resolver_vanitypath_whitelist() { + public String[] resource_resolver_vanitypath_allowlist() { return null; } @@ -216,7 +216,7 @@ public class MockedResourceResolverImplTest { } @Override - public String[] resource_resolver_vanitypath_blacklist() { + public String[] resource_resolver_vanitypath_denylist() { return null; } @@ -306,7 +306,7 @@ public class MockedResourceResolverImplTest { public boolean resource_resolver_vanitypath_cache_in_background() { return false; } - }); + }, null); // configure using Bundle Mockito.when(usingBundle.getBundleContext()).thenReturn(usingBundleContext); diff --git a/src/test/java/org/apache/sling/resourceresolver/impl/VanityPathConfigurerTest.java b/src/test/java/org/apache/sling/resourceresolver/impl/VanityPathConfigurerTest.java new file mode 100644 index 0000000..683d095 --- /dev/null +++ b/src/test/java/org/apache/sling/resourceresolver/impl/VanityPathConfigurerTest.java @@ -0,0 +1,72 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.sling.resourceresolver.impl; + +import org.junit.Before; +import org.junit.Test; +import static org.junit.Assert.assertEquals; + +import java.util.List; + +public class VanityPathConfigurerTest { + private VanityPathConfigurer vanityPathConfigurer; + + @Before + public void before() { + vanityPathConfigurer = new VanityPathConfigurer(); + } + + @Test + public void testConfigureVanityPathPrefixes_givenBothPathPrefixAndFallBack_thenPathPrefixIsUsed() { + String[] pathPrefixes = {"/some/path/"}; + String[] pathPrefixesFallback = {"/some/fallback/path/"}; + + final List<String> result = vanityPathConfigurer.configureVanityPathPrefixes(pathPrefixes, pathPrefixesFallback, + "original", "fallback"); + verifyResults(result, pathPrefixes); + } + + @Test + public void testConfigureVanityPathPrefixes_givenOnlyPathPrefix_thenPathPrefixIsUsed() { + String[] pathPrefixes = {"/some/path/"}; + String[] pathPrefixesFallback = null; + + final List<String> result = vanityPathConfigurer.configureVanityPathPrefixes(pathPrefixes, pathPrefixesFallback, + "original", "fallback"); + verifyResults(result, pathPrefixes); + } + + @Test + public void testConfigureVanityPathPrefixes_givenOnlyPathPrefixFallback_thenPathPrefixFallbackIsUsed() { + String[] pathPrefixes = null; + String[] pathPrefixesFallback = {"/some/fallback/path/"}; + + final List<String> result = vanityPathConfigurer.configureVanityPathPrefixes(pathPrefixes, pathPrefixesFallback, + "original", "fallback"); + verifyResults(result, pathPrefixesFallback); + } + + private void verifyResults(List<String> actualResult, String[] expectedResults) { + assertEquals(expectedResults.length, actualResult.size()); + for(int i=0; i<expectedResults.length; i++) { + assertEquals(expectedResults[i], actualResult.get(i)); + } + } + +}