This is an automated email from the ASF dual-hosted git repository. andysch pushed a commit to branch feature/SLING-7768 in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-resourceresolver.git
commit 511d33d2c65caa3495f0ec803d6816c002735c6e Author: Andreas Schaefer <[email protected]> AuthorDate: Wed Jul 25 15:18:58 2018 -0700 Rename the PlaceHolderProvider to StringInterpolationProvider and created a test suite to test the String Interpolation Provider with Map Entries --- pom.xml | 3 + .../impl/CommonResourceResolverFactoryImpl.java | 2 +- .../impl/ResourceResolverFactoryActivator.java | 8 +- .../resourceresolver/impl/mapping/MapEntries.java | 14 +- ...vider.java => StringInterpolationProvider.java} | 8 +- ... StringInterpolationProviderConfiguration.java} | 6 +- ...l.java => StringInterpolationProviderImpl.java} | 28 +-- .../impl/mapping/MapEntriesTest.java | 21 ++- .../impl/mapping/PlaceholderProviderImplTest.java | 139 --------------- .../mapping/StringInterpolationMapEntriesTest.java | 195 +++++++++++++++++++++ .../StringInterpolationProviderImplTest.java | 155 ++++++++++++++++ 11 files changed, 398 insertions(+), 181 deletions(-) diff --git a/pom.xml b/pom.xml index e0c613c..5466e8a 100644 --- a/pom.xml +++ b/pom.xml @@ -73,6 +73,9 @@ javax.jcr;resolution:=optional, * </Import-Package> + <Export-Package> + org.apache.sling.resourceresolver.impl.mapping + </Export-Package> <Provide-Capability> osgi.service;objectClass=javax.servlet.Servlet, osgi.service;objectClass=org.apache.sling.api.resource.ResourceResolverFactory, 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 3289098..d393cd8 100644 --- a/src/main/java/org/apache/sling/resourceresolver/impl/CommonResourceResolverFactoryImpl.java +++ b/src/main/java/org/apache/sling/resourceresolver/impl/CommonResourceResolverFactoryImpl.java @@ -322,7 +322,7 @@ public class CommonResourceResolverFactoryImpl implements ResourceResolverFactor } // set up the map entries from configuration try { - mapEntries = new MapEntries(this, bundleContext, this.activator.getEventAdmin(), this.activator.getPlaceholderProvider()); + mapEntries = new MapEntries(this, bundleContext, this.activator.getEventAdmin(), this.activator.getStringInterpolationProvider()); } catch (final Exception e) { logger.error("activate: Cannot access repository, failed setting up Mapping Support", e); } 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 371d5a3..478be4a 100644 --- a/src/main/java/org/apache/sling/resourceresolver/impl/ResourceResolverFactoryActivator.java +++ b/src/main/java/org/apache/sling/resourceresolver/impl/ResourceResolverFactoryActivator.java @@ -39,7 +39,7 @@ import org.apache.sling.api.resource.runtime.RuntimeService; import org.apache.sling.resourceresolver.impl.helper.ResourceDecoratorTracker; import org.apache.sling.resourceresolver.impl.mapping.MapEntries; import org.apache.sling.resourceresolver.impl.mapping.Mapping; -import org.apache.sling.resourceresolver.impl.mapping.PlaceholderProvider; +import org.apache.sling.resourceresolver.impl.mapping.StringInterpolationProvider; import org.apache.sling.resourceresolver.impl.observation.ResourceChangeListenerWhiteboard; import org.apache.sling.resourceresolver.impl.providers.ResourceProviderTracker; import org.apache.sling.resourceresolver.impl.providers.ResourceProviderTracker.ChangeListener; @@ -111,7 +111,7 @@ public class ResourceResolverFactoryActivator { /** Event admin. */ @Reference - PlaceholderProvider placeholderProvider; + StringInterpolationProvider stringInterpolationProvider; /** Service User Mapper */ @Reference @@ -158,8 +158,8 @@ public class ResourceResolverFactoryActivator { return this.eventAdmin; } - public PlaceholderProvider getPlaceholderProvider() { - return placeholderProvider; + public StringInterpolationProvider getStringInterpolationProvider() { + return stringInterpolationProvider; } /** 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 7877171..89fa39b 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 @@ -55,7 +55,6 @@ import javax.servlet.http.HttpServletResponse; import org.apache.sling.api.SlingConstants; import org.apache.sling.api.SlingException; import org.apache.sling.api.resource.LoginException; -import org.apache.sling.api.resource.QuerySyntaxException; import org.apache.sling.api.resource.Resource; import org.apache.sling.api.resource.ResourceResolver; import org.apache.sling.api.resource.ResourceUtil; @@ -69,7 +68,6 @@ import org.apache.sling.resourceresolver.impl.ResourceResolverImpl; import org.apache.sling.resourceresolver.impl.mapping.MapConfigurationProvider.VanityPathConfig; import org.osgi.framework.BundleContext; import org.osgi.framework.Constants; -import org.osgi.framework.ServiceReference; import org.osgi.framework.ServiceRegistration; import org.osgi.service.event.Event; import org.osgi.service.event.EventAdmin; @@ -153,10 +151,10 @@ public class MapEntries implements private Thread aliasTraversal = null; - private PlaceholderProvider placeholderProvider; + private StringInterpolationProvider stringInterpolationProvider; @SuppressWarnings({ "unchecked" }) - public MapEntries(final MapConfigurationProvider factory, final BundleContext bundleContext, final EventAdmin eventAdmin, final PlaceholderProvider placeholderProvider) + public MapEntries(final MapConfigurationProvider factory, final BundleContext bundleContext, final EventAdmin eventAdmin, final StringInterpolationProvider stringInterpolationProvider) throws LoginException, IOException { this.resolver = factory.getServiceResourceResolver(factory.getServiceUserAuthenticationInfo("mapping")); @@ -167,7 +165,7 @@ public class MapEntries implements this.mapMaps = Collections.<MapEntry> emptyList(); this.vanityTargets = Collections.<String,List <String>>emptyMap(); this.aliasMap = Collections.emptyMap(); - this.placeholderProvider = placeholderProvider; + this.stringInterpolationProvider = stringInterpolationProvider; doInit(); @@ -991,9 +989,9 @@ public class MapEntries implements trailingSlash = true; } // Check for placeholders and replace if needed - PlaceholderProvider.Check check = placeholderProvider.hasPlaceholder(name); - if(check.getStatus() == PlaceholderProvider.STATUS.found) { - name = placeholderProvider.resolve(check); + StringInterpolationProvider.Check check = stringInterpolationProvider.hasPlaceholder(name); + if(check.getStatus() == StringInterpolationProvider.STATUS.found) { + name = stringInterpolationProvider.resolve(check); } final String childPath = parentPath.concat(name); diff --git a/src/main/java/org/apache/sling/resourceresolver/impl/mapping/PlaceholderProvider.java b/src/main/java/org/apache/sling/resourceresolver/impl/mapping/StringInterpolationProvider.java similarity index 91% rename from src/main/java/org/apache/sling/resourceresolver/impl/mapping/PlaceholderProvider.java rename to src/main/java/org/apache/sling/resourceresolver/impl/mapping/StringInterpolationProvider.java index 95c01d7..aa398e2 100644 --- a/src/main/java/org/apache/sling/resourceresolver/impl/mapping/PlaceholderProvider.java +++ b/src/main/java/org/apache/sling/resourceresolver/impl/mapping/StringInterpolationProvider.java @@ -25,16 +25,16 @@ import java.util.List; * that depend on the environment like host names / ports for dev, test, * qa, staging, prod systems * - * Placeholders are enclosed in two opening/closing round brackets: {{replaceMe}} + * Placeholders are enclosed in Starting and Ending Delimiters (see PLACEHOLDER_START/END_TOKEN) * The name of the placeholder can contain any character except opening or closing * brackets (no nesting). */ -public interface PlaceholderProvider { +public interface StringInterpolationProvider { enum STATUS {found, unknown, none}; - public static final String PLACEHOLDER_START_TOKEN = "{{"; - public static final String PLACEHOLDER_END_TOKEN = "}}"; + public static final String PLACEHOLDER_START_TOKEN = "${"; + public static final String PLACEHOLDER_END_TOKEN = "}"; /** * Checks if the given values contains a placeholder and if that placeholder is known * @param value String to check diff --git a/src/main/java/org/apache/sling/resourceresolver/impl/mapping/PlaceholderProviderConfiguration.java b/src/main/java/org/apache/sling/resourceresolver/impl/mapping/StringInterpolationProviderConfiguration.java similarity index 87% rename from src/main/java/org/apache/sling/resourceresolver/impl/mapping/PlaceholderProviderConfiguration.java rename to src/main/java/org/apache/sling/resourceresolver/impl/mapping/StringInterpolationProviderConfiguration.java index eea215c..664669e 100644 --- a/src/main/java/org/apache/sling/resourceresolver/impl/mapping/PlaceholderProviderConfiguration.java +++ b/src/main/java/org/apache/sling/resourceresolver/impl/mapping/StringInterpolationProviderConfiguration.java @@ -21,9 +21,9 @@ package org.apache.sling.resourceresolver.impl.mapping; import org.osgi.service.metatype.annotations.AttributeDefinition; import org.osgi.service.metatype.annotations.ObjectClassDefinition; -@ObjectClassDefinition(name = "Apache Sling Placeholder Provider", - description = "Configures the Placeholder Provider and the location of its key/value pairs") -public @interface PlaceholderProviderConfiguration { +@ObjectClassDefinition(name = "Apache Sling String Interpolation Provider", + description = "Configures the String Interpolation Provider and the location of its key/value pairs") +public @interface StringInterpolationProviderConfiguration { @AttributeDefinition( name = "Placeholder Values", description = "A list of key / value pairs separated by a equal (=) sign. " + diff --git a/src/main/java/org/apache/sling/resourceresolver/impl/mapping/PlaceholderProviderImpl.java b/src/main/java/org/apache/sling/resourceresolver/impl/mapping/StringInterpolationProviderImpl.java similarity index 89% rename from src/main/java/org/apache/sling/resourceresolver/impl/mapping/PlaceholderProviderImpl.java rename to src/main/java/org/apache/sling/resourceresolver/impl/mapping/StringInterpolationProviderImpl.java index 836a3cf..5150c83 100644 --- a/src/main/java/org/apache/sling/resourceresolver/impl/mapping/PlaceholderProviderImpl.java +++ b/src/main/java/org/apache/sling/resourceresolver/impl/mapping/StringInterpolationProviderImpl.java @@ -35,15 +35,15 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -@Designate(ocd = PlaceholderProviderConfiguration.class) -@Component(name = "org.apache.sling.resourceresolver.impl.mapping.PlaceholderProvider") -public class PlaceholderProviderImpl - implements PlaceholderProvider +@Designate(ocd = StringInterpolationProviderConfiguration.class) +@Component(name = "org.apache.sling.resourceresolver.impl.mapping.StringInterpolationProvider") +public class StringInterpolationProviderImpl + implements StringInterpolationProvider { /** Logger. */ private final Logger logger = LoggerFactory.getLogger(this.getClass()); - public static PlaceholderProviderConfiguration DEFAULT_CONFIG; + public static StringInterpolationProviderConfiguration DEFAULT_CONFIG; static { final InvocationHandler handler = new InvocationHandler() { @@ -51,12 +51,12 @@ public class PlaceholderProviderImpl @Override public Object invoke(final Object obj, final Method calledMethod, final Object[] args) throws Throwable { - if ( calledMethod.getDeclaringClass().isAssignableFrom(PlaceholderProviderConfiguration.class) ) { + if ( calledMethod.getDeclaringClass().isAssignableFrom(StringInterpolationProviderConfiguration.class) ) { return calledMethod.getDefaultValue(); } if ( calledMethod.getDeclaringClass() == Object.class ) { if ( calledMethod.getName().equals("toString") && (args == null || args.length == 0) ) { - return "Generated @" + PlaceholderProviderConfiguration.class.getName() + " instance"; + return "Generated @" + StringInterpolationProviderConfiguration.class.getName() + " instance"; } if ( calledMethod.getName().equals("hashCode") && (args == null || args.length == 0) ) { return this.hashCode(); @@ -68,15 +68,15 @@ public class PlaceholderProviderImpl throw new InternalError("unexpected method dispatched: " + calledMethod); } }; - DEFAULT_CONFIG = (PlaceholderProviderConfiguration) Proxy.newProxyInstance( - PlaceholderProviderConfiguration.class.getClassLoader(), - new Class[] { PlaceholderProviderConfiguration.class }, + DEFAULT_CONFIG = (StringInterpolationProviderConfiguration) Proxy.newProxyInstance( + StringInterpolationProviderConfiguration.class.getClassLoader(), + new Class[] { StringInterpolationProviderConfiguration.class }, handler ); } private BundleContext bundleContext; - private PlaceholderProviderConfiguration config = DEFAULT_CONFIG; + private StringInterpolationProviderConfiguration config = DEFAULT_CONFIG; private Map<String, String> placeholderEntries = new HashMap<>(); // ---------- SCR Integration --------------------------------------------- @@ -85,7 +85,7 @@ public class PlaceholderProviderImpl * Activates this component (called by SCR before) */ @Activate - protected void activate(final BundleContext bundleContext, final PlaceholderProviderConfiguration config) { + protected void activate(final BundleContext bundleContext, final StringInterpolationProviderConfiguration config) { this.bundleContext = bundleContext; this.config = config; for(String line: this.config.place_holder_key_value_pairs()) { @@ -110,7 +110,7 @@ public class PlaceholderProviderImpl * Modifies this component (called by SCR to update this component) */ @Modified - protected void modified(final BundleContext bundleContext, final PlaceholderProviderConfiguration config) { + protected void modified(final BundleContext bundleContext, final StringInterpolationProviderConfiguration config) { this.deactivate(); this.activate(bundleContext, config); } @@ -169,7 +169,7 @@ public class PlaceholderProviderImpl answer += value; carret = carret + end - start + PLACEHOLDER_END_TOKEN.length(); } - if(carret < line.length() - 1) { + if(carret < line.length()) { // There is some text left after the last placeholder so copy this to the target line answer += line.substring(carret); } diff --git a/src/test/java/org/apache/sling/resourceresolver/impl/mapping/MapEntriesTest.java b/src/test/java/org/apache/sling/resourceresolver/impl/mapping/MapEntriesTest.java index 86f3766..682dacf 100644 --- a/src/test/java/org/apache/sling/resourceresolver/impl/mapping/MapEntriesTest.java +++ b/src/test/java/org/apache/sling/resourceresolver/impl/mapping/MapEntriesTest.java @@ -16,6 +16,7 @@ */ package org.apache.sling.resourceresolver.impl.mapping; +import static org.apache.sling.resourceresolver.impl.mapping.MapEntries.PROP_REDIRECT_EXTERNAL; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; @@ -32,10 +33,13 @@ import static org.mockito.Mockito.when; import java.io.File; import java.io.IOException; import java.lang.reflect.Field; +import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; +import java.lang.reflect.Proxy; import java.text.ParseException; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; @@ -59,6 +63,7 @@ import java.util.concurrent.atomic.AtomicLong; import org.apache.sling.api.SlingException; import org.apache.sling.api.resource.Resource; import org.apache.sling.api.resource.ResourceResolver; +import org.apache.sling.api.resource.ResourceResolverFactory; import org.apache.sling.api.resource.ResourceUtil; import org.apache.sling.api.resource.ValueMap; import org.apache.sling.api.resource.observation.ResourceChange; @@ -102,7 +107,7 @@ public class MapEntriesTest { private EventAdmin eventAdmin; @Mock - private PlaceholderProvider placeholderProvider; + private StringInterpolationProvider stringInterpolationProvider; private Map<String, Map<String, String>> aliasMap; @@ -140,7 +145,7 @@ public class MapEntriesTest { when(resourceResolver.findResources(anyString(), eq("sql"))).thenReturn( Collections.<Resource> emptySet().iterator()); - mapEntries = new MapEntries(resourceResolverFactory, bundleContext, eventAdmin, placeholderProvider); + mapEntries = new MapEntries(resourceResolverFactory, bundleContext, eventAdmin, stringInterpolationProvider); final Field aliasMapField = MapEntries.class.getDeclaredField("aliasMap"); aliasMapField.setAccessible(true); @@ -856,7 +861,7 @@ public class MapEntriesTest { addResource.setAccessible(true); when(resourceResolverFactory.isOptimizeAliasResolutionEnabled()).thenReturn(false); - mapEntries = new MapEntries(resourceResolverFactory, bundleContext, eventAdmin, placeholderProvider); + mapEntries = new MapEntries(resourceResolverFactory, bundleContext, eventAdmin, stringInterpolationProvider); Resource parent = mock(Resource.class); when(parent.getPath()).thenReturn("/parent"); @@ -881,7 +886,7 @@ public class MapEntriesTest { addResource.setAccessible(true); when(resourceResolverFactory.isOptimizeAliasResolutionEnabled()).thenReturn(false); - mapEntries = new MapEntries(resourceResolverFactory, bundleContext, eventAdmin, placeholderProvider); + mapEntries = new MapEntries(resourceResolverFactory, bundleContext, eventAdmin, stringInterpolationProvider); Resource parent = mock(Resource.class); when(parent.getPath()).thenReturn("/parent"); @@ -906,7 +911,7 @@ public class MapEntriesTest { removeAlias.setAccessible(true); when(resourceResolverFactory.isOptimizeAliasResolutionEnabled()).thenReturn(false); - mapEntries = new MapEntries(resourceResolverFactory, bundleContext, eventAdmin, placeholderProvider); + mapEntries = new MapEntries(resourceResolverFactory, bundleContext, eventAdmin, stringInterpolationProvider); Resource parent = mock(Resource.class); when(parent.getPath()).thenReturn("/parent"); @@ -1659,7 +1664,7 @@ public class MapEntriesTest { final Method addResource = MapEntries.class.getDeclaredMethod("addResource", String.class, AtomicBoolean.class); addResource.setAccessible(true); - mapEntries = new MapEntries(resourceResolverFactory, bundleContext, eventAdmin, placeholderProvider); + mapEntries = new MapEntries(resourceResolverFactory, bundleContext, eventAdmin, stringInterpolationProvider); Resource parent = mock(Resource.class); when(parent.getPath()).thenReturn("/parent"); @@ -1709,7 +1714,7 @@ public class MapEntriesTest { final Method addResource = MapEntries.class.getDeclaredMethod("addResource", String.class, AtomicBoolean.class); addResource.setAccessible(true); - mapEntries = Mockito.spy(new MapEntries(resourceResolverFactory, bundleContext, eventAdmin, placeholderProvider)); + mapEntries = Mockito.spy(new MapEntries(resourceResolverFactory, bundleContext, eventAdmin, stringInterpolationProvider)); doReturn(100).when(mapEntries).getTraversalRetryInterval(); Resource parent = mock(Resource.class); @@ -1766,7 +1771,7 @@ public class MapEntriesTest { final Method addResource = MapEntries.class.getDeclaredMethod("addResource", String.class, AtomicBoolean.class); addResource.setAccessible(true); - mapEntries = Mockito.spy(new MapEntries(resourceResolverFactory, bundleContext, eventAdmin, placeholderProvider)); + mapEntries = Mockito.spy(new MapEntries(resourceResolverFactory, bundleContext, eventAdmin, stringInterpolationProvider)); doReturn(100).when(mapEntries).getTraversalRetryInterval(); Resource parent = mock(Resource.class); diff --git a/src/test/java/org/apache/sling/resourceresolver/impl/mapping/PlaceholderProviderImplTest.java b/src/test/java/org/apache/sling/resourceresolver/impl/mapping/PlaceholderProviderImplTest.java deleted file mode 100644 index 472bcad..0000000 --- a/src/test/java/org/apache/sling/resourceresolver/impl/mapping/PlaceholderProviderImplTest.java +++ /dev/null @@ -1,139 +0,0 @@ -/* - * 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.mapping; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.osgi.framework.BundleContext; - -import static org.junit.Assert.assertEquals; -import static org.mockito.Mockito.when; - -public class PlaceholderProviderImplTest { - - @Mock - private BundleContext bundleContext; - - @Mock - private PlaceholderProviderConfiguration placeholderProviderConfiguration; - - @SuppressWarnings({ "unchecked" }) - @Before - public void setup() throws Exception { - MockitoAnnotations.initMocks(this); - } - - @Test - public void test_simple_one_placeholder() { - when(placeholderProviderConfiguration.place_holder_key_value_pairs()).thenReturn( - new String[] { "one=two"} - ); - - PlaceholderProviderImpl placeholderProvider = new PlaceholderProviderImpl(); - placeholderProvider.activate(bundleContext, placeholderProviderConfiguration); - - String line = "{{one}}"; - PlaceholderProvider.Check check = placeholderProvider.hasPlaceholder(line); - assertEquals("Wrong Check status", PlaceholderProvider.STATUS.found, check.getStatus()); - String resolved = placeholderProvider.resolve(check); - assertEquals("Wrong resolved line", "two", resolved); - } - - @Test - public void test_simple_text_one_placeholder() { - when(placeholderProviderConfiguration.place_holder_key_value_pairs()).thenReturn( - new String[] { "one=two"} - ); - - PlaceholderProviderImpl placeholderProvider = new PlaceholderProviderImpl(); - placeholderProvider.activate(bundleContext, placeholderProviderConfiguration); - - String line = "Here is {{one}}, too"; - PlaceholderProvider.Check check = placeholderProvider.hasPlaceholder(line); - assertEquals("Wrong Check status", PlaceholderProvider.STATUS.found, check.getStatus()); - String resolved = placeholderProvider.resolve(check); - assertEquals("Wrong resolved line", "Here is two, too", resolved); - } - - @Test - public void test_two_placeholders() { - when(placeholderProviderConfiguration.place_holder_key_value_pairs()).thenReturn( - new String[] { "one=two", "three=four"} - ); - - PlaceholderProviderImpl placeholderProvider = new PlaceholderProviderImpl(); - placeholderProvider.activate(bundleContext, placeholderProviderConfiguration); - - String line = "{{one}} with another {{three}}"; - PlaceholderProvider.Check check = placeholderProvider.hasPlaceholder(line); - assertEquals("Wrong Check status", PlaceholderProvider.STATUS.found, check.getStatus()); - String resolved = placeholderProvider.resolve(check); - assertEquals("Wrong resolved line", "two with another four", resolved); - } - - @Test - public void test_three_placeholders() { - when(placeholderProviderConfiguration.place_holder_key_value_pairs()).thenReturn( - new String[] { "one=two", "three=four", "five=six"} - ); - - PlaceholderProviderImpl placeholderProvider = new PlaceholderProviderImpl(); - placeholderProvider.activate(bundleContext, placeholderProviderConfiguration); - - String line = "Here comes {{one}} with another {{three}} equals {{five}}, horray!"; - PlaceholderProvider.Check check = placeholderProvider.hasPlaceholder(line); - assertEquals("Wrong Check status", PlaceholderProvider.STATUS.found, check.getStatus()); - String resolved = placeholderProvider.resolve(check); - assertEquals("Wrong resolved line", "Here comes two with another four equals six, horray!", resolved); - } - - @Test - public void test_no_placeholders() { - when(placeholderProviderConfiguration.place_holder_key_value_pairs()).thenReturn( - new String[] { "one=two", "three=four", "five=six"} - ); - - PlaceholderProviderImpl placeholderProvider = new PlaceholderProviderImpl(); - placeholderProvider.activate(bundleContext, placeholderProviderConfiguration); - - String line = "Here comes is a text with no placeholders!"; - PlaceholderProvider.Check check = placeholderProvider.hasPlaceholder(line); - assertEquals("Wrong Check status", PlaceholderProvider.STATUS.none, check.getStatus()); - String resolved = placeholderProvider.resolve(check); - assertEquals("Wrong resolved line", "Here comes is a text with no placeholders!", resolved); - } - - @Test - public void test_unkown_placeholders() { - when(placeholderProviderConfiguration.place_holder_key_value_pairs()).thenReturn( - new String[] { "one=two", "three=four", "five=six"} - ); - - PlaceholderProviderImpl placeholderProvider = new PlaceholderProviderImpl(); - placeholderProvider.activate(bundleContext, placeholderProviderConfiguration); - - String line = "Here comes {{unkown}} placeholders!"; - PlaceholderProvider.Check check = placeholderProvider.hasPlaceholder(line); - assertEquals("Wrong Check status", PlaceholderProvider.STATUS.unknown, check.getStatus()); - String resolved = placeholderProvider.resolve(check); - assertEquals("Wrong resolved line", "Here comes {{unkown}} placeholders!", resolved); - } -} diff --git a/src/test/java/org/apache/sling/resourceresolver/impl/mapping/StringInterpolationMapEntriesTest.java b/src/test/java/org/apache/sling/resourceresolver/impl/mapping/StringInterpolationMapEntriesTest.java new file mode 100644 index 0000000..8392637 --- /dev/null +++ b/src/test/java/org/apache/sling/resourceresolver/impl/mapping/StringInterpolationMapEntriesTest.java @@ -0,0 +1,195 @@ +/* + * 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.mapping; + +import org.apache.sling.api.resource.Resource; +import org.apache.sling.api.resource.ResourceResolver; +import org.apache.sling.api.resource.ValueMap; +import org.apache.sling.api.resource.path.Path; +import org.apache.sling.api.wrappers.ValueMapDecorator; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; +import org.osgi.framework.BundleContext; +import org.osgi.service.event.EventAdmin; + +import java.io.File; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import static org.apache.sling.resourceresolver.impl.mapping.MapEntries.PROP_REDIRECT_EXTERNAL; +import static org.junit.Assert.assertEquals; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyString; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; +import static org.mockito.Mockito.withSettings; + +/** + * These are tests that are testing the Sling Interpolation Feature (SLING-7768) + * on the MapEntries level + */ +public class StringInterpolationMapEntriesTest { + private static final String PROP_REG_EXP = "sling:match"; + + @Mock + private MapConfigurationProvider resourceResolverFactory; + + @Mock + private BundleContext bundleContext; + + @Mock + private EventAdmin eventAdmin; + + @Mock + private ResourceResolver resourceResolver; + + @Mock + private StringInterpolationProviderConfiguration stringInterpolationProviderConfiguration; + + File vanityBloomFilterFile; + + private Resource map; + private Resource http; + + @SuppressWarnings({"unchecked"}) + @Before + public void setup() throws Exception { + MockitoAnnotations.initMocks(this); + + when(resourceResolverFactory.getServiceResourceResolver(any(Map.class))).thenReturn(resourceResolver); + when(resourceResolverFactory.isVanityPathEnabled()).thenReturn(true); + final List<MapConfigurationProvider.VanityPathConfig> configs = new ArrayList<>(); + when(resourceResolverFactory.getVanityPathConfig()).thenReturn(configs); + when(resourceResolverFactory.isOptimizeAliasResolutionEnabled()).thenReturn(true); + when(resourceResolverFactory.isForceNoAliasTraversal()).thenReturn(true); + when(resourceResolverFactory.getObservationPaths()).thenReturn(new Path[] {new Path("/")}); + when(resourceResolverFactory.getMapRoot()).thenReturn(MapEntries.DEFAULT_MAP_ROOT); + when(resourceResolverFactory.getMaxCachedVanityPathEntries()).thenReturn(-1L); + when(resourceResolverFactory.isMaxCachedVanityPathEntriesStartup()).thenReturn(true); + when(resourceResolver.findResources(anyString(), eq("sql"))).thenReturn( + Collections.<Resource> emptySet().iterator()); + vanityBloomFilterFile = new File("target/test-classes/resourcesvanityBloomFilter.txt"); + when(bundleContext.getDataFile("vanityBloomFilter.txt")).thenReturn(vanityBloomFilterFile); + + map = setupEtcMapResource("/etc", "map"); + http = setupEtcMapResource("http", map); + } + + @Test + public void simple_node_string_interpolation() throws Exception { + // To avoid side effects the String Interpolation uses its own Resource Resolver + Resource sivOne = setupEtcMapResource("${siv.one}", http,PROP_REDIRECT_EXTERNAL, "/content/test-me"); + StringInterpolationProvider stringInterpolationProvider = setupStringInterpolationProvider(new String[] {"siv.one=test-value"}); + + MapEntries mapEntries = new MapEntries(resourceResolverFactory, bundleContext, eventAdmin, stringInterpolationProvider); + List<MapEntry> mapMaps = mapEntries.getResolveMaps(); + assertEquals("Expected one mapping", 1, mapMaps.size()); + MapEntry mapEntry = mapMaps.get(0); + assertEquals("Wrong String Interpolation for siv.one", "^http/test-value/", mapEntry.getPattern()); + String[] redirects = mapEntry.getRedirect(); + assertEquals("Expected one redirect", 1, redirects.length); + assertEquals("Wrong Mapping found for siv.one", "/content/test-me/", redirects[0]); + } + + @Test + public void simple_match_string_interpolation() throws Exception { + // To avoid side effects the String Interpolation uses its own Resource Resolver + Resource sivOne = setupEtcMapResource("test-node", http, + PROP_REG_EXP, "${siv.one}/", + PROP_REDIRECT_EXTERNAL, "/content/test-me/" + ); + StringInterpolationProvider stringInterpolationProvider = setupStringInterpolationProvider(new String[] {"siv.one=test-value"}); + + MapEntries mapEntries = new MapEntries(resourceResolverFactory, bundleContext, eventAdmin, stringInterpolationProvider); + List<MapEntry> mapMaps = mapEntries.getResolveMaps(); + assertEquals("Expected one mapping", 1, mapMaps.size()); + MapEntry mapEntry = mapMaps.get(0); + assertEquals("Wrong String Interpolation for siv.one", "^http/test-value/", mapEntry.getPattern()); + String[] redirects = mapEntry.getRedirect(); + assertEquals("Expected one redirect", 1, redirects.length); + assertEquals("Wrong Mapping found for siv.one", "/content/test-me/", redirects[0]); + } + + // -------------------------- private methods ---------- + + private ValueMap buildValueMap(Object... string) { + final Map<String, Object> data = new HashMap<>(); + for (int i = 0; i < string.length; i = i + 2) { + data.put((String) string[i], string[i+1]); + } + return new ValueMapDecorator(data); + } + + private Resource setupEtcMapResource(String parentPath, String name, String...valueMapPairs) { + return setupEtcMapResource0(parentPath, name, null, valueMapPairs); + } + private Resource setupEtcMapResource(String name, Resource parent, String...valueMapPairs) { + return setupEtcMapResource0(null, name, parent, valueMapPairs); + } + private Resource setupEtcMapResource0(String parentPath, String name, Resource parent, String...valueMapPairs) { + Resource resource = mock(Resource.class, withSettings().name(name).extraInterfaces(ResourceDecorator.class)); + String path = (parent == null ? parentPath : parent.getPath()) + "/" + name; + when(resource.getPath()).thenReturn(path); + when(resource.getName()).thenReturn(name); + ValueMap valueMap = buildValueMap(valueMapPairs); + when(resource.getValueMap()).thenReturn(valueMap); + when(resource.adaptTo(ValueMap.class)).thenReturn(valueMap); + when(resourceResolver.getResource(resource.getPath())).thenReturn(resource); + if(parent != null) { + List<Resource> childList = ((ResourceDecorator) parent).getChildrenList(); + childList.add(resource); + } + final List<Resource> childrenList = new ArrayList<>(); + when(((ResourceDecorator) resource).getChildrenList()).thenReturn(childrenList); + // Delay the children list iterator to make sure all children are added beforehand + // Iterators have a modCount that is set when created. Any changes to the underlying list will + // change that modCount and the usage of the iterator will fail due to Concurrent Modification Exception + when(resource.listChildren()).thenAnswer(new Answer<Iterator<Resource>>() { + @Override + public Iterator<Resource> answer(InvocationOnMock invocation) throws Throwable { + return childrenList.iterator(); + } + }); + + return resource; + } + + private StringInterpolationProvider setupStringInterpolationProvider(final String[] placeholderValues) { + when(stringInterpolationProviderConfiguration.place_holder_key_value_pairs()).thenReturn(placeholderValues); + StringInterpolationProviderImpl stringInterpolationProvider = new StringInterpolationProviderImpl(); + stringInterpolationProvider.activate(bundleContext, stringInterpolationProviderConfiguration); + return stringInterpolationProvider; + } + + /** + * Iterator to piggyback the list of Resources onto a Resource Mock + * so that we can add children to them and create the iterators after + * everything is setup + */ + private static interface ResourceDecorator { + public List<Resource> getChildrenList(); + } +} diff --git a/src/test/java/org/apache/sling/resourceresolver/impl/mapping/StringInterpolationProviderImplTest.java b/src/test/java/org/apache/sling/resourceresolver/impl/mapping/StringInterpolationProviderImplTest.java new file mode 100644 index 0000000..212c928 --- /dev/null +++ b/src/test/java/org/apache/sling/resourceresolver/impl/mapping/StringInterpolationProviderImplTest.java @@ -0,0 +1,155 @@ +/* + * 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.mapping; + +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.osgi.framework.BundleContext; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.when; +import static org.apache.sling.resourceresolver.impl.mapping.StringInterpolationProvider.PLACEHOLDER_START_TOKEN; +import static org.apache.sling.resourceresolver.impl.mapping.StringInterpolationProvider.PLACEHOLDER_END_TOKEN; + +public class StringInterpolationProviderImplTest { + + @Mock + private BundleContext bundleContext; + + @Mock + private StringInterpolationProviderConfiguration stringInterpolationProviderConfiguration; + + @SuppressWarnings({ "unchecked" }) + @Before + public void setup() throws Exception { + MockitoAnnotations.initMocks(this); + } + + @Test + public void test_simple_one_placeholder() { + when(stringInterpolationProviderConfiguration.place_holder_key_value_pairs()).thenReturn( + new String[] { "one=two"} + ); + + StringInterpolationProviderImpl placeholderProvider = new StringInterpolationProviderImpl(); + placeholderProvider.activate(bundleContext, stringInterpolationProviderConfiguration); + + String line = PLACEHOLDER_START_TOKEN + "one" + PLACEHOLDER_END_TOKEN; + StringInterpolationProvider.Check check = placeholderProvider.hasPlaceholder(line); + assertEquals("Wrong Check status", StringInterpolationProvider.STATUS.found, check.getStatus()); + String resolved = placeholderProvider.resolve(check); + assertEquals("Wrong resolved line", "two", resolved); + } + + @Test + public void test_simple_text_one_placeholder() { + when(stringInterpolationProviderConfiguration.place_holder_key_value_pairs()).thenReturn( + new String[] { "one=two"} + ); + StringInterpolationProviderImpl placeholderProvider = new StringInterpolationProviderImpl(); + placeholderProvider.activate(bundleContext, stringInterpolationProviderConfiguration); + + String line = "Here is " + PLACEHOLDER_START_TOKEN + "one" + PLACEHOLDER_END_TOKEN + ", too"; + StringInterpolationProvider.Check check = placeholderProvider.hasPlaceholder(line); + assertEquals("Wrong Check status", StringInterpolationProvider.STATUS.found, check.getStatus()); + String resolved = placeholderProvider.resolve(check); + assertEquals("Wrong resolved line", "Here is two, too", resolved); + } + + @Test + public void test_two_placeholders() { + when(stringInterpolationProviderConfiguration.place_holder_key_value_pairs()).thenReturn( + new String[] { "one=two", "three=four"} + ); + StringInterpolationProviderImpl placeholderProvider = new StringInterpolationProviderImpl(); + placeholderProvider.activate(bundleContext, stringInterpolationProviderConfiguration); + + String line = PLACEHOLDER_START_TOKEN + "one" + PLACEHOLDER_END_TOKEN + " with another " + PLACEHOLDER_START_TOKEN + "three" + PLACEHOLDER_END_TOKEN; + StringInterpolationProvider.Check check = placeholderProvider.hasPlaceholder(line); + assertEquals("Wrong Check status", StringInterpolationProvider.STATUS.found, check.getStatus()); + String resolved = placeholderProvider.resolve(check); + assertEquals("Wrong resolved line", "two with another four", resolved); + } + + @Test + public void test_three_placeholders() { + when(stringInterpolationProviderConfiguration.place_holder_key_value_pairs()).thenReturn( + new String[] { "one=two", "three=four", "five=six"} + ); + + StringInterpolationProviderImpl placeholderProvider = new StringInterpolationProviderImpl(); + placeholderProvider.activate(bundleContext, stringInterpolationProviderConfiguration); + + String line = "Here comes " + PLACEHOLDER_START_TOKEN + "one" + PLACEHOLDER_END_TOKEN + " with another " + PLACEHOLDER_START_TOKEN + "three" + PLACEHOLDER_END_TOKEN + " equals " + PLACEHOLDER_START_TOKEN + "five" + PLACEHOLDER_END_TOKEN + ", horray!"; + StringInterpolationProvider.Check check = placeholderProvider.hasPlaceholder(line); + assertEquals("Wrong Check status", StringInterpolationProvider.STATUS.found, check.getStatus()); + String resolved = placeholderProvider.resolve(check); + assertEquals("Wrong resolved line", "Here comes two with another four equals six, horray!", resolved); + } + + @Test + public void test_no_placeholders() { + when(stringInterpolationProviderConfiguration.place_holder_key_value_pairs()).thenReturn( + new String[] { "one=two", "three=four", "five=six"} + ); + + StringInterpolationProviderImpl placeholderProvider = new StringInterpolationProviderImpl(); + placeholderProvider.activate(bundleContext, stringInterpolationProviderConfiguration); + + String line = "Here comes is a text with no placeholders!"; + StringInterpolationProvider.Check check = placeholderProvider.hasPlaceholder(line); + assertEquals("Wrong Check status", StringInterpolationProvider.STATUS.none, check.getStatus()); + String resolved = placeholderProvider.resolve(check); + assertEquals("Wrong resolved line", "Here comes is a text with no placeholders!", resolved); + } + + @Test + public void test_unkown_placeholders() { + when(stringInterpolationProviderConfiguration.place_holder_key_value_pairs()).thenReturn( + new String[] { "one=two", "three=four", "five=six"} + ); + + StringInterpolationProviderImpl placeholderProvider = new StringInterpolationProviderImpl(); + placeholderProvider.activate(bundleContext, stringInterpolationProviderConfiguration); + + String line = "Here comes " + PLACEHOLDER_START_TOKEN + "unkown" + PLACEHOLDER_END_TOKEN + " placeholders!"; + StringInterpolationProvider.Check check = placeholderProvider.hasPlaceholder(line); + assertEquals("Wrong Check status", StringInterpolationProvider.STATUS.unknown, check.getStatus()); + String resolved = placeholderProvider.resolve(check); + assertEquals("Wrong resolved line", "Here comes ${unkown} placeholders!", resolved); + } + + @Test + public void test_trailing_slash_placeholders() { + when(stringInterpolationProviderConfiguration.place_holder_key_value_pairs()).thenReturn( + new String[] { "siv.one=test-value"} + ); + + StringInterpolationProviderImpl placeholderProvider = new StringInterpolationProviderImpl(); + placeholderProvider.activate(bundleContext, stringInterpolationProviderConfiguration); + + String line = PLACEHOLDER_START_TOKEN + "siv.one" + PLACEHOLDER_END_TOKEN + "/"; + StringInterpolationProvider.Check check = placeholderProvider.hasPlaceholder(line); + assertEquals("Wrong Check status", StringInterpolationProvider.STATUS.found, check.getStatus()); + String resolved = placeholderProvider.resolve(check); + assertEquals("Wrong resolved line", "test-value/", resolved); + } +}
