| /* |
| * 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 static org.junit.Assert.assertEquals; |
| import static org.junit.Assert.assertFalse; |
| import static org.junit.Assert.assertNotNull; |
| import static org.junit.Assert.assertNull; |
| import static org.junit.Assert.assertTrue; |
| import static org.junit.Assert.fail; |
| 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 java.io.File; |
| import java.io.IOException; |
| import java.lang.reflect.Field; |
| import java.lang.reflect.Method; |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.Collections; |
| import java.util.HashMap; |
| import java.util.HashSet; |
| import java.util.Iterator; |
| import java.util.LinkedList; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Random; |
| import java.util.Set; |
| import java.util.concurrent.Callable; |
| import java.util.concurrent.ExecutorService; |
| import java.util.concurrent.Executors; |
| import java.util.concurrent.Future; |
| import java.util.concurrent.Semaphore; |
| import java.util.concurrent.TimeUnit; |
| import java.util.concurrent.atomic.AtomicBoolean; |
| import java.util.concurrent.atomic.AtomicInteger; |
| import java.util.concurrent.atomic.AtomicLong; |
| |
| import org.apache.sling.api.resource.Resource; |
| import org.apache.sling.api.resource.ResourceResolver; |
| import org.apache.sling.api.resource.ResourceUtil; |
| import org.apache.sling.api.resource.ValueMap; |
| import org.apache.sling.api.resource.observation.ResourceChange; |
| import org.apache.sling.api.resource.observation.ResourceChange.ChangeType; |
| import org.apache.sling.api.resource.path.Path; |
| import org.apache.sling.api.wrappers.ValueMapDecorator; |
| import org.apache.sling.resourceresolver.impl.ResourceResolverImpl; |
| import org.apache.sling.resourceresolver.impl.mapping.MapConfigurationProvider.VanityPathConfig; |
| import org.junit.After; |
| import org.junit.Before; |
| import org.junit.Test; |
| import org.mockito.Mock; |
| import org.mockito.Mockito; |
| import org.mockito.MockitoAnnotations; |
| import org.mockito.invocation.InvocationOnMock; |
| import org.mockito.stubbing.Answer; |
| import org.osgi.framework.Bundle; |
| import org.osgi.framework.BundleContext; |
| import org.osgi.service.event.EventAdmin; |
| |
| public class MapEntriesTest { |
| |
| private MapEntries mapEntries; |
| |
| File vanityBloomFilterFile; |
| |
| @Mock |
| private MapConfigurationProvider resourceResolverFactory; |
| |
| @Mock |
| private BundleContext bundleContext; |
| |
| @Mock |
| private Bundle bundle; |
| |
| @Mock |
| private ResourceResolver resourceResolver; |
| |
| @Mock |
| private EventAdmin eventAdmin; |
| |
| private Map<String, Map<String, String>> aliasMap; |
| |
| @SuppressWarnings({ "unchecked" }) |
| @Before |
| public void setup() throws Exception { |
| MockitoAnnotations.initMocks(this); |
| |
| final List<VanityPathConfig> configs = new ArrayList<>(); |
| configs.add(new VanityPathConfig("/libs/", false)); |
| configs.add(new VanityPathConfig("/libs/denied", true)); |
| configs.add(new VanityPathConfig("/foo/", false)); |
| configs.add(new VanityPathConfig("/baa/", false)); |
| configs.add(new VanityPathConfig("/justVanityPath", false)); |
| configs.add(new VanityPathConfig("/justVanityPath2", false)); |
| configs.add(new VanityPathConfig("/badVanityPath", false)); |
| configs.add(new VanityPathConfig("/redirectingVanityPath", false)); |
| configs.add(new VanityPathConfig("/redirectingVanityPath301", false)); |
| configs.add(new VanityPathConfig("/vanityPathOnJcrContent", false)); |
| |
| Collections.sort(configs); |
| vanityBloomFilterFile = new File("src/main/resourcesvanityBloomFilter.txt"); |
| when(bundle.getSymbolicName()).thenReturn("TESTBUNDLE"); |
| when(bundleContext.getBundle()).thenReturn(bundle); |
| when(bundleContext.getDataFile("vanityBloomFilter.txt")).thenReturn(vanityBloomFilterFile); |
| when(resourceResolverFactory.getServiceResourceResolver(any(Map.class))).thenReturn(resourceResolver); |
| when(resourceResolverFactory.isVanityPathEnabled()).thenReturn(true); |
| when(resourceResolverFactory.getVanityPathConfig()).thenReturn(configs); |
| when(resourceResolverFactory.isOptimizeAliasResolutionEnabled()).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()); |
| |
| mapEntries = new MapEntries(resourceResolverFactory, bundleContext, eventAdmin); |
| final Field aliasMapField = MapEntries.class.getDeclaredField("aliasMap"); |
| aliasMapField.setAccessible(true); |
| |
| this.aliasMap = ( Map<String, Map<String, String>>) aliasMapField.get(mapEntries); |
| } |
| |
| @After |
| public void tearDown() throws Exception { |
| vanityBloomFilterFile.delete(); |
| } |
| |
| |
| @Test |
| public void test_simple_alias_support() { |
| Resource parent = mock(Resource.class); |
| when(parent.getPath()).thenReturn("/parent"); |
| |
| final Resource result = mock(Resource.class); |
| when(result.getParent()).thenReturn(parent); |
| when(result.getPath()).thenReturn("/parent/child"); |
| when(result.getName()).thenReturn("child"); |
| when(result.getValueMap()).thenReturn(buildValueMap(ResourceResolverImpl.PROP_ALIAS, "alias")); |
| |
| when(resourceResolver.findResources(anyString(), eq("sql"))).thenAnswer(new Answer<Iterator<Resource>>() { |
| |
| @Override |
| public Iterator<Resource> answer(InvocationOnMock invocation) throws Throwable { |
| if (invocation.getArguments()[0].toString().contains(ResourceResolverImpl.PROP_ALIAS)) { |
| return Collections.singleton(result).iterator(); |
| } else { |
| return Collections.<Resource> emptySet().iterator(); |
| } |
| } |
| }); |
| |
| mapEntries.doInit(); |
| |
| Map<String, String> aliasMap = mapEntries.getAliasMap("/parent"); |
| assertNotNull(aliasMap); |
| assertTrue(aliasMap.containsKey("alias")); |
| assertEquals("child", aliasMap.get("alias")); |
| } |
| |
| @Test |
| public void test_that_duplicate_alias_doesnt_replace_first_alias() { |
| Resource parent = mock(Resource.class); |
| when(parent.getPath()).thenReturn("/parent"); |
| |
| final Resource result = mock(Resource.class); |
| when(result.getParent()).thenReturn(parent); |
| when(result.getPath()).thenReturn("/parent/child"); |
| when(result.getName()).thenReturn("child"); |
| when(result.getValueMap()).thenReturn(buildValueMap(ResourceResolverImpl.PROP_ALIAS, "alias")); |
| |
| final Resource secondResult = mock(Resource.class); |
| when(secondResult.getParent()).thenReturn(parent); |
| when(secondResult.getPath()).thenReturn("/parent/child2"); |
| when(secondResult.getName()).thenReturn("child2"); |
| when(secondResult.getValueMap()).thenReturn(buildValueMap(ResourceResolverImpl.PROP_ALIAS, "alias")); |
| |
| when(resourceResolver.findResources(anyString(), eq("sql"))).thenAnswer(new Answer<Iterator<Resource>>() { |
| |
| @Override |
| public Iterator<Resource> answer(InvocationOnMock invocation) throws Throwable { |
| if (invocation.getArguments()[0].toString().contains(ResourceResolverImpl.PROP_ALIAS)) { |
| return Arrays.asList(result, secondResult).iterator(); |
| } else { |
| return Collections.<Resource> emptySet().iterator(); |
| } |
| } |
| }); |
| |
| mapEntries.doInit(); |
| |
| Map<String, String> aliasMap = mapEntries.getAliasMap("/parent"); |
| assertNotNull(aliasMap); |
| assertTrue(aliasMap.containsKey("alias")); |
| assertEquals("child", aliasMap.get("alias")); |
| } |
| |
| @Test |
| public void test_vanity_path_registration() throws Exception { |
| // specifically making this a weird value because we want to verify that |
| // the configuration value is being used |
| int DEFAULT_VANITY_STATUS = 333333; |
| |
| when(resourceResolverFactory.getDefaultVanityPathRedirectStatus()).thenReturn(DEFAULT_VANITY_STATUS); |
| |
| final List<Resource> resources = new ArrayList<>(); |
| |
| Resource justVanityPath = mock(Resource.class, "justVanityPath"); |
| when(justVanityPath.getPath()).thenReturn("/justVanityPath"); |
| when(justVanityPath.getName()).thenReturn("justVanityPath"); |
| when(justVanityPath.getValueMap()).thenReturn(buildValueMap("sling:vanityPath", "/target/justVanityPath")); |
| resources.add(justVanityPath); |
| |
| Resource badVanityPath = mock(Resource.class, "badVanityPath"); |
| when(badVanityPath.getPath()).thenReturn("/badVanityPath"); |
| when(badVanityPath.getName()).thenReturn("badVanityPath"); |
| when(badVanityPath.getValueMap()).thenReturn(buildValueMap("sling:vanityPath", "/content/mypage/en-us-{132")); |
| resources.add(badVanityPath); |
| |
| |
| Resource redirectingVanityPath = mock(Resource.class, "redirectingVanityPath"); |
| when(redirectingVanityPath.getPath()).thenReturn("/redirectingVanityPath"); |
| when(redirectingVanityPath.getName()).thenReturn("redirectingVanityPath"); |
| when(redirectingVanityPath.getValueMap()).thenReturn(buildValueMap("sling:vanityPath", "/target/redirectingVanityPath", "sling:redirect", true)); |
| resources.add(redirectingVanityPath); |
| |
| Resource redirectingVanityPath301 = mock(Resource.class, "redirectingVanityPath301"); |
| when(redirectingVanityPath301.getPath()).thenReturn("/redirectingVanityPath301"); |
| when(redirectingVanityPath301.getName()).thenReturn("redirectingVanityPath301"); |
| when(redirectingVanityPath301.getValueMap()).thenReturn(buildValueMap("sling:vanityPath", "/target/redirectingVanityPath301", "sling:redirect", true, "sling:redirectStatus", 301)); |
| resources.add(redirectingVanityPath301); |
| |
| Resource vanityPathOnJcrContentParent = mock(Resource.class, "vanityPathOnJcrContentParent"); |
| when(vanityPathOnJcrContentParent.getPath()).thenReturn("/vanityPathOnJcrContent"); |
| when(vanityPathOnJcrContentParent.getName()).thenReturn("vanityPathOnJcrContent"); |
| |
| Resource vanityPathOnJcrContent = mock(Resource.class, "vanityPathOnJcrContent"); |
| when(vanityPathOnJcrContent.getPath()).thenReturn("/vanityPathOnJcrContent/jcr:content"); |
| when(vanityPathOnJcrContent.getName()).thenReturn("jcr:content"); |
| when(vanityPathOnJcrContent.getParent()).thenReturn(vanityPathOnJcrContentParent); |
| when(vanityPathOnJcrContent.getValueMap()).thenReturn(buildValueMap("sling:vanityPath", "/target/vanityPathOnJcrContent")); |
| resources.add(vanityPathOnJcrContent); |
| |
| when(resourceResolver.findResources(anyString(), eq("sql"))).thenAnswer(new Answer<Iterator<Resource>>() { |
| |
| @Override |
| public Iterator<Resource> answer(InvocationOnMock invocation) throws Throwable { |
| if (invocation.getArguments()[0].toString().contains("sling:vanityPath")) { |
| return resources.iterator(); |
| } else { |
| return Collections.<Resource> emptySet().iterator(); |
| } |
| } |
| }); |
| |
| mapEntries.doInit(); |
| mapEntries.initializeVanityPaths(); |
| |
| List<MapEntry> entries = mapEntries.getResolveMaps(); |
| assertEquals(8, entries.size()); |
| for (MapEntry entry : entries) { |
| if (entry.getPattern().contains("/target/redirectingVanityPath301")) { |
| assertEquals(301, entry.getStatus()); |
| assertFalse(entry.isInternal()); |
| } else if (entry.getPattern().contains("/target/redirectingVanityPath")) { |
| assertEquals(DEFAULT_VANITY_STATUS, entry.getStatus()); |
| assertFalse(entry.isInternal()); |
| } else if (entry.getPattern().contains("/target/justVanityPath")) { |
| assertTrue(entry.isInternal()); |
| } else if (entry.getPattern().contains("/target/vanityPathOnJcrContent")) { |
| for (String redirect : entry.getRedirect()) { |
| assertFalse(redirect.contains("jcr:content")); |
| } |
| } |
| } |
| |
| Field field = MapEntries.class.getDeclaredField("vanityTargets"); |
| field.setAccessible(true); |
| @SuppressWarnings("unchecked") |
| Map<String, List<String>> vanityTargets = (Map<String, List<String>>) field.get(mapEntries); |
| assertEquals(4, vanityTargets.size()); |
| |
| } |
| |
| @Test |
| public void test_vanity_path_updates() throws Exception { |
| Resource parent = mock(Resource.class, "parent"); |
| when(parent.getPath()).thenReturn("/foo/parent"); |
| when(parent.getName()).thenReturn("parent"); |
| when(parent.getValueMap()).thenReturn(new ValueMapDecorator(Collections.<String, Object>emptyMap())); |
| when(resourceResolver.getResource(parent.getPath())).thenReturn(parent); |
| |
| Resource child = mock(Resource.class, "jcrcontent"); |
| when(child.getPath()).thenReturn("/foo/parent/jcr:content"); |
| when(child.getName()).thenReturn("jcr:content"); |
| when(child.getValueMap()).thenReturn(buildValueMap("sling:vanityPath", "/target/found")); |
| when(child.getParent()).thenReturn(parent); |
| when(parent.getChild(child.getName())).thenReturn(child); |
| when(resourceResolver.getResource(child.getPath())).thenReturn(child); |
| |
| when(resourceResolver.findResources(anyString(), eq("sql"))).thenAnswer(new Answer<Iterator<Resource>>() { |
| |
| @Override |
| public Iterator<Resource> answer(InvocationOnMock invocation) throws Throwable { |
| return Collections.<Resource> emptySet().iterator(); |
| } |
| }); |
| |
| mapEntries.doInit(); |
| mapEntries.initializeVanityPaths(); |
| |
| // map entries should have no alias atm |
| assertTrue( mapEntries.getResolveMaps().isEmpty()); |
| |
| // add parent |
| mapEntries.onChange(Arrays.asList(new ResourceChange(ChangeType.ADDED, parent.getPath(), false))); |
| assertTrue( mapEntries.getResolveMaps().isEmpty()); |
| |
| // add child |
| mapEntries.onChange(Arrays.asList(new ResourceChange(ChangeType.ADDED, child.getPath(), false))); |
| |
| // two entries for the vanity path |
| List<MapEntry> entries = mapEntries.getResolveMaps(); |
| assertEquals(2, entries.size()); |
| for (MapEntry entry : entries) { |
| assertTrue(entry.getPattern().contains("/target/found")); |
| } |
| |
| // update parent - no change |
| mapEntries.onChange(Arrays.asList(new ResourceChange(ChangeType.CHANGED, parent.getPath(), false))); |
| entries = mapEntries.getResolveMaps(); |
| assertEquals(2, entries.size()); |
| for (MapEntry entry : entries) { |
| assertTrue(entry.getPattern().contains("/target/found")); |
| } |
| |
| // update child - no change |
| mapEntries.onChange(Arrays.asList(new ResourceChange(ChangeType.CHANGED, child.getPath(), false))); |
| entries = mapEntries.getResolveMaps(); |
| assertEquals(2, entries.size()); |
| for (MapEntry entry : entries) { |
| assertTrue(entry.getPattern().contains("/target/found")); |
| } |
| |
| // remove child - empty again |
| when(resourceResolver.getResource(child.getPath())).thenReturn(null); |
| when(parent.getChild(child.getName())).thenReturn(null); |
| mapEntries.onChange(Arrays.asList(new ResourceChange(ChangeType.REMOVED, child.getPath(), false))); |
| assertTrue( mapEntries.getResolveMaps().isEmpty()); |
| |
| // remove parent - still empty |
| when(resourceResolver.getResource(parent.getPath())).thenReturn(null); |
| mapEntries.onChange(Arrays.asList(new ResourceChange(ChangeType.REMOVED, parent.getPath(), false))); |
| assertTrue( mapEntries.getResolveMaps().isEmpty()); |
| } |
| |
| 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 getVanityPathResource(final String path) { |
| Resource rsrc = mock(Resource.class); |
| when(rsrc.getPath()).thenReturn(path); |
| when(rsrc.getName()).thenReturn(ResourceUtil.getName(path)); |
| when(rsrc.getValueMap()).thenReturn(buildValueMap("sling:vanityPath", "/vanity" + path)); |
| return rsrc; |
| } |
| |
| @Test |
| public void test_vanity_path_registration_include_exclude() throws IOException { |
| final String[] validPaths = {"/libs/somewhere", "/libs/a/b", "/foo/a", "/baa/a"}; |
| final String[] invalidPaths = {"/libs/denied/a", "/libs/denied/b/c", "/nowhere"}; |
| |
| final List<Resource> resources = new ArrayList<>(); |
| for(final String val : validPaths) { |
| resources.add(getVanityPathResource(val)); |
| } |
| for(final String val : invalidPaths) { |
| resources.add(getVanityPathResource(val)); |
| } |
| |
| |
| when(resourceResolver.findResources(anyString(), eq("sql"))).thenAnswer(new Answer<Iterator<Resource>>() { |
| |
| @Override |
| public Iterator<Resource> answer(InvocationOnMock invocation) throws Throwable { |
| if (invocation.getArguments()[0].toString().contains("sling:vanityPath")) { |
| return resources.iterator(); |
| } else { |
| return Collections.<Resource> emptySet().iterator(); |
| } |
| } |
| }); |
| |
| mapEntries.doInit(); |
| mapEntries.initializeVanityPaths(); |
| |
| List<MapEntry> entries = mapEntries.getResolveMaps(); |
| // each valid resource results in 2 entries |
| assertEquals(validPaths.length * 2, entries.size()); |
| |
| final Set<String> resultSet = new HashSet<>(); |
| for(final String p : validPaths) { |
| resultSet.add(p + "$1"); |
| resultSet.add(p + ".html"); |
| } |
| for (final MapEntry entry : entries) { |
| assertTrue(resultSet.remove(entry.getRedirect()[0])); |
| } |
| } |
| |
| @Test |
| public void test_getActualContentPath() throws Exception { |
| |
| Method method = MapEntries.class.getDeclaredMethod("getActualContentPath", String.class); |
| method.setAccessible(true); |
| |
| String actualContent = (String) method.invoke(mapEntries, "/content"); |
| assertEquals("/content", actualContent); |
| |
| actualContent = (String) method.invoke(mapEntries, "/content/jcr:content"); |
| assertEquals("/content", actualContent); |
| } |
| |
| @Test |
| public void test_getMapEntryRedirect() throws Exception { |
| |
| Method method = MapEntries.class.getDeclaredMethod("getMapEntryRedirect", MapEntry.class); |
| method.setAccessible(true); |
| |
| MapEntry mapEntry = new MapEntry("/content", -1, false, 0, "/content"); |
| String actualContent = (String) method.invoke(mapEntries, mapEntry); |
| assertEquals("/content", actualContent); |
| |
| mapEntry = new MapEntry("/content", -1, false, 0, "/content$1"); |
| actualContent = (String) method.invoke(mapEntries, mapEntry); |
| assertEquals("/content", actualContent); |
| |
| mapEntry = new MapEntry("/content", -1, false, 0, "/content.html"); |
| actualContent = (String) method.invoke(mapEntries, mapEntry); |
| assertEquals("/content", actualContent); |
| } |
| |
| @SuppressWarnings("unchecked") |
| @Test |
| public void test_doAddVanity() throws Exception { |
| List<MapEntry> entries = mapEntries.getResolveMaps(); |
| assertEquals(0, entries.size()); |
| Field field = MapEntries.class.getDeclaredField("vanityTargets"); |
| field.setAccessible(true); |
| Map<String, List<String>> vanityTargets = (Map<String, List<String>>) field.get(mapEntries); |
| assertEquals(0, vanityTargets.size()); |
| |
| final Method addResource = MapEntries.class.getDeclaredMethod("addResource", String.class, AtomicBoolean.class); |
| addResource.setAccessible(true); |
| |
| Resource justVanityPath = mock(Resource.class, "justVanityPath"); |
| when(resourceResolver.getResource("/justVanityPath")).thenReturn(justVanityPath); |
| when(justVanityPath.getPath()).thenReturn("/justVanityPath"); |
| when(justVanityPath.getName()).thenReturn("justVanityPath"); |
| when(justVanityPath.getValueMap()).thenReturn(buildValueMap("sling:vanityPath", "/target/justVanityPath")); |
| |
| addResource.invoke(mapEntries, "/justVanityPath", new AtomicBoolean()); |
| |
| entries = mapEntries.getResolveMaps(); |
| assertEquals(2, entries.size()); |
| |
| Field vanityCounter = MapEntries.class.getDeclaredField("vanityCounter"); |
| vanityCounter.setAccessible(true); |
| AtomicLong counter = (AtomicLong) vanityCounter.get(mapEntries); |
| assertEquals(2, counter.longValue()); |
| |
| //bad vanity |
| Resource badVanityPath = mock(Resource.class, "badVanityPath"); |
| when(resourceResolver.getResource("/badVanityPath")).thenReturn(badVanityPath); |
| when(badVanityPath.getPath()).thenReturn("/badVanityPath"); |
| when(badVanityPath.getName()).thenReturn("badVanityPath"); |
| when(badVanityPath.getValueMap()).thenReturn(buildValueMap("sling:vanityPath", "/content/mypage/en-us-{132")); |
| |
| addResource.invoke(mapEntries, "/badVanityPath", new AtomicBoolean()); |
| |
| |
| assertEquals(2, entries.size()); |
| |
| vanityTargets = (Map<String, List<String>>) field.get(mapEntries); |
| assertEquals(1, vanityTargets.size()); |
| |
| //vanity under jcr:content |
| Resource vanityPathOnJcrContentParent = mock(Resource.class, "vanityPathOnJcrContentParent"); |
| when(vanityPathOnJcrContentParent.getPath()).thenReturn("/vanityPathOnJcrContent"); |
| when(vanityPathOnJcrContentParent.getName()).thenReturn("vanityPathOnJcrContent"); |
| |
| Resource vanityPathOnJcrContent = mock(Resource.class, "vanityPathOnJcrContent"); |
| when(resourceResolver.getResource("/vanityPathOnJcrContent/jcr:content")).thenReturn(vanityPathOnJcrContent); |
| when(vanityPathOnJcrContent.getPath()).thenReturn("/vanityPathOnJcrContent/jcr:content"); |
| when(vanityPathOnJcrContent.getName()).thenReturn("jcr:content"); |
| when(vanityPathOnJcrContent.getParent()).thenReturn(vanityPathOnJcrContentParent); |
| when(vanityPathOnJcrContent.getValueMap()).thenReturn(buildValueMap("sling:vanityPath", "/target/vanityPathOnJcrContent")); |
| |
| addResource.invoke(mapEntries, "/vanityPathOnJcrContent/jcr:content", new AtomicBoolean()); |
| |
| entries = mapEntries.getResolveMaps(); |
| assertEquals(4, entries.size()); |
| |
| counter = (AtomicLong) vanityCounter.get(mapEntries); |
| assertEquals(4, counter.longValue()); |
| |
| vanityTargets = (Map<String, List<String>>) field.get(mapEntries); |
| assertEquals(2, vanityTargets.size()); |
| |
| assertNull(vanityTargets.get("/vanityPathOnJcrContent/jcr:content")); |
| assertNotNull(vanityTargets.get("/vanityPathOnJcrContent")); |
| } |
| |
| @SuppressWarnings("unchecked") |
| @Test |
| public void test_doAddVanity_1() throws Exception { |
| when(this.resourceResolverFactory.getMaxCachedVanityPathEntries()).thenReturn(10L); |
| |
| List<MapEntry> entries = mapEntries.getResolveMaps(); |
| assertEquals(0, entries.size()); |
| Field field = MapEntries.class.getDeclaredField("vanityTargets"); |
| field.setAccessible(true); |
| Map<String, List<String>> vanityTargets = (Map<String, List<String>>) field.get(mapEntries); |
| assertEquals(0, vanityTargets.size()); |
| |
| final Method addResource = MapEntries.class.getDeclaredMethod("addResource", String.class, AtomicBoolean.class); |
| addResource.setAccessible(true); |
| |
| Resource justVanityPath = mock(Resource.class, "justVanityPath"); |
| when(resourceResolver.getResource("/justVanityPath")).thenReturn(justVanityPath); |
| when(justVanityPath.getPath()).thenReturn("/justVanityPath"); |
| when(justVanityPath.getName()).thenReturn("justVanityPath"); |
| when(justVanityPath.getValueMap()).thenReturn(buildValueMap("sling:vanityPath", "/target/justVanityPath")); |
| |
| addResource.invoke(mapEntries, "/justVanityPath", new AtomicBoolean()); |
| |
| entries = mapEntries.getResolveMaps(); |
| assertEquals(2, entries.size()); |
| |
| Field vanityCounter = MapEntries.class.getDeclaredField("vanityCounter"); |
| vanityCounter.setAccessible(true); |
| AtomicLong counter = (AtomicLong) vanityCounter.get(mapEntries); |
| assertEquals(2, counter.longValue()); |
| |
| //bad vanity |
| Resource badVanityPath = mock(Resource.class, "badVanityPath"); |
| when(resourceResolver.getResource("/badVanityPath")).thenReturn(badVanityPath); |
| when(badVanityPath.getPath()).thenReturn("/badVanityPath"); |
| when(badVanityPath.getName()).thenReturn("badVanityPath"); |
| when(badVanityPath.getValueMap()).thenReturn(buildValueMap("sling:vanityPath", "/content/mypage/en-us-{132")); |
| |
| addResource.invoke(mapEntries, "/badVanityPath", new AtomicBoolean()); |
| |
| |
| assertEquals(2, entries.size()); |
| |
| vanityTargets = (Map<String, List<String>>) field.get(mapEntries); |
| assertEquals(1, vanityTargets.size()); |
| |
| //vanity under jcr:content |
| Resource vanityPathOnJcrContentParent = mock(Resource.class, "vanityPathOnJcrContentParent"); |
| when(vanityPathOnJcrContentParent.getPath()).thenReturn("/vanityPathOnJcrContent"); |
| when(vanityPathOnJcrContentParent.getName()).thenReturn("vanityPathOnJcrContent"); |
| |
| Resource vanityPathOnJcrContent = mock(Resource.class, "vanityPathOnJcrContent"); |
| when(resourceResolver.getResource("/vanityPathOnJcrContent/jcr:content")).thenReturn(vanityPathOnJcrContent); |
| when(vanityPathOnJcrContent.getPath()).thenReturn("/vanityPathOnJcrContent/jcr:content"); |
| when(vanityPathOnJcrContent.getName()).thenReturn("jcr:content"); |
| when(vanityPathOnJcrContent.getParent()).thenReturn(vanityPathOnJcrContentParent); |
| when(vanityPathOnJcrContent.getValueMap()).thenReturn(buildValueMap("sling:vanityPath", "/target/vanityPathOnJcrContent")); |
| |
| addResource.invoke(mapEntries, "/vanityPathOnJcrContent/jcr:content", new AtomicBoolean()); |
| |
| entries = mapEntries.getResolveMaps(); |
| assertEquals(4, entries.size()); |
| |
| counter = (AtomicLong) vanityCounter.get(mapEntries); |
| assertEquals(4, counter.longValue()); |
| |
| vanityTargets = (Map<String, List<String>>) field.get(mapEntries); |
| assertEquals(2, vanityTargets.size()); |
| |
| assertNull(vanityTargets.get("/vanityPathOnJcrContent/jcr:content")); |
| assertNotNull(vanityTargets.get("/vanityPathOnJcrContent")); |
| } |
| |
| |
| @SuppressWarnings("unchecked") |
| @Test |
| public void test_doUpdateVanity() throws Exception { |
| Field field0 = MapEntries.class.getDeclaredField("resolveMapsMap"); |
| field0.setAccessible(true); |
| Map<String, List<MapEntry>> resolveMapsMap = (Map<String, List<MapEntry>>) field0.get(mapEntries); |
| assertEquals(1, resolveMapsMap.size()); |
| |
| Field field = MapEntries.class.getDeclaredField("vanityTargets"); |
| field.setAccessible(true); |
| Map<String, List<String>> vanityTargets = (Map<String, List<String>>) field.get(mapEntries); |
| assertEquals(0, vanityTargets.size()); |
| |
| final Method addResource = MapEntries.class.getDeclaredMethod("addResource", String.class, AtomicBoolean.class); |
| addResource.setAccessible(true); |
| |
| final Method updateResource = MapEntries.class.getDeclaredMethod("updateResource", String.class, AtomicBoolean.class); |
| updateResource.setAccessible(true); |
| |
| Resource justVanityPath = mock(Resource.class, "justVanityPath"); |
| when(resourceResolver.getResource("/justVanityPath")).thenReturn(justVanityPath); |
| when(justVanityPath.getPath()).thenReturn("/justVanityPath"); |
| when(justVanityPath.getName()).thenReturn("justVanityPath"); |
| when(justVanityPath.getValueMap()).thenReturn(buildValueMap("sling:vanityPath", "/target/justVanityPath")); |
| |
| addResource.invoke(mapEntries, "/justVanityPath", new AtomicBoolean()); |
| |
| assertEquals(2, resolveMapsMap.size()); |
| assertEquals(1, vanityTargets.size()); |
| assertNotNull(resolveMapsMap.get("/target/justVanityPath")); |
| assertNull(resolveMapsMap.get("/target/justVanityPathUpdated")); |
| assertEquals(1, vanityTargets.get("/justVanityPath").size()); |
| assertEquals("/target/justVanityPath", vanityTargets.get("/justVanityPath").get(0)); |
| |
| //update vanity path |
| when(justVanityPath.getValueMap()).thenReturn(buildValueMap("sling:vanityPath", "/target/justVanityPathUpdated")); |
| updateResource.invoke(mapEntries, "/justVanityPath", new AtomicBoolean()); |
| |
| assertEquals(2, resolveMapsMap.size()); |
| assertEquals(1, vanityTargets.size()); |
| assertNull(resolveMapsMap.get("/target/justVanityPath")); |
| assertNotNull(resolveMapsMap.get("/target/justVanityPathUpdated")); |
| assertEquals(1, vanityTargets.get("/justVanityPath").size()); |
| assertEquals("/target/justVanityPathUpdated", vanityTargets.get("/justVanityPath").get(0)); |
| |
| //vanity under jcr:content |
| Resource vanityPathOnJcrContentParent = mock(Resource.class, "vanityPathOnJcrContentParent"); |
| when(vanityPathOnJcrContentParent.getPath()).thenReturn("/vanityPathOnJcrContent"); |
| when(vanityPathOnJcrContentParent.getName()).thenReturn("vanityPathOnJcrContent"); |
| when(vanityPathOnJcrContentParent.getValueMap()).thenReturn(buildValueMap()); |
| |
| Resource vanityPathOnJcrContent = mock(Resource.class, "vanityPathOnJcrContent"); |
| when(resourceResolver.getResource("/vanityPathOnJcrContent/jcr:content")).thenReturn(vanityPathOnJcrContent); |
| when(vanityPathOnJcrContent.getPath()).thenReturn("/vanityPathOnJcrContent/jcr:content"); |
| when(vanityPathOnJcrContent.getName()).thenReturn("jcr:content"); |
| when(vanityPathOnJcrContent.getParent()).thenReturn(vanityPathOnJcrContentParent); |
| when(vanityPathOnJcrContent.getValueMap()).thenReturn(buildValueMap("sling:vanityPath", "/target/vanityPathOnJcrContent")); |
| |
| addResource.invoke(mapEntries, "/vanityPathOnJcrContent/jcr:content", new AtomicBoolean()); |
| |
| assertEquals(3, resolveMapsMap.size()); |
| assertEquals(2, vanityTargets.size()); |
| assertNotNull(resolveMapsMap.get("/target/vanityPathOnJcrContent")); |
| assertNull(resolveMapsMap.get("/target/vanityPathOnJcrContentUpdated")); |
| assertEquals(1, vanityTargets.get("/vanityPathOnJcrContent").size()); |
| assertEquals("/target/vanityPathOnJcrContent", vanityTargets.get("/vanityPathOnJcrContent").get(0)); |
| |
| //update vanity path |
| when(vanityPathOnJcrContent.getValueMap()).thenReturn(buildValueMap("sling:vanityPath", "/target/vanityPathOnJcrContentUpdated")); |
| updateResource.invoke(mapEntries, "/vanityPathOnJcrContent/jcr:content", new AtomicBoolean()); |
| |
| assertEquals(3, resolveMapsMap.size()); |
| assertEquals(2, vanityTargets.size()); |
| assertNull(resolveMapsMap.get("/target/vanityPathOnJcrContent")); |
| assertNotNull(resolveMapsMap.get("/target/vanityPathOnJcrContentUpdated")); |
| assertEquals(1, vanityTargets.get("/vanityPathOnJcrContent").size()); |
| assertEquals("/target/vanityPathOnJcrContentUpdated", vanityTargets.get("/vanityPathOnJcrContent").get(0)); |
| } |
| |
| @SuppressWarnings("unchecked") |
| @Test |
| public void test_doRemoveVanity() throws Exception { |
| Field field0 = MapEntries.class.getDeclaredField("resolveMapsMap"); |
| field0.setAccessible(true); |
| Map<String, List<MapEntry>> resolveMapsMap = (Map<String, List<MapEntry>>) field0.get(mapEntries); |
| assertEquals(1, resolveMapsMap.size()); |
| |
| Field field = MapEntries.class.getDeclaredField("vanityTargets"); |
| field.setAccessible(true); |
| Map<String, List<String>> vanityTargets = (Map<String, List<String>>) field.get(mapEntries); |
| assertEquals(0, vanityTargets.size()); |
| |
| final Method addResource = MapEntries.class.getDeclaredMethod("addResource", String.class, AtomicBoolean.class); |
| addResource.setAccessible(true); |
| |
| Method method1 = MapEntries.class.getDeclaredMethod("doRemoveVanity", String.class); |
| method1.setAccessible(true); |
| |
| Resource justVanityPath = mock(Resource.class, "justVanityPath"); |
| when(resourceResolver.getResource("/justVanityPath")).thenReturn(justVanityPath); |
| when(justVanityPath.getPath()).thenReturn("/justVanityPath"); |
| when(justVanityPath.getName()).thenReturn("justVanityPath"); |
| when(justVanityPath.getValueMap()).thenReturn(buildValueMap("sling:vanityPath", "/target/justVanityPath")); |
| |
| addResource.invoke(mapEntries, "/justVanityPath", new AtomicBoolean()); |
| |
| Field vanityCounter = MapEntries.class.getDeclaredField("vanityCounter"); |
| vanityCounter.setAccessible(true); |
| AtomicLong counter = (AtomicLong) vanityCounter.get(mapEntries); |
| assertEquals(2, counter.longValue()); |
| assertEquals(2, resolveMapsMap.size()); |
| assertEquals(1, vanityTargets.size()); |
| assertNotNull(resolveMapsMap.get("/target/justVanityPath")); |
| assertEquals(1, vanityTargets.get("/justVanityPath").size()); |
| assertEquals("/target/justVanityPath", vanityTargets.get("/justVanityPath").get(0)); |
| |
| //remove vanity path |
| method1.invoke(mapEntries, "/justVanityPath"); |
| |
| counter = (AtomicLong) vanityCounter.get(mapEntries); |
| assertEquals(0, counter.longValue()); |
| |
| assertEquals(1, resolveMapsMap.size()); |
| assertEquals(0, vanityTargets.size()); |
| assertNull(resolveMapsMap.get("/target/justVanityPath")); |
| |
| //vanity under jcr:content |
| Resource vanityPathOnJcrContentParent = mock(Resource.class, "vanityPathOnJcrContentParent"); |
| when(vanityPathOnJcrContentParent.getPath()).thenReturn("/vanityPathOnJcrContent"); |
| when(vanityPathOnJcrContentParent.getName()).thenReturn("vanityPathOnJcrContent"); |
| |
| Resource vanityPathOnJcrContent = mock(Resource.class, "vanityPathOnJcrContent"); |
| when(resourceResolver.getResource("/vanityPathOnJcrContent/jcr:content")).thenReturn(vanityPathOnJcrContent); |
| when(vanityPathOnJcrContent.getPath()).thenReturn("/vanityPathOnJcrContent/jcr:content"); |
| when(vanityPathOnJcrContent.getName()).thenReturn("jcr:content"); |
| when(vanityPathOnJcrContent.getParent()).thenReturn(vanityPathOnJcrContentParent); |
| when(vanityPathOnJcrContent.getValueMap()).thenReturn(buildValueMap("sling:vanityPath", "/target/vanityPathOnJcrContent")); |
| |
| addResource.invoke(mapEntries, "/vanityPathOnJcrContent/jcr:content", new AtomicBoolean()); |
| |
| assertEquals(2, resolveMapsMap.size()); |
| assertEquals(1, vanityTargets.size()); |
| assertNotNull(resolveMapsMap.get("/target/vanityPathOnJcrContent")); |
| assertEquals(1,vanityTargets.get("/vanityPathOnJcrContent").size()); |
| assertEquals("/target/vanityPathOnJcrContent", vanityTargets.get("/vanityPathOnJcrContent").get(0)); |
| |
| //remove vanity path |
| method1.invoke(mapEntries, "/vanityPathOnJcrContent/jcr:content"); |
| |
| assertEquals(1, resolveMapsMap.size()); |
| assertEquals(0, vanityTargets.size()); |
| assertNull(resolveMapsMap.get("/target/vanityPathOnJcrContent")); |
| |
| } |
| /* |
| @SuppressWarnings("unchecked") |
| @Test |
| public void test_doUpdateVanityOrder() throws Exception { |
| Field field0 = MapEntries.class.getDeclaredField("resolveMapsMap"); |
| field0.setAccessible(true); |
| Map<String, List<MapEntry>> resolveMapsMap = (Map<String, List<MapEntry>>) field0.get(mapEntries); |
| assertEquals(1, resolveMapsMap.size()); |
| |
| Field field = MapEntries.class.getDeclaredField("vanityTargets"); |
| field.setAccessible(true); |
| Map<String, List<String>> vanityTargets = (Map<String, List<String>>) field.get(mapEntries); |
| assertEquals(0, vanityTargets.size()); |
| |
| Method method = MapEntries.class.getDeclaredMethod("doAddVanity", String.class); |
| method.setAccessible(true); |
| |
| Method method1 = MapEntries.class.getDeclaredMethod("doUpdateVanityOrder", String.class, boolean.class); |
| method1.setAccessible(true); |
| |
| Resource justVanityPath = mock(Resource.class, "justVanityPath"); |
| when(resourceResolver.getResource("/justVanityPath")).thenReturn(justVanityPath); |
| when(justVanityPath.getPath()).thenReturn("/justVanityPath"); |
| when(justVanityPath.getName()).thenReturn("justVanityPath"); |
| when(justVanityPath.getValueMap()).thenReturn(buildValueMap("sling:vanityPath", "/target/justVanityPath")); |
| |
| method.invoke(mapEntries, "/justVanityPath"); |
| |
| Resource justVanityPath2 = mock(Resource.class, "justVanityPath2"); |
| when(resourceResolver.getResource("/justVanityPath2")).thenReturn(justVanityPath2); |
| when(justVanityPath2.getPath()).thenReturn("/justVanityPath2"); |
| when(justVanityPath2.getName()).thenReturn("justVanityPath2"); |
| when(justVanityPath2.getValueMap()).thenReturn(buildValueMap("sling:vanityPath", "/target/justVanityPath","sling:vanityOrder", 100)); |
| |
| method.invoke(mapEntries, "/justVanityPath2"); |
| |
| assertEquals(2, resolveMapsMap.size()); |
| assertEquals(2, vanityTargets.size()); |
| assertNotNull(resolveMapsMap.get("/target/justVanityPath")); |
| |
| Iterator <MapEntry> iterator = resolveMapsMap.get("/target/justVanityPath").iterator(); |
| assertEquals("/justVanityPath2$1", iterator.next().getRedirect()[0]); |
| assertEquals("/justVanityPath$1", iterator.next().getRedirect()[0]); |
| assertEquals("/justVanityPath2.html", iterator.next().getRedirect()[0]); |
| assertEquals("/justVanityPath.html", iterator.next().getRedirect()[0]); |
| assertFalse(iterator.hasNext()); |
| |
| when(justVanityPath.getValueMap()).thenReturn(buildValueMap("sling:vanityPath", "/target/justVanityPath","sling:vanityOrder", 1000)); |
| method1.invoke(mapEntries, "/justVanityPath",false); |
| |
| iterator = resolveMapsMap.get("/target/justVanityPath").iterator(); |
| assertEquals("/justVanityPath$1", iterator.next().getRedirect()[0]); |
| assertEquals("/justVanityPath2$1", iterator.next().getRedirect()[0]); |
| assertEquals("/justVanityPath.html", iterator.next().getRedirect()[0]); |
| assertEquals("/justVanityPath2.html", iterator.next().getRedirect()[0]); |
| assertFalse(iterator.hasNext()); |
| |
| when(justVanityPath.getValueMap()).thenReturn(buildValueMap("sling:vanityPath", "/target/justVanityPath")); |
| method1.invoke(mapEntries, "/justVanityPath",true); |
| |
| iterator = resolveMapsMap.get("/target/justVanityPath").iterator(); |
| assertEquals("/justVanityPath2$1", iterator.next().getRedirect()[0]); |
| assertEquals("/justVanityPath$1", iterator.next().getRedirect()[0]); |
| assertEquals("/justVanityPath2.html", iterator.next().getRedirect()[0]); |
| assertEquals("/justVanityPath.html", iterator.next().getRedirect()[0]); |
| assertFalse(iterator.hasNext()); |
| } |
| */ |
| |
| //SLING-3727 |
| @Test |
| public void test_doAddAliasAttributesWithDisableAliasOptimization() throws Exception { |
| final Method addResource = MapEntries.class.getDeclaredMethod("addResource", String.class, AtomicBoolean.class); |
| addResource.setAccessible(true); |
| |
| when(resourceResolverFactory.isOptimizeAliasResolutionEnabled()).thenReturn(false); |
| mapEntries = new MapEntries(resourceResolverFactory, bundleContext, eventAdmin); |
| |
| Resource parent = mock(Resource.class); |
| when(parent.getPath()).thenReturn("/parent"); |
| |
| final Resource result = mock(Resource.class); |
| when(resourceResolver.getResource("/parent/child")).thenReturn(result); |
| when(result.getParent()).thenReturn(parent); |
| when(result.getPath()).thenReturn("/parent/child"); |
| when(result.getName()).thenReturn("child"); |
| when(result.getValueMap()).thenReturn(buildValueMap(ResourceResolverImpl.PROP_ALIAS, "alias")); |
| |
| addResource.invoke(mapEntries, "/parent/child", new AtomicBoolean()); |
| |
| Map<String, String> aliasMap = mapEntries.getAliasMap("/parent"); |
| assertNull(aliasMap); |
| } |
| |
| //SLING-3727 |
| @Test |
| public void test_doUpdateAttributesWithDisableAliasOptimization() throws Exception { |
| final Method addResource = MapEntries.class.getDeclaredMethod("addResource", String.class, AtomicBoolean.class); |
| addResource.setAccessible(true); |
| |
| when(resourceResolverFactory.isOptimizeAliasResolutionEnabled()).thenReturn(false); |
| mapEntries = new MapEntries(resourceResolverFactory, bundleContext, eventAdmin); |
| |
| Resource parent = mock(Resource.class); |
| when(parent.getPath()).thenReturn("/parent"); |
| |
| final Resource result = mock(Resource.class); |
| when(resourceResolver.getResource("/parent/child")).thenReturn(result); |
| when(result.getParent()).thenReturn(parent); |
| when(result.getPath()).thenReturn("/parent/child"); |
| when(result.getName()).thenReturn("child"); |
| when(result.getValueMap()).thenReturn(buildValueMap(ResourceResolverImpl.PROP_ALIAS, "alias")); |
| |
| addResource.invoke(mapEntries, "/parent/child", new AtomicBoolean()); |
| |
| Map<String, String> aliasMap = mapEntries.getAliasMap("/parent"); |
| assertNull(aliasMap); |
| } |
| |
| //SLING-3727 |
| @Test |
| public void test_doRemoveAttributessWithDisableAliasOptimization() throws Exception { |
| final Method removeAlias = MapEntries.class.getDeclaredMethod("removeAlias", String.class, String.class, AtomicBoolean.class); |
| removeAlias.setAccessible(true); |
| |
| when(resourceResolverFactory.isOptimizeAliasResolutionEnabled()).thenReturn(false); |
| mapEntries = new MapEntries(resourceResolverFactory, bundleContext, eventAdmin); |
| |
| Resource parent = mock(Resource.class); |
| when(parent.getPath()).thenReturn("/parent"); |
| |
| final Resource result = mock(Resource.class); |
| when(resourceResolver.getResource("/parent/child")).thenReturn(result); |
| when(result.getParent()).thenReturn(parent); |
| when(result.getPath()).thenReturn("/parent/child"); |
| when(result.getName()).thenReturn("child"); |
| when(result.getValueMap()).thenReturn(buildValueMap(ResourceResolverImpl.PROP_ALIAS, "alias")); |
| |
| removeAlias.invoke(mapEntries, "/parent", "/parent/child", new AtomicBoolean()); |
| |
| Map<String, String> aliasMap = mapEntries.getAliasMap("/parent"); |
| assertNull(aliasMap); |
| } |
| |
| @Test |
| public void test_doAddAlias() throws Exception { |
| final Method addResource = MapEntries.class.getDeclaredMethod("addResource", String.class, AtomicBoolean.class); |
| addResource.setAccessible(true); |
| |
| assertEquals(0, aliasMap.size()); |
| |
| Resource parent = mock(Resource.class); |
| when(parent.getPath()).thenReturn("/parent"); |
| |
| final Resource result = mock(Resource.class); |
| when(resourceResolver.getResource("/parent/child")).thenReturn(result); |
| when(result.getParent()).thenReturn(parent); |
| when(result.getPath()).thenReturn("/parent/child"); |
| when(result.getName()).thenReturn("child"); |
| when(result.getValueMap()).thenReturn(buildValueMap(ResourceResolverImpl.PROP_ALIAS, "alias")); |
| |
| addResource.invoke(mapEntries, "/parent/child", new AtomicBoolean()); |
| |
| Map<String, String> aliasMapEntry = mapEntries.getAliasMap("/parent"); |
| assertNotNull(aliasMapEntry); |
| assertTrue(aliasMapEntry.containsKey("alias")); |
| assertEquals("child", aliasMapEntry.get("alias")); |
| |
| assertEquals(1, aliasMap.size()); |
| |
| //test_that_duplicate_alias_doesnt_replace_first_alias |
| final Resource secondResult = mock(Resource.class); |
| when(resourceResolver.getResource("/parent/child2")).thenReturn(secondResult); |
| when(secondResult.getParent()).thenReturn(parent); |
| when(secondResult.getPath()).thenReturn("/parent/child2"); |
| when(secondResult.getName()).thenReturn("child2"); |
| when(secondResult.getValueMap()).thenReturn(buildValueMap(ResourceResolverImpl.PROP_ALIAS, "alias")); |
| |
| addResource.invoke(mapEntries, "/parent/child2", new AtomicBoolean()); |
| |
| aliasMapEntry = mapEntries.getAliasMap("/parent"); |
| assertNotNull(aliasMapEntry); |
| assertTrue(aliasMapEntry.containsKey("alias")); |
| assertEquals("child", aliasMapEntry.get("alias")); |
| |
| assertEquals(1, aliasMap.size()); |
| |
| //testing jcr:content node |
| final Resource jcrContentResult = mock(Resource.class); |
| when(resourceResolver.getResource("/parent/child/jcr:content")).thenReturn(jcrContentResult); |
| when(jcrContentResult.getParent()).thenReturn(result); |
| when(jcrContentResult.getPath()).thenReturn("/parent/child/jcr:content"); |
| when(jcrContentResult.getName()).thenReturn("jcr:content"); |
| when(jcrContentResult.getValueMap()).thenReturn(buildValueMap(ResourceResolverImpl.PROP_ALIAS, "aliasJcrContent")); |
| |
| addResource.invoke(mapEntries, "/parent/child/jcr:content", new AtomicBoolean()); |
| |
| aliasMapEntry = mapEntries.getAliasMap("/parent"); |
| assertNotNull(aliasMapEntry); |
| assertEquals(2, aliasMapEntry.size()); |
| assertTrue(aliasMapEntry.containsKey("aliasJcrContent")); |
| assertEquals("child", aliasMapEntry.get("aliasJcrContent")); |
| |
| assertEquals(1, aliasMap.size()); |
| } |
| |
| @Test |
| public void test_doAddAlias2() throws Exception { |
| final Method addResource = MapEntries.class.getDeclaredMethod("addResource", String.class, AtomicBoolean.class); |
| addResource.setAccessible(true); |
| |
| assertEquals(0, aliasMap.size()); |
| |
| Resource parent = mock(Resource.class); |
| when(parent.getPath()).thenReturn("/"); |
| |
| final Resource result = mock(Resource.class); |
| when(resourceResolver.getResource("/parent")).thenReturn(result); |
| when(result.getParent()).thenReturn(parent); |
| when(result.getPath()).thenReturn("/parent"); |
| when(result.getName()).thenReturn("parent"); |
| when(result.getValueMap()).thenReturn(buildValueMap(ResourceResolverImpl.PROP_ALIAS, "alias")); |
| |
| addResource.invoke(mapEntries, "/parent", new AtomicBoolean()); |
| |
| Map<String, String> aliasMapEntry = mapEntries.getAliasMap("/"); |
| assertNotNull(aliasMapEntry); |
| assertTrue(aliasMapEntry.containsKey("alias")); |
| assertEquals("parent", aliasMapEntry.get("alias")); |
| |
| assertEquals(1, aliasMap.size()); |
| |
| //test_that_duplicate_alias_doesnt_replace_first_alias |
| final Resource secondResult = mock(Resource.class); |
| when(resourceResolver.getResource("/parent2")).thenReturn(secondResult); |
| when(secondResult.getParent()).thenReturn(parent); |
| when(secondResult.getPath()).thenReturn("/parent2"); |
| when(secondResult.getName()).thenReturn("parent2"); |
| when(secondResult.getValueMap()).thenReturn(buildValueMap(ResourceResolverImpl.PROP_ALIAS, "alias")); |
| |
| addResource.invoke(mapEntries, "/parent2", new AtomicBoolean()); |
| |
| aliasMapEntry = mapEntries.getAliasMap("/"); |
| assertNotNull(aliasMapEntry); |
| assertTrue(aliasMapEntry.containsKey("alias")); |
| assertEquals("parent", aliasMapEntry.get("alias")); |
| |
| assertEquals(1, aliasMap.size()); |
| |
| //testing jcr:content node |
| final Resource jcrContentResult = mock(Resource.class); |
| when(resourceResolver.getResource("/parent/jcr:content")).thenReturn(jcrContentResult); |
| when(jcrContentResult.getParent()).thenReturn(result); |
| when(jcrContentResult.getPath()).thenReturn("/parent/jcr:content"); |
| when(jcrContentResult.getName()).thenReturn("jcr:content"); |
| when(jcrContentResult.getValueMap()).thenReturn(buildValueMap(ResourceResolverImpl.PROP_ALIAS, "aliasJcrContent")); |
| |
| addResource.invoke(mapEntries, "/parent/jcr:content", new AtomicBoolean()); |
| |
| aliasMapEntry = mapEntries.getAliasMap("/"); |
| assertNotNull(aliasMapEntry); |
| assertEquals(2, aliasMapEntry.size()); |
| assertTrue(aliasMapEntry.containsKey("aliasJcrContent")); |
| assertEquals("parent", aliasMapEntry.get("aliasJcrContent")); |
| |
| assertEquals(1, aliasMap.size()); |
| } |
| |
| @Test |
| public void test_doUpdateAlias() throws Exception { |
| final Method updateResource = MapEntries.class.getDeclaredMethod("updateResource", String.class, AtomicBoolean.class); |
| updateResource.setAccessible(true); |
| |
| assertEquals(0, aliasMap.size()); |
| |
| Resource parent = mock(Resource.class); |
| when(parent.getPath()).thenReturn("/parent"); |
| |
| final Resource result = mock(Resource.class); |
| when(resourceResolver.getResource("/parent/child")).thenReturn(result); |
| when(result.getParent()).thenReturn(parent); |
| when(result.getPath()).thenReturn("/parent/child"); |
| when(result.getName()).thenReturn("child"); |
| when(result.getValueMap()).thenReturn(buildValueMap(ResourceResolverImpl.PROP_ALIAS, "alias")); |
| |
| updateResource.invoke(mapEntries, "/parent/child", new AtomicBoolean()); |
| |
| Map<String, String> aliasMapEntry = mapEntries.getAliasMap("/parent"); |
| assertNotNull(aliasMapEntry); |
| assertTrue(aliasMapEntry.containsKey("alias")); |
| assertFalse(aliasMapEntry.containsKey("aliasUpdated")); |
| assertEquals("child", aliasMapEntry.get("alias")); |
| |
| assertEquals(1, aliasMap.size()); |
| |
| when(result.getValueMap()).thenReturn(buildValueMap(ResourceResolverImpl.PROP_ALIAS, "aliasUpdated")); |
| |
| updateResource.invoke(mapEntries, "/parent/child", new AtomicBoolean()); |
| |
| aliasMapEntry = mapEntries.getAliasMap("/parent"); |
| assertNotNull(aliasMapEntry); |
| assertFalse(aliasMapEntry.containsKey("alias")); |
| assertTrue(aliasMapEntry.containsKey("aliasUpdated")); |
| assertEquals("child", aliasMapEntry.get("aliasUpdated")); |
| |
| assertEquals(1, aliasMap.size()); |
| |
| //testing jcr:content node update |
| final Resource jcrContentResult = mock(Resource.class); |
| when(resourceResolver.getResource("/parent/child/jcr:content")).thenReturn(jcrContentResult); |
| when(jcrContentResult.getParent()).thenReturn(result); |
| when(jcrContentResult.getPath()).thenReturn("/parent/child/jcr:content"); |
| when(jcrContentResult.getName()).thenReturn("jcr:content"); |
| when(jcrContentResult.getValueMap()).thenReturn(buildValueMap(ResourceResolverImpl.PROP_ALIAS, "aliasJcrContent")); |
| when(result.getChild("jcr:content")).thenReturn(jcrContentResult); |
| |
| updateResource.invoke(mapEntries, "/parent/child/jcr:content", new AtomicBoolean()); |
| |
| aliasMapEntry = mapEntries.getAliasMap("/parent"); |
| assertNotNull(aliasMapEntry); |
| assertEquals(2, aliasMapEntry.size()); |
| assertTrue(aliasMapEntry.containsKey("aliasJcrContent")); |
| assertFalse(aliasMapEntry.containsKey("aliasJcrContentUpdated")); |
| assertEquals("child", aliasMapEntry.get("aliasJcrContent")); |
| |
| assertEquals(1, aliasMap.size()); |
| |
| when(jcrContentResult.getValueMap()).thenReturn(buildValueMap(ResourceResolverImpl.PROP_ALIAS, "aliasJcrContentUpdated")); |
| updateResource.invoke(mapEntries, "/parent/child/jcr:content", new AtomicBoolean()); |
| |
| aliasMapEntry = mapEntries.getAliasMap("/parent"); |
| assertNotNull(aliasMapEntry); |
| assertEquals(2, aliasMapEntry.size()); |
| assertFalse(aliasMapEntry.containsKey("aliasJcrContent")); |
| assertTrue(aliasMapEntry.containsKey("aliasJcrContentUpdated")); |
| assertEquals("child", aliasMapEntry.get("aliasJcrContentUpdated")); |
| |
| assertEquals(1, aliasMap.size()); |
| |
| //re-update alias |
| updateResource.invoke(mapEntries, "/parent/child", new AtomicBoolean()); |
| |
| aliasMapEntry = mapEntries.getAliasMap("/parent"); |
| assertNotNull(aliasMapEntry); |
| assertEquals(2, aliasMapEntry.size()); |
| assertFalse(aliasMapEntry.containsKey("alias")); |
| assertTrue(aliasMapEntry.containsKey("aliasUpdated")); |
| assertEquals("child", aliasMapEntry.get("aliasUpdated")); |
| |
| //add another node with different alias and check that the update doesn't break anything (see also SLING-3728) |
| final Resource secondResult = mock(Resource.class); |
| when(resourceResolver.getResource("/parent/child2")).thenReturn(secondResult); |
| when(secondResult.getParent()).thenReturn(parent); |
| when(secondResult.getPath()).thenReturn("/parent/child2"); |
| when(secondResult.getName()).thenReturn("child2"); |
| when(secondResult.getValueMap()).thenReturn(buildValueMap(ResourceResolverImpl.PROP_ALIAS, "alias2")); |
| |
| updateResource.invoke(mapEntries, "/parent/child2", new AtomicBoolean()); |
| assertEquals(1, aliasMap.size()); |
| |
| aliasMapEntry = mapEntries.getAliasMap("/parent"); |
| assertNotNull(aliasMapEntry); |
| assertEquals(3, aliasMapEntry.size()); |
| |
| when(jcrContentResult.getValueMap()).thenReturn(buildValueMap(ResourceResolverImpl.PROP_ALIAS, "aliasJcrContentUpdated")); |
| updateResource.invoke(mapEntries, "/parent/child/jcr:content", new AtomicBoolean()); |
| |
| aliasMapEntry = mapEntries.getAliasMap("/parent"); |
| assertNotNull(aliasMapEntry); |
| assertEquals(3, aliasMapEntry.size()); |
| assertFalse(aliasMapEntry.containsKey("aliasJcrContent")); |
| assertTrue(aliasMapEntry.containsKey("aliasJcrContentUpdated")); |
| assertEquals("child", aliasMapEntry.get("aliasJcrContentUpdated")); |
| |
| assertEquals(1, aliasMap.size()); |
| |
| |
| when(result.getValueMap()).thenReturn(buildValueMap(ResourceResolverImpl.PROP_ALIAS, null)); |
| when(jcrContentResult.getValueMap()).thenReturn(buildValueMap(ResourceResolverImpl.PROP_ALIAS, "aliasJcrContentUpdated")); |
| updateResource.invoke(mapEntries, "/parent/child/jcr:content", new AtomicBoolean()); |
| |
| aliasMapEntry = mapEntries.getAliasMap("/parent"); |
| assertNotNull(aliasMapEntry); |
| assertEquals(2, aliasMapEntry.size()); |
| assertFalse(aliasMapEntry.containsKey("aliasJcrContent")); |
| assertTrue(aliasMapEntry.containsKey("aliasJcrContentUpdated")); |
| assertEquals("child", aliasMapEntry.get("aliasJcrContentUpdated")); |
| |
| assertEquals(1, aliasMap.size()); |
| |
| } |
| |
| @Test |
| public void test_doRemoveAlias() throws Exception { |
| final Method addResource = MapEntries.class.getDeclaredMethod("addResource", String.class, AtomicBoolean.class); |
| addResource.setAccessible(true); |
| |
| final Method removeAlias = MapEntries.class.getDeclaredMethod("removeAlias", String.class, String.class, AtomicBoolean.class); |
| removeAlias.setAccessible(true); |
| |
| // check that alias map is empty |
| assertEquals(0, aliasMap.size()); |
| |
| final Resource parent = mock(Resource.class); |
| when(parent.getPath()).thenReturn("/parent"); |
| |
| final Resource child = mock(Resource.class); |
| when(resourceResolver.getResource("/parent/child")).thenReturn(child); |
| when(child.getParent()).thenReturn(parent); |
| when(child.getPath()).thenReturn("/parent/child"); |
| when(child.getName()).thenReturn("child"); |
| when(child.getValueMap()).thenReturn(buildValueMap(ResourceResolverImpl.PROP_ALIAS, "alias")); |
| |
| addResource.invoke(mapEntries, "/parent/child", new AtomicBoolean()); |
| |
| Map<String, String> aliasMapEntry = mapEntries.getAliasMap("/parent"); |
| assertNotNull(aliasMapEntry); |
| assertTrue(aliasMapEntry.containsKey("alias")); |
| assertEquals("child", aliasMapEntry.get("alias")); |
| |
| assertEquals(1, aliasMap.size()); |
| |
| removeAlias.invoke(mapEntries, "/parent", "/parent/child", new AtomicBoolean()); |
| |
| aliasMapEntry = mapEntries.getAliasMap("/parent"); |
| assertNull(aliasMapEntry); |
| |
| assertEquals(0, aliasMap.size()); |
| |
| //re-add node and test nodeDeletion true |
| addResource.invoke(mapEntries, "/parent/child", new AtomicBoolean()); |
| |
| aliasMapEntry = mapEntries.getAliasMap("/parent"); |
| assertNotNull(aliasMapEntry); |
| assertTrue(aliasMapEntry.containsKey("alias")); |
| assertEquals("child", aliasMapEntry.get("alias")); |
| |
| assertEquals(1, aliasMap.size()); |
| |
| when(resourceResolver.getResource("/parent/child")).thenReturn(null); |
| removeAlias.invoke(mapEntries, "/parent", "/parent/child", new AtomicBoolean()); |
| |
| aliasMapEntry = mapEntries.getAliasMap("/parent"); |
| assertNull(aliasMapEntry); |
| |
| assertEquals(0, aliasMap.size()); |
| } |
| |
| @Test |
| public void test_doRemoveAlias2() throws Exception { |
| final Method addResource = MapEntries.class.getDeclaredMethod("addResource", String.class, AtomicBoolean.class); |
| addResource.setAccessible(true); |
| |
| final Method removeAlias = MapEntries.class.getDeclaredMethod("removeAlias", String.class, String.class, AtomicBoolean.class); |
| removeAlias.setAccessible(true); |
| |
| assertEquals(0, aliasMap.size()); |
| |
| Resource parent = mock(Resource.class); |
| when(parent.getPath()).thenReturn("/parent"); |
| |
| final Resource result = mock(Resource.class); |
| when(resourceResolver.getResource("/parent/child")).thenReturn(result); |
| when(result.getParent()).thenReturn(parent); |
| when(result.getPath()).thenReturn("/parent/child"); |
| when(result.getName()).thenReturn("child"); |
| when(result.getValueMap()).thenReturn(buildValueMap()); |
| |
| //testing jcr:content node removal |
| final Resource jcrContentResult = mock(Resource.class); |
| when(resourceResolver.getResource("/parent/child/jcr:content")).thenReturn(jcrContentResult); |
| when(jcrContentResult.getParent()).thenReturn(result); |
| when(jcrContentResult.getPath()).thenReturn("/parent/child/jcr:content"); |
| when(jcrContentResult.getName()).thenReturn("jcr:content"); |
| when(jcrContentResult.getValueMap()).thenReturn(buildValueMap(ResourceResolverImpl.PROP_ALIAS, "aliasJcrContent")); |
| when(result.getChild("jcr:content")).thenReturn(jcrContentResult); |
| |
| addResource.invoke(mapEntries, "/parent/child/jcr:content", new AtomicBoolean()); |
| |
| Map<String, String> aliasMapEntry = mapEntries.getAliasMap("/parent"); |
| assertNotNull(aliasMapEntry); |
| assertTrue(aliasMapEntry.containsKey("aliasJcrContent")); |
| assertEquals("child", aliasMapEntry.get("aliasJcrContent")); |
| |
| assertEquals(1, aliasMap.size()); |
| |
| removeAlias.invoke(mapEntries, "/parent", "/parent/child/jcr:content", new AtomicBoolean()); |
| |
| aliasMapEntry = mapEntries.getAliasMap("/parent"); |
| assertNull(aliasMapEntry); |
| |
| assertEquals(0, aliasMap.size()); |
| |
| //re-add node and test nodeDeletion true |
| addResource.invoke(mapEntries, "/parent/child/jcr:content", new AtomicBoolean()); |
| |
| aliasMapEntry = mapEntries.getAliasMap("/parent"); |
| assertNotNull(aliasMapEntry); |
| assertTrue(aliasMapEntry.containsKey("aliasJcrContent")); |
| assertEquals("child", aliasMapEntry.get("aliasJcrContent")); |
| |
| assertEquals(1, aliasMap.size()); |
| when(resourceResolver.getResource("/parent/child/jcr:content")).thenReturn(null); |
| when(result.getChild("jcr:content")).thenReturn(null); |
| removeAlias.invoke(mapEntries, "/parent", "/parent/child/jcr:content", new AtomicBoolean()); |
| |
| aliasMapEntry = mapEntries.getAliasMap("/parent"); |
| assertNull(aliasMapEntry); |
| |
| assertEquals(0, aliasMap.size()); |
| } |
| |
| @Test |
| public void test_doRemoveAlias3() throws Exception { |
| final Method addResource = MapEntries.class.getDeclaredMethod("addResource", String.class, AtomicBoolean.class); |
| addResource.setAccessible(true); |
| |
| final Method removeAlias = MapEntries.class.getDeclaredMethod("removeAlias", String.class, String.class, AtomicBoolean.class); |
| removeAlias.setAccessible(true); |
| |
| assertEquals(0, aliasMap.size()); |
| |
| final Resource parentRsrc = mock(Resource.class); |
| when(parentRsrc.getPath()).thenReturn("/parent"); |
| |
| final Resource childRsrc = mock(Resource.class); |
| when(resourceResolver.getResource("/parent/child")).thenReturn(childRsrc); |
| when(childRsrc.getParent()).thenReturn(parentRsrc); |
| when(childRsrc.getPath()).thenReturn("/parent/child"); |
| when(childRsrc.getName()).thenReturn("child"); |
| when(childRsrc.getValueMap()).thenReturn(buildValueMap(ResourceResolverImpl.PROP_ALIAS, "alias")); |
| |
| addResource.invoke(mapEntries, "/parent/child", new AtomicBoolean()); |
| |
| final Resource jcrContentResult = mock(Resource.class); |
| when(resourceResolver.getResource("/parent/child/jcr:content")).thenReturn(jcrContentResult); |
| when(jcrContentResult.getParent()).thenReturn(childRsrc); |
| when(jcrContentResult.getPath()).thenReturn("/parent/child/jcr:content"); |
| when(jcrContentResult.getName()).thenReturn("jcr:content"); |
| when(jcrContentResult.getValueMap()).thenReturn(buildValueMap(ResourceResolverImpl.PROP_ALIAS, "aliasJcrContent")); |
| when(childRsrc.getChild("jcr:content")).thenReturn(jcrContentResult); |
| |
| addResource.invoke(mapEntries, "/parent/child/jcr:content", new AtomicBoolean()); |
| |
| // test with two nodes |
| assertEquals(1, aliasMap.size()); |
| Map<String, String> aliasMapEntry = mapEntries.getAliasMap("/parent"); |
| assertNotNull(aliasMapEntry); |
| assertEquals(2, aliasMapEntry.size()); |
| assertEquals("child", aliasMapEntry.get("aliasJcrContent")); |
| assertEquals("child", aliasMapEntry.get("alias")); |
| |
| // remove child jcr:content node |
| removeAlias.invoke(mapEntries, "/parent", "/parent/child/jcr:content", new AtomicBoolean()); |
| |
| // test with one node |
| assertEquals(1, aliasMap.size()); |
| aliasMapEntry = mapEntries.getAliasMap("/parent"); |
| assertNotNull(aliasMapEntry); |
| assertEquals(1, aliasMapEntry.size()); |
| assertEquals("child", aliasMapEntry.get("alias")); |
| |
| // re-add the node and test /parent/child |
| addResource.invoke(mapEntries, "/parent/child/jcr:content", new AtomicBoolean()); |
| |
| // STOP |
| aliasMapEntry = mapEntries.getAliasMap("/parent"); |
| assertNotNull(aliasMapEntry); |
| assertEquals(2, aliasMapEntry.size()); |
| assertEquals("child", aliasMapEntry.get("aliasJcrContent")); |
| assertEquals("child", aliasMapEntry.get("alias")); |
| |
| removeAlias.invoke(mapEntries, "/parent", "/parent/child", new AtomicBoolean()); |
| addResource.invoke(mapEntries, "/parent/child/jcr:content", new AtomicBoolean()); |
| |
| assertEquals(1, aliasMap.size()); |
| aliasMapEntry = mapEntries.getAliasMap("/parent"); |
| assertNotNull(aliasMapEntry); |
| assertEquals(1, aliasMapEntry.size()); |
| assertEquals("child", aliasMapEntry.get("aliasJcrContent")); |
| |
| // re-add the node and test node removal |
| addResource.invoke(mapEntries, "/parent/child", new AtomicBoolean()); |
| |
| aliasMapEntry = mapEntries.getAliasMap("/parent"); |
| assertNotNull(aliasMapEntry); |
| assertTrue(aliasMapEntry.containsKey("aliasJcrContent")); |
| assertEquals("child", aliasMapEntry.get("aliasJcrContent")); |
| assertEquals(2, aliasMapEntry.size()); |
| |
| when(resourceResolver.getResource("/parent/child/jcr:content")).thenReturn(null); |
| when(childRsrc.getChild("jcr:content")).thenReturn(null); |
| removeAlias.invoke(mapEntries, "/parent", "/parent/child/jcr:content", new AtomicBoolean()); |
| |
| assertEquals(1, aliasMap.size()); |
| aliasMapEntry = mapEntries.getAliasMap("/parent"); |
| assertNotNull(aliasMapEntry); |
| assertEquals(1, aliasMapEntry.size()); |
| |
| // re-add the node and test node removal for /parent/child |
| when(resourceResolver.getResource("/parent/child/jcr:content")).thenReturn(jcrContentResult); |
| when(childRsrc.getChild("jcr:content")).thenReturn(jcrContentResult); |
| addResource.invoke(mapEntries, "/parent/child/jcr:content", new AtomicBoolean()); |
| |
| |
| aliasMapEntry = mapEntries.getAliasMap("/parent"); |
| assertNotNull(aliasMapEntry); |
| assertTrue(aliasMapEntry.containsKey("aliasJcrContent")); |
| assertEquals("child", aliasMapEntry.get("aliasJcrContent")); |
| assertEquals(2, aliasMapEntry.size()); |
| |
| removeAlias.invoke(mapEntries, "/parent", "/parent/child", new AtomicBoolean()); |
| |
| assertEquals(0, aliasMap.size()); |
| aliasMapEntry = mapEntries.getAliasMap("/parent"); |
| assertNull(aliasMapEntry); |
| } |
| |
| @Test |
| public void test_doRemoveAlias4() throws Exception { |
| final Method addResource = MapEntries.class.getDeclaredMethod("addResource", String.class, AtomicBoolean.class); |
| addResource.setAccessible(true); |
| |
| final Method removeAlias = MapEntries.class.getDeclaredMethod("removeAlias", String.class, String.class, AtomicBoolean.class); |
| removeAlias.setAccessible(true); |
| |
| assertEquals(0, aliasMap.size()); |
| |
| Resource parent = mock(Resource.class); |
| when(parent.getPath()).thenReturn("/"); |
| |
| final Resource result = mock(Resource.class); |
| when(resourceResolver.getResource("/parent")).thenReturn(result); |
| when(result.getParent()).thenReturn(parent); |
| when(result.getPath()).thenReturn("/parent"); |
| when(result.getName()).thenReturn("parent"); |
| when(result.getValueMap()).thenReturn(buildValueMap(ResourceResolverImpl.PROP_ALIAS, "alias")); |
| |
| addResource.invoke(mapEntries, "/parent", new AtomicBoolean()); |
| |
| Map<String, String> aliasMapEntry = mapEntries.getAliasMap("/"); |
| assertNotNull(aliasMapEntry); |
| assertTrue(aliasMapEntry.containsKey("alias")); |
| assertEquals("parent", aliasMapEntry.get("alias")); |
| |
| assertEquals(1, aliasMap.size()); |
| |
| removeAlias.invoke(mapEntries, "/", "/parent", new AtomicBoolean()); |
| |
| aliasMapEntry = mapEntries.getAliasMap("/"); |
| assertNull(aliasMapEntry); |
| |
| assertEquals(0, aliasMap.size()); |
| |
| //re-add node and test nodeDeletion true |
| addResource.invoke(mapEntries, "/parent", new AtomicBoolean()); |
| |
| aliasMapEntry = mapEntries.getAliasMap("/"); |
| assertNotNull(aliasMapEntry); |
| assertTrue(aliasMapEntry.containsKey("alias")); |
| assertEquals("parent", aliasMapEntry.get("alias")); |
| |
| assertEquals(1, aliasMap.size()); |
| |
| when(resourceResolver.getResource("/parent")).thenReturn(null); |
| removeAlias.invoke(mapEntries, "/", "/parent", new AtomicBoolean()); |
| |
| aliasMapEntry = mapEntries.getAliasMap("/"); |
| assertNull(aliasMapEntry); |
| |
| assertEquals(0, aliasMap.size()); |
| } |
| |
| @Test |
| public void test_doRemoveAlias5() throws Exception { |
| final Method addResource = MapEntries.class.getDeclaredMethod("addResource", String.class, AtomicBoolean.class); |
| addResource.setAccessible(true); |
| |
| final Method removeAlias = MapEntries.class.getDeclaredMethod("removeAlias", String.class, String.class, AtomicBoolean.class); |
| removeAlias.setAccessible(true); |
| |
| assertEquals(0, aliasMap.size()); |
| |
| Resource parent = mock(Resource.class); |
| when(parent.getPath()).thenReturn("/"); |
| |
| final Resource result = mock(Resource.class); |
| when(resourceResolver.getResource("/parent")).thenReturn(result); |
| when(result.getParent()).thenReturn(parent); |
| when(result.getPath()).thenReturn("/parent"); |
| when(result.getName()).thenReturn("parent"); |
| when(result.getValueMap()).thenReturn(buildValueMap()); |
| |
| //testing jcr:content node removal |
| final Resource jcrContentResult = mock(Resource.class); |
| when(resourceResolver.getResource("/parent/jcr:content")).thenReturn(jcrContentResult); |
| when(jcrContentResult.getParent()).thenReturn(result); |
| when(jcrContentResult.getPath()).thenReturn("/parent/jcr:content"); |
| when(jcrContentResult.getName()).thenReturn("jcr:content"); |
| when(jcrContentResult.getValueMap()).thenReturn(buildValueMap(ResourceResolverImpl.PROP_ALIAS, "aliasJcrContent")); |
| when(result.getChild("jcr:content")).thenReturn(jcrContentResult); |
| |
| addResource.invoke(mapEntries, "/parent/jcr:content", new AtomicBoolean()); |
| |
| Map<String, String> aliasMapEntry = mapEntries.getAliasMap("/"); |
| assertNotNull(aliasMapEntry); |
| assertTrue(aliasMapEntry.containsKey("aliasJcrContent")); |
| assertEquals("parent", aliasMapEntry.get("aliasJcrContent")); |
| |
| assertEquals(1, aliasMap.size()); |
| |
| removeAlias.invoke(mapEntries, "/", "/parent/jcr:content", new AtomicBoolean()); |
| |
| aliasMapEntry = mapEntries.getAliasMap("/"); |
| assertNull(aliasMapEntry); |
| |
| assertEquals(0, aliasMap.size()); |
| |
| //re-add node and test nodeDeletion true |
| addResource.invoke(mapEntries, "/parent/jcr:content", new AtomicBoolean()); |
| |
| aliasMapEntry = mapEntries.getAliasMap("/"); |
| assertNotNull(aliasMapEntry); |
| assertTrue(aliasMapEntry.containsKey("aliasJcrContent")); |
| assertEquals("parent", aliasMapEntry.get("aliasJcrContent")); |
| |
| assertEquals(1, aliasMap.size()); |
| when(resourceResolver.getResource("/parent/jcr:content")).thenReturn(null); |
| when(result.getChild("jcr:content")).thenReturn(null); |
| removeAlias.invoke(mapEntries, "/", "/parent/jcr:content", new AtomicBoolean()); |
| |
| aliasMapEntry = mapEntries.getAliasMap("/"); |
| assertNull(aliasMapEntry); |
| |
| assertEquals(0, aliasMap.size()); |
| } |
| |
| @Test |
| public void test_isValidVanityPath() throws Exception { |
| Method method = MapEntries.class.getDeclaredMethod("isValidVanityPath", String.class); |
| method.setAccessible(true); |
| |
| assertFalse((Boolean)method.invoke(mapEntries, "/jcr:system/node")); |
| |
| assertTrue((Boolean)method.invoke(mapEntries, "/justVanityPath")); |
| } |
| |
| @Test |
| //SLING-4847 |
| public void test_doNodeAdded1() throws Exception { |
| final Method addResource = MapEntries.class.getDeclaredMethod("addResource", String.class, AtomicBoolean.class); |
| addResource.setAccessible(true); |
| final AtomicBoolean refreshed = new AtomicBoolean(false); |
| addResource.invoke(mapEntries, "/node", refreshed); |
| assertTrue(refreshed.get()); |
| } |
| |
| @Test |
| //SLING-4891 |
| public void test_getVanityPaths_1() throws Exception { |
| |
| when(this.resourceResolverFactory.getMaxCachedVanityPathEntries()).thenReturn(0L); |
| |
| Method method = MapEntries.class.getDeclaredMethod("getVanityPaths", String.class); |
| method.setAccessible(true); |
| method.invoke(mapEntries, "/notExisting"); |
| |
| Field vanityCounter = MapEntries.class.getDeclaredField("vanityCounter"); |
| vanityCounter.setAccessible(true); |
| AtomicLong counter = (AtomicLong) vanityCounter.get(mapEntries); |
| assertEquals(0, counter.longValue()); |
| } |
| |
| @Test |
| //SLING-4891 |
| public void test_getVanityPaths_2() throws Exception { |
| |
| final Resource justVanityPath = mock(Resource.class, "justVanityPath"); |
| when(resourceResolver.getResource("/justVanityPath")).thenReturn(justVanityPath); |
| when(justVanityPath.getPath()).thenReturn("/justVanityPath"); |
| when(justVanityPath.getName()).thenReturn("justVanityPath"); |
| when(justVanityPath.getValueMap()).thenReturn(buildValueMap("sling:vanityPath", "/target/justVanityPath")); |
| |
| |
| when(resourceResolver.findResources(anyString(), eq("sql"))).thenAnswer(new Answer<Iterator<Resource>>() { |
| |
| @Override |
| public Iterator<Resource> answer(InvocationOnMock invocation) throws Throwable { |
| if (invocation.getArguments()[0].toString().contains("sling:vanityPath")) { |
| return Collections.singleton(justVanityPath).iterator(); |
| } else { |
| return Collections.<Resource> emptySet().iterator(); |
| } |
| } |
| }); |
| |
| when(this.resourceResolverFactory.getMaxCachedVanityPathEntries()).thenReturn(0L); |
| |
| Method method = MapEntries.class.getDeclaredMethod("getVanityPaths", String.class); |
| method.setAccessible(true); |
| method.invoke(mapEntries, "/target/justVanityPath"); |
| |
| Field vanityCounter = MapEntries.class.getDeclaredField("vanityCounter"); |
| vanityCounter.setAccessible(true); |
| AtomicLong counter = (AtomicLong) vanityCounter.get(mapEntries); |
| assertEquals(2, counter.longValue()); |
| |
| final Resource justVanityPath2 = mock(Resource.class, "justVanityPath2"); |
| when(resourceResolver.getResource("/justVanityPath2")).thenReturn(justVanityPath2); |
| when(justVanityPath2.getPath()).thenReturn("/justVanityPath2"); |
| when(justVanityPath2.getName()).thenReturn("justVanityPath2"); |
| when(justVanityPath2.getValueMap()).thenReturn(buildValueMap("sling:vanityPath", "/target/justVanityPath","sling:vanityOrder", 100)); |
| |
| when(resourceResolver.findResources(anyString(), eq("sql"))).thenAnswer(new Answer<Iterator<Resource>>() { |
| |
| @Override |
| public Iterator<Resource> answer(InvocationOnMock invocation) throws Throwable { |
| if (invocation.getArguments()[0].toString().contains("sling:vanityPath")) { |
| return Collections.singleton(justVanityPath).iterator(); |
| } else { |
| return Collections.<Resource> emptySet().iterator(); |
| } |
| } |
| }); |
| |
| method.invoke(mapEntries, "/target/justVanityPath"); |
| |
| counter = (AtomicLong) vanityCounter.get(mapEntries); |
| assertEquals(4, counter.longValue()); |
| } |
| |
| @Test |
| //SLING-4891 |
| public void test_getVanityPaths_3() throws Exception { |
| |
| final Resource justVanityPath = mock(Resource.class, "justVanityPath"); |
| when(resourceResolver.getResource("/justVanityPath")).thenReturn(justVanityPath); |
| when(justVanityPath.getPath()).thenReturn("/justVanityPath"); |
| when(justVanityPath.getName()).thenReturn("justVanityPath"); |
| when(justVanityPath.getValueMap()).thenReturn(buildValueMap("sling:vanityPath", "/target/justVanityPath")); |
| |
| |
| when(resourceResolver.findResources(anyString(), eq("sql"))).thenAnswer(new Answer<Iterator<Resource>>() { |
| |
| @Override |
| public Iterator<Resource> answer(InvocationOnMock invocation) throws Throwable { |
| if (invocation.getArguments()[0].toString().contains("sling:vanityPath")) { |
| return Collections.singleton(justVanityPath).iterator(); |
| } else { |
| return Collections.<Resource> emptySet().iterator(); |
| } |
| } |
| }); |
| |
| when(this.resourceResolverFactory.getMaxCachedVanityPathEntries()).thenReturn(0L); |
| when(this.resourceResolverFactory.isMaxCachedVanityPathEntriesStartup()).thenReturn(false); |
| |
| Method method = MapEntries.class.getDeclaredMethod("getVanityPaths", String.class); |
| method.setAccessible(true); |
| method.invoke(mapEntries, "/target/justVanityPath"); |
| |
| Field vanityCounter = MapEntries.class.getDeclaredField("vanityCounter"); |
| vanityCounter.setAccessible(true); |
| AtomicLong counter = (AtomicLong) vanityCounter.get(mapEntries); |
| assertEquals(0, counter.longValue()); |
| } |
| |
| @Test |
| //SLING-4891 |
| public void test_getVanityPaths_4() throws Exception { |
| |
| final Resource badVanityPath = mock(Resource.class, "badVanityPath"); |
| when(badVanityPath.getPath()).thenReturn("/badVanityPath"); |
| when(badVanityPath.getName()).thenReturn("badVanityPath"); |
| when(badVanityPath.getValueMap()).thenReturn(buildValueMap("sling:vanityPath", "/content/mypage/en-us-{132")); |
| |
| |
| when(resourceResolver.findResources(anyString(), eq("sql"))).thenAnswer(new Answer<Iterator<Resource>>() { |
| |
| @Override |
| public Iterator<Resource> answer(InvocationOnMock invocation) throws Throwable { |
| if (invocation.getArguments()[0].toString().contains("sling:vanityPath")) { |
| return Collections.singleton(badVanityPath).iterator(); |
| } else { |
| return Collections.<Resource> emptySet().iterator(); |
| } |
| } |
| }); |
| |
| when(this.resourceResolverFactory.getMaxCachedVanityPathEntries()).thenReturn(0L); |
| when(this.resourceResolverFactory.isMaxCachedVanityPathEntriesStartup()).thenReturn(true); |
| |
| Method method = MapEntries.class.getDeclaredMethod("getVanityPaths", String.class); |
| method.setAccessible(true); |
| method.invoke(mapEntries, "/content/mypage/en-us-{132"); |
| |
| Field vanityCounter = MapEntries.class.getDeclaredField("vanityCounter"); |
| vanityCounter.setAccessible(true); |
| AtomicLong counter = (AtomicLong) vanityCounter.get(mapEntries); |
| assertEquals(0, counter.longValue()); |
| } |
| |
| @Test |
| //SLING-4891 |
| public void test_getVanityPaths_5() throws Exception { |
| |
| final Resource justVanityPath = mock(Resource.class, "justVanityPath"); |
| when(resourceResolver.getResource("/justVanityPath")).thenReturn(justVanityPath); |
| when(justVanityPath.getPath()).thenReturn("/justVanityPath"); |
| when(justVanityPath.getName()).thenReturn("justVanityPath"); |
| when(justVanityPath.getValueMap()).thenReturn(buildValueMap("sling:vanityPath", "/target/justVanityPath")); |
| |
| when(resourceResolver.findResources(anyString(), eq("sql"))).thenAnswer(new Answer<Iterator<Resource>>() { |
| |
| @Override |
| public Iterator<Resource> answer(InvocationOnMock invocation) throws Throwable { |
| if (invocation.getArguments()[0].toString().contains("sling:vanityPath")) { |
| return Collections.singleton(justVanityPath).iterator(); |
| } else { |
| return Collections.<Resource> emptySet().iterator(); |
| } |
| } |
| }); |
| |
| when(this.resourceResolverFactory.getMaxCachedVanityPathEntries()).thenReturn(2L); |
| when(this.resourceResolverFactory.isMaxCachedVanityPathEntriesStartup()).thenReturn(false); |
| |
| Method method = MapEntries.class.getDeclaredMethod("getVanityPaths", String.class); |
| method.setAccessible(true); |
| method.invoke(mapEntries, "/target/justVanityPath"); |
| |
| Field vanityCounter = MapEntries.class.getDeclaredField("vanityCounter"); |
| vanityCounter.setAccessible(true); |
| AtomicLong counter = (AtomicLong) vanityCounter.get(mapEntries); |
| assertEquals(2, counter.longValue()); |
| |
| final Resource justVanityPath2 = mock(Resource.class, "justVanityPath2"); |
| when(resourceResolver.getResource("/justVanityPath2")).thenReturn(justVanityPath2); |
| when(justVanityPath2.getPath()).thenReturn("/justVanityPath2"); |
| when(justVanityPath2.getName()).thenReturn("justVanityPath2"); |
| when(justVanityPath2.getValueMap()).thenReturn(buildValueMap("sling:vanityPath", "/target/justVanityPath","sling:vanityOrder", 100)); |
| |
| when(resourceResolver.findResources(anyString(), eq("sql"))).thenAnswer(new Answer<Iterator<Resource>>() { |
| |
| @Override |
| public Iterator<Resource> answer(InvocationOnMock invocation) throws Throwable { |
| if (invocation.getArguments()[0].toString().contains("sling:vanityPath")) { |
| return Collections.singleton(justVanityPath).iterator(); |
| } else { |
| return Collections.<Resource> emptySet().iterator(); |
| } |
| } |
| }); |
| |
| method.invoke(mapEntries, "/target/justVanityPath"); |
| |
| counter = (AtomicLong) vanityCounter.get(mapEntries); |
| assertEquals(2, counter.longValue()); |
| } |
| |
| @Test |
| //SLING-4891 |
| public void test_loadVanityPaths() throws Exception { |
| when(this.resourceResolverFactory.getMaxCachedVanityPathEntries()).thenReturn(2L); |
| |
| final Resource justVanityPath = mock(Resource.class, "justVanityPath"); |
| when(resourceResolver.getResource("/justVanityPath")).thenReturn(justVanityPath); |
| when(justVanityPath.getPath()).thenReturn("/justVanityPath"); |
| when(justVanityPath.getName()).thenReturn("justVanityPath"); |
| when(justVanityPath.getValueMap()).thenReturn(buildValueMap("sling:vanityPath", "/target/justVanityPath")); |
| |
| when(resourceResolver.findResources(anyString(), eq("sql"))).thenAnswer(new Answer<Iterator<Resource>>() { |
| |
| @Override |
| public Iterator<Resource> answer(InvocationOnMock invocation) throws Throwable { |
| if (invocation.getArguments()[0].toString().contains("sling:vanityPath")) { |
| return Collections.singleton(justVanityPath).iterator(); |
| } else { |
| return Collections.<Resource> emptySet().iterator(); |
| } |
| } |
| }); |
| |
| Method method = MapEntries.class.getDeclaredMethod("loadVanityPaths", boolean.class); |
| method.setAccessible(true); |
| method.invoke(mapEntries, false); |
| |
| Field vanityCounter = MapEntries.class.getDeclaredField("vanityCounter"); |
| vanityCounter.setAccessible(true); |
| AtomicLong counter = (AtomicLong) vanityCounter.get(mapEntries); |
| assertEquals(2, counter.longValue()); |
| } |
| |
| @Test |
| //SLING-4891 |
| public void test_loadVanityPaths_1() throws Exception { |
| |
| final Resource justVanityPath = mock(Resource.class, "justVanityPath"); |
| when(resourceResolver.getResource("/justVanityPath")).thenReturn(justVanityPath); |
| when(justVanityPath.getPath()).thenReturn("/justVanityPath"); |
| when(justVanityPath.getName()).thenReturn("justVanityPath"); |
| when(justVanityPath.getValueMap()).thenReturn(buildValueMap("sling:vanityPath", "/target/justVanityPath")); |
| |
| when(resourceResolver.findResources(anyString(), eq("sql"))).thenAnswer(new Answer<Iterator<Resource>>() { |
| |
| @Override |
| public Iterator<Resource> answer(InvocationOnMock invocation) throws Throwable { |
| if (invocation.getArguments()[0].toString().contains("sling:vanityPath")) { |
| return Collections.singleton(justVanityPath).iterator(); |
| } else { |
| return Collections.<Resource> emptySet().iterator(); |
| } |
| } |
| }); |
| |
| Method method = MapEntries.class.getDeclaredMethod("loadVanityPaths", boolean.class); |
| method.setAccessible(true); |
| method.invoke(mapEntries, false); |
| |
| Field vanityCounter = MapEntries.class.getDeclaredField("vanityCounter"); |
| vanityCounter.setAccessible(true); |
| AtomicLong counter = (AtomicLong) vanityCounter.get(mapEntries); |
| assertEquals(2, counter.longValue()); |
| } |
| |
| @Test |
| //SLING-4891 |
| public void test_getMapEntryList() throws Exception { |
| |
| List<MapEntry> entries = mapEntries.getResolveMaps(); |
| assertEquals(0, entries.size()); |
| |
| |
| final Resource justVanityPath = mock(Resource.class, |
| "justVanityPath"); |
| |
| when(resourceResolver.getResource("/justVanityPath")).thenReturn(justVanityPath); |
| |
| when(justVanityPath.getPath()).thenReturn("/justVanityPath"); |
| |
| when(justVanityPath.getName()).thenReturn("justVanityPath"); |
| |
| when(justVanityPath.getValueMap()).thenReturn(buildValueMap("sling:vanityPath", |
| "/target/justVanityPath")); |
| |
| when(resourceResolver.findResources(anyString(), |
| eq("sql"))).thenAnswer(new Answer<Iterator<Resource>>() { |
| |
| @Override |
| public Iterator<Resource> answer(InvocationOnMock invocation) |
| throws Throwable { |
| if |
| (invocation.getArguments()[0].toString().contains("sling:vanityPath")) { |
| return Collections.singleton(justVanityPath).iterator(); |
| } else { |
| return Collections.<Resource> emptySet().iterator(); |
| } |
| } |
| }); |
| |
| Method method = |
| MapEntries.class.getDeclaredMethod("getMapEntryList",String.class); |
| method.setAccessible(true); |
| method.invoke(mapEntries, "/target/justVanityPath"); |
| |
| entries = mapEntries.getResolveMaps(); |
| assertEquals(2, entries.size()); |
| |
| Field vanityCounter = |
| MapEntries.class.getDeclaredField("vanityCounter"); |
| vanityCounter.setAccessible(true); |
| AtomicLong counter = (AtomicLong) vanityCounter.get(mapEntries); |
| assertEquals(2, counter.longValue()); |
| |
| method.invoke(mapEntries, "/target/justVanityPath"); |
| |
| entries = mapEntries.getResolveMaps(); |
| assertEquals(2, entries.size()); |
| |
| counter = (AtomicLong) vanityCounter.get(mapEntries); |
| assertEquals(2, counter.longValue()); |
| } |
| |
| @Test |
| //SLING-4883 |
| public void test_concutrrent_getResolveMapsIterator() throws Exception { |
| ExecutorService pool = Executors.newFixedThreadPool(10); |
| |
| final Resource justVanityPath = mock(Resource.class, "justVanityPath"); |
| when(resourceResolver.getResource("/justVanityPath")).thenReturn(justVanityPath); |
| when(justVanityPath.getPath()).thenReturn("/justVanityPath"); |
| when(justVanityPath.getName()).thenReturn("justVanityPath"); |
| when(justVanityPath.getValueMap()).thenReturn(buildValueMap("sling:vanityPath", "/target/justVanityPath")); |
| |
| |
| when(resourceResolver.findResources(anyString(), eq("sql"))).thenAnswer(new Answer<Iterator<Resource>>() { |
| |
| @Override |
| public Iterator<Resource> answer(InvocationOnMock invocation) throws Throwable { |
| if (invocation.getArguments()[0].toString().contains("sling:vanityPath")) { |
| return Collections.singleton(justVanityPath).iterator(); |
| } else { |
| return Collections.<Resource> emptySet().iterator(); |
| } |
| } |
| }); |
| |
| |
| when(this.resourceResolverFactory.getMaxCachedVanityPathEntries()).thenReturn(2L); |
| |
| ArrayList<DataFuture> list = new ArrayList<>(); |
| for (int i =0;i<10;i++) { |
| list.add(createDataFuture(pool, mapEntries)); |
| |
| } |
| |
| for (DataFuture df : list) { |
| df.future.get(); |
| } |
| |
| } |
| |
| // tests SLING-6542 |
| @Test |
| public void sessionConcurrency() throws Exception { |
| final Method addResource = MapEntries.class.getDeclaredMethod("addResource", String.class, AtomicBoolean.class); |
| addResource.setAccessible(true); |
| final Method updateResource = MapEntries.class.getDeclaredMethod("updateResource", String.class, AtomicBoolean.class); |
| updateResource.setAccessible(true); |
| final Method handleConfigurationUpdate = MapEntries.class.getDeclaredMethod("handleConfigurationUpdate", |
| String.class, AtomicBoolean.class, AtomicBoolean.class, boolean.class); |
| handleConfigurationUpdate.setAccessible(true); |
| |
| final Semaphore sessionLock = new Semaphore(1); |
| // simulate somewhat slow (1ms) session operations that use locking |
| // to determine that they are using the session exclusively. |
| // if that lock mechanism detects concurrent access we fail |
| Mockito.doAnswer(new Answer<Void>() { |
| |
| @Override |
| public Void answer(InvocationOnMock invocation) throws Throwable { |
| simulateSomewhatSlowSessionOperation(sessionLock); |
| return null; |
| } |
| |
| }).when(resourceResolver).refresh(); |
| Mockito.doAnswer(new Answer<Resource>() { |
| |
| @Override |
| public Resource answer(InvocationOnMock invocation) throws Throwable { |
| simulateSomewhatSlowSessionOperation(sessionLock); |
| return null; |
| } |
| |
| }).when(resourceResolver).getResource(any(String.class)); |
| |
| when(resourceResolverFactory.isMapConfiguration(any(String.class))).thenReturn(true); |
| |
| final AtomicInteger failureCnt = new AtomicInteger(0); |
| final List<Exception> exceptions = new LinkedList<>(); |
| final Semaphore done = new Semaphore(0); |
| final int NUM_THREADS = 30; |
| final Random random = new Random(12321); |
| for(int i=0; i<NUM_THREADS; i++) { |
| final int randomWait = random.nextInt(10); |
| Runnable r = new Runnable() { |
| |
| @Override |
| public void run() { |
| try{ |
| Thread.sleep(randomWait); |
| for(int i=0; i<3; i++) { |
| addResource.invoke(mapEntries, "/node", new AtomicBoolean()); |
| updateResource.invoke(mapEntries, "/node", new AtomicBoolean()); |
| handleConfigurationUpdate.invoke(mapEntries, "/node", new AtomicBoolean(), new AtomicBoolean(), false); |
| } |
| } catch(Exception e) { |
| e.printStackTrace(); |
| synchronized(exceptions) { |
| exceptions.add(e); |
| } |
| failureCnt.incrementAndGet(); |
| } finally { |
| done.release(); |
| } |
| } |
| }; |
| Thread th = new Thread(r); |
| th.setDaemon(true); |
| th.start(); |
| } |
| assertTrue("threads did not finish in time", done.tryAcquire(NUM_THREADS, 30, TimeUnit.SECONDS)); |
| if (failureCnt.get() != 0) { |
| synchronized(exceptions) { |
| throw new AssertionError("exceptions encountered (" + failureCnt.get() + "). First exception: ", exceptions.get(0)); |
| } |
| } |
| } |
| |
| // -------------------------- private methods ---------- |
| private DataFuture createDataFuture(ExecutorService pool, final MapEntries mapEntries) { |
| |
| Future<Iterator<?>> future = pool.submit(new Callable<Iterator<?>>() { |
| @Override |
| public Iterator<MapEntry> call() throws Exception { |
| return mapEntries.getResolveMapsIterator("http/localhost.8080/target/justVanityPath"); |
| } |
| }); |
| return new DataFuture(future); |
| } |
| |
| private void simulateSomewhatSlowSessionOperation(final Semaphore sessionLock) throws InterruptedException { |
| if (!sessionLock.tryAcquire()) { |
| fail("concurrent session access detected"); |
| } |
| try{ |
| Thread.sleep(1); |
| } finally { |
| sessionLock.release(); |
| } |
| } |
| |
| // -------------------------- inner classes ------------ |
| |
| private static class DataFuture { |
| public Future<Iterator<?>> future; |
| |
| public DataFuture(Future<Iterator<?>> future) { |
| super(); |
| this.future = future; |
| } |
| } |
| |
| } |