From 15e6fcaa8121b1f3ff220393e82bd4753cb9f379 Mon Sep 17 00:00:00 2001 From: Bertrand Delacretaz Date: Fri, 4 Apr 2025 18:02:03 +0200 Subject: [PATCH 1/6] SLING-12739 - initial implementation with incomplete tests --- .../internal/SlingServletResolver.java | 22 ++++- .../it/FilteredServletSelectionIT.java | 81 +++++++++++++++++++ 2 files changed, 102 insertions(+), 1 deletion(-) create mode 100644 src/test/java/org/apache/sling/servlets/resolver/it/FilteredServletSelectionIT.java diff --git a/src/main/java/org/apache/sling/servlets/resolver/internal/SlingServletResolver.java b/src/main/java/org/apache/sling/servlets/resolver/internal/SlingServletResolver.java index 2eecb28..770608f 100644 --- a/src/main/java/org/apache/sling/servlets/resolver/internal/SlingServletResolver.java +++ b/src/main/java/org/apache/sling/servlets/resolver/internal/SlingServletResolver.java @@ -28,6 +28,7 @@ import java.util.Collection; import java.util.Collections; import java.util.concurrent.atomic.AtomicReference; +import java.util.function.Predicate; import javax.servlet.Servlet; import javax.servlet.ServletContext; @@ -70,6 +71,8 @@ import org.osgi.service.component.annotations.Deactivate; import org.osgi.service.component.annotations.Modified; import org.osgi.service.component.annotations.Reference; +import org.osgi.service.component.annotations.ReferenceCardinality; +import org.osgi.service.component.annotations.ReferencePolicy; import org.osgi.service.metatype.annotations.Designate; import org.osgi.util.tracker.ServiceTracker; import org.slf4j.Logger; @@ -129,6 +132,13 @@ public class SlingServletResolver private final ThreadLocal perThreadScriptResolver = new ThreadLocal<>(); + @Reference( + target = "(name=sling.servlet.resolver.resource.hiding)", + policy = ReferencePolicy.DYNAMIC, + cardinality = ReferenceCardinality.OPTIONAL + ) + private volatile Predicate resourceHidingPredicate; + /** * The allowed execution paths. */ @@ -442,6 +452,15 @@ private Resource getErrorResource(final SlingHttpServletRequest request) { return res; } + /** @return true if the given Resource is hidden by our resourceHidingPredicate */ + private boolean isHidden(Resource r) { + final boolean result = r != null && resourceHidingPredicate != null && resourceHidingPredicate.test(r.getPath()); + if(result && LOGGER.isDebugEnabled()) { + LOGGER.debug("Resource hidden by resource hiding predicate: {}", r.getPath()); + } + return result; + } + /** * Resolve an appropriate servlet for a given request and resource type * using the provided ResourceResolver @@ -468,7 +487,7 @@ private Servlet resolveServletInternal(final SlingHttpServletRequest request, final String scriptPath = ResourceUtil.normalize(scriptNameOrResourceType); if (scriptPath != null && isPathAllowed(scriptPath, this.executionPaths.get()) ) { final Resource res = AbstractResourceCollector.getResourceOrNull(resolver,scriptPath,useResourceCaching); - servlet = this.getServlet(res); + servlet = isHidden(res) ? null : this.getServlet(res); if (servlet != null && !pathBasedServletAcceptor.accept(request, servlet)) { if(LOGGER.isDebugEnabled()) { LOGGER.debug("Servlet {} rejected by {} returning FORBIDDEN status", RequestUtil.getServletName(servlet), @@ -536,6 +555,7 @@ private Servlet getServletInternal(final AbstractResourceCollector locationUtil, } final Collection candidates = locationUtil.getServlets(resolver, localCache.getScriptEngineExtensions()); + candidates.removeIf(r -> isHidden(r)); if (LOGGER.isDebugEnabled()) { if (candidates.isEmpty()) { diff --git a/src/test/java/org/apache/sling/servlets/resolver/it/FilteredServletSelectionIT.java b/src/test/java/org/apache/sling/servlets/resolver/it/FilteredServletSelectionIT.java new file mode 100644 index 0000000..1cca939 --- /dev/null +++ b/src/test/java/org/apache/sling/servlets/resolver/it/FilteredServletSelectionIT.java @@ -0,0 +1,81 @@ +/* + * 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.servlets.resolver.it; + +import static org.junit.Assert.assertEquals; + +import java.util.Hashtable; +import java.util.UUID; +import java.util.function.Predicate; + +import javax.servlet.http.HttpServletResponse; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.ops4j.pax.exam.junit.PaxExam; +import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy; +import org.ops4j.pax.exam.spi.reactors.PerClass; + +// TODO test with absolute script/servlet paths +// TODO test that scripts are also covered by the exclusion + +@RunWith(PaxExam.class) +@ExamReactorStrategy(PerClass.class) +public class FilteredServletSelectionIT extends ServletResolverTestSupport { + + private int hiddenResourceCount = 0; + private final static String isHidden = "IS_HIDDEN_" + UUID.randomUUID(); + private final static String notHidden = "NOT_HIDDEN_" + UUID.randomUUID(); + + @Before + public void setupTestServlets() throws Exception { + // Register two servlets differing only in extensions, + // to verify that one of them is hidden + final TestServlet ts = new TestServlet("HidingTestServlet") + .with(P_RESOURCE_TYPES, RT_DEFAULT) + .with(P_METHODS, M_GET); + + ts.with(P_EXTENSIONS, notHidden).register(bundleContext); + ts.with(P_EXTENSIONS, isHidden).register(bundleContext); + + // Register a predicate that hides one of the servlet resources + final Predicate hidingPredicate = new Predicate() { + @Override + public boolean test(String t) { + if(t.contains(isHidden)) { + hiddenResourceCount++; + return true; + } + return false; + } + }; + final Hashtable props = new Hashtable<>(); + props.put("name","sling.servlet.resolver.resource.hiding"); + bundleContext.registerService(Predicate.class.getName(), hidingPredicate, props); + } + + @Test + public void testFilteredServlet() throws Exception { + assertTestServlet("/." + notHidden, "HidingTestServlet"); + assertEquals(0, hiddenResourceCount); + assertTestServlet("/." + isHidden, HttpServletResponse.SC_NOT_FOUND); + assertEquals(1, hiddenResourceCount); + } +} \ No newline at end of file From 602d094ab063c3bcfb7453196dd73dc234e9aca5 Mon Sep 17 00:00:00 2001 From: Bertrand Delacretaz Date: Fri, 11 Apr 2025 11:50:36 +0200 Subject: [PATCH 2/6] SLING-12739 - unit testing --- .../resourcehiding/ServletHidingTest.java | 125 ++++++++++++++++++ 1 file changed, 125 insertions(+) create mode 100644 src/test/java/org/apache/sling/servlets/resolver/internal/resourcehiding/ServletHidingTest.java diff --git a/src/test/java/org/apache/sling/servlets/resolver/internal/resourcehiding/ServletHidingTest.java b/src/test/java/org/apache/sling/servlets/resolver/internal/resourcehiding/ServletHidingTest.java new file mode 100644 index 0000000..55577da --- /dev/null +++ b/src/test/java/org/apache/sling/servlets/resolver/internal/resourcehiding/ServletHidingTest.java @@ -0,0 +1,125 @@ +/* + * 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.servlets.resolver.internal.resourcehiding; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.fail; + +import java.lang.reflect.Field; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.function.Predicate; + +import javax.servlet.Servlet; + +import org.apache.sling.api.resource.PersistenceException; +import org.apache.sling.api.resource.ResourceUtil; +import org.apache.sling.api.servlets.SlingSafeMethodsServlet; +import org.apache.sling.commons.testing.sling.MockSlingHttpServletRequest; +import org.apache.sling.servlets.resolver.internal.SlingServletResolverTestBase; +import org.apache.sling.servlets.resolver.internal.helper.HelperTestBase; +import org.apache.sling.servlets.resolver.internal.resource.MockServletResource; +import org.junit.Test; +import org.osgi.framework.Bundle; + +public class ServletHidingTest extends SlingServletResolverTestBase { + + private static final String TEST_ID = UUID.randomUUID().toString(); + + protected static class TestServlet extends SlingSafeMethodsServlet { + private final String id; + + public TestServlet(String id) { + this.id = id; + } + + public String toString() { + return id; + } + } + + private void setServletHidingFilter(Predicate predicate) throws Exception { + final Field predicateField = servletResolver.getClass().getDeclaredField("resourceHidingPredicate"); + predicateField.setAccessible(true); + predicateField.set(servletResolver, predicate); + } + + private void registerServlet(String id, String resourceType) { + final String path = "/" + resourceType + "/" + ResourceUtil.getName(resourceType) + ".servlet"; + Map props = new HashMap<>(); + props.put(MockServletResource.PROP_SERVLET, new TestServlet(id)); + HelperTestBase.addOrReplaceResource(mockResourceResolver, path, props); + try { + mockResourceResolver.commit(); + } catch (PersistenceException e) { + fail(e.toString()); + } + } + + private Servlet resolveServlet() { + MockSlingHttpServletRequest req = new MockSlingHttpServletRequest( + MockSlingHttpServletRequest.RESOURCE_TYPE, null, "html", null, null); + req.setResourceResolver(mockResourceResolver); + return servletResolver.resolveServlet(req); + } + + @Override + protected void defineTestServlets(Bundle bundle) { + registerServlet(TEST_ID, MockSlingHttpServletRequest.RESOURCE_TYPE); + } + + private void assertResolvesToTestServletId(String info, boolean expectMatch) { + final Servlet s = resolveServlet(); + assertNotNull("Expecting non-null Servlet", s); + if(expectMatch) { + assertEquals("Expecting our test servlet (" + info + ")", TEST_ID, s.toString()); + } else { + assertNotEquals("NOT expecting our test servlet (" + info + ")", TEST_ID, s.toString()); + } + } + + @Test + public void testHideAndSeek() throws Exception { + final AtomicBoolean hide = new AtomicBoolean(); + final Predicate pred = (ignoredPath) -> hide.get(); + + // No filtering + setServletHidingFilter(null); + assertResolvesToTestServletId("before hiding", true); + + // Filter with our predicate + setServletHidingFilter(pred); + hide.set(true); + assertResolvesToTestServletId("hidden by our Predicate", false); + hide.set(false); + assertResolvesToTestServletId("Predicate active but returns false", true); + + // Back to no filtering, (paranoid) check that it's really gone + setServletHidingFilter(null); + hide.set(false); + assertResolvesToTestServletId("No Predicate set, hide=false", true); + hide.set(true); + assertResolvesToTestServletId("No Predicate set, hide=true", true); + } + +} From ee46e02062cbd422d27df51b9c88a446421dfbb3 Mon Sep 17 00:00:00 2001 From: Bertrand Delacretaz Date: Fri, 11 Apr 2025 13:01:06 +0200 Subject: [PATCH 3/6] SLING-12739 add hidden servlet fallback tests --- .../it/FilteredServletSelectionIT.java | 81 ------------------ .../servlets/resolver/it/TestServlet.java | 4 +- .../resourcehiding/BasicResourceHidingIT.java | 49 +++++++++++ .../HiddenServletFallbackIT.java | 47 +++++++++++ .../it/resourcehiding/NoHidingIT.java | 35 ++++++++ .../resourcehiding/ResourceHidingITBase.java | 82 +++++++++++++++++++ 6 files changed, 215 insertions(+), 83 deletions(-) delete mode 100644 src/test/java/org/apache/sling/servlets/resolver/it/FilteredServletSelectionIT.java create mode 100644 src/test/java/org/apache/sling/servlets/resolver/it/resourcehiding/BasicResourceHidingIT.java create mode 100644 src/test/java/org/apache/sling/servlets/resolver/it/resourcehiding/HiddenServletFallbackIT.java create mode 100644 src/test/java/org/apache/sling/servlets/resolver/it/resourcehiding/NoHidingIT.java create mode 100644 src/test/java/org/apache/sling/servlets/resolver/it/resourcehiding/ResourceHidingITBase.java diff --git a/src/test/java/org/apache/sling/servlets/resolver/it/FilteredServletSelectionIT.java b/src/test/java/org/apache/sling/servlets/resolver/it/FilteredServletSelectionIT.java deleted file mode 100644 index 1cca939..0000000 --- a/src/test/java/org/apache/sling/servlets/resolver/it/FilteredServletSelectionIT.java +++ /dev/null @@ -1,81 +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.servlets.resolver.it; - -import static org.junit.Assert.assertEquals; - -import java.util.Hashtable; -import java.util.UUID; -import java.util.function.Predicate; - -import javax.servlet.http.HttpServletResponse; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.ops4j.pax.exam.junit.PaxExam; -import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy; -import org.ops4j.pax.exam.spi.reactors.PerClass; - -// TODO test with absolute script/servlet paths -// TODO test that scripts are also covered by the exclusion - -@RunWith(PaxExam.class) -@ExamReactorStrategy(PerClass.class) -public class FilteredServletSelectionIT extends ServletResolverTestSupport { - - private int hiddenResourceCount = 0; - private final static String isHidden = "IS_HIDDEN_" + UUID.randomUUID(); - private final static String notHidden = "NOT_HIDDEN_" + UUID.randomUUID(); - - @Before - public void setupTestServlets() throws Exception { - // Register two servlets differing only in extensions, - // to verify that one of them is hidden - final TestServlet ts = new TestServlet("HidingTestServlet") - .with(P_RESOURCE_TYPES, RT_DEFAULT) - .with(P_METHODS, M_GET); - - ts.with(P_EXTENSIONS, notHidden).register(bundleContext); - ts.with(P_EXTENSIONS, isHidden).register(bundleContext); - - // Register a predicate that hides one of the servlet resources - final Predicate hidingPredicate = new Predicate() { - @Override - public boolean test(String t) { - if(t.contains(isHidden)) { - hiddenResourceCount++; - return true; - } - return false; - } - }; - final Hashtable props = new Hashtable<>(); - props.put("name","sling.servlet.resolver.resource.hiding"); - bundleContext.registerService(Predicate.class.getName(), hidingPredicate, props); - } - - @Test - public void testFilteredServlet() throws Exception { - assertTestServlet("/." + notHidden, "HidingTestServlet"); - assertEquals(0, hiddenResourceCount); - assertTestServlet("/." + isHidden, HttpServletResponse.SC_NOT_FOUND); - assertEquals(1, hiddenResourceCount); - } -} \ No newline at end of file diff --git a/src/test/java/org/apache/sling/servlets/resolver/it/TestServlet.java b/src/test/java/org/apache/sling/servlets/resolver/it/TestServlet.java index 39e1d08..181307f 100644 --- a/src/test/java/org/apache/sling/servlets/resolver/it/TestServlet.java +++ b/src/test/java/org/apache/sling/servlets/resolver/it/TestServlet.java @@ -56,12 +56,12 @@ public void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOEx doGet(req, resp); } - TestServlet with(String key, Object value) { + public TestServlet with(String key, Object value) { properties.put(key, value); return this; } - void register(BundleContext context) { + public void register(BundleContext context) { context.registerService(Servlet.class.getName(), this, properties); } } \ No newline at end of file diff --git a/src/test/java/org/apache/sling/servlets/resolver/it/resourcehiding/BasicResourceHidingIT.java b/src/test/java/org/apache/sling/servlets/resolver/it/resourcehiding/BasicResourceHidingIT.java new file mode 100644 index 0000000..10afb48 --- /dev/null +++ b/src/test/java/org/apache/sling/servlets/resolver/it/resourcehiding/BasicResourceHidingIT.java @@ -0,0 +1,49 @@ +/* + * 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.servlets.resolver.it.resourcehiding; + +import static org.junit.Assert.assertEquals; + +import javax.servlet.http.HttpServletResponse; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.ops4j.pax.exam.junit.PaxExam; +import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy; +import org.ops4j.pax.exam.spi.reactors.PerClass; + +@RunWith(PaxExam.class) +@ExamReactorStrategy(PerClass.class) +public class BasicResourceHidingIT extends ResourceHidingITBase { + + @Before + public void setupPredicate() { + registerPredicate((path) -> path.contains(EXT_B)); + } + + @Test + public void testOnlyApresent() throws Exception { + assertEquals(0, hiddenResourcesCount); + assertTestServlet("/." + EXT_A, EXT_A); + assertEquals(0, hiddenResourcesCount); + assertTestServlet("/." + EXT_B, HttpServletResponse.SC_NOT_FOUND); + assertEquals(1, hiddenResourcesCount); + } +} \ No newline at end of file diff --git a/src/test/java/org/apache/sling/servlets/resolver/it/resourcehiding/HiddenServletFallbackIT.java b/src/test/java/org/apache/sling/servlets/resolver/it/resourcehiding/HiddenServletFallbackIT.java new file mode 100644 index 0000000..c891e7c --- /dev/null +++ b/src/test/java/org/apache/sling/servlets/resolver/it/resourcehiding/HiddenServletFallbackIT.java @@ -0,0 +1,47 @@ +/* + * 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.servlets.resolver.it.resourcehiding; + +import static org.junit.Assert.assertEquals; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.ops4j.pax.exam.junit.PaxExam; +import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy; +import org.ops4j.pax.exam.spi.reactors.PerClass; + +@RunWith(PaxExam.class) +@ExamReactorStrategy(PerClass.class) +public class HiddenServletFallbackIT extends ResourceHidingITBase { + + @Before + public void setupPredicate() { + registerPredicate((path) -> path.contains(SEL_A)); + } + + @Test + public void testFallbackToExtA() throws Exception { + assertEquals(0, hiddenResourcesCount); + assertTestServlet("/." + SEL_A + "." + EXT_A, EXT_A); + assertEquals(1, hiddenResourcesCount); + assertTestServlet("/." + EXT_A, EXT_A); + assertEquals(1, hiddenResourcesCount); + } +} \ No newline at end of file diff --git a/src/test/java/org/apache/sling/servlets/resolver/it/resourcehiding/NoHidingIT.java b/src/test/java/org/apache/sling/servlets/resolver/it/resourcehiding/NoHidingIT.java new file mode 100644 index 0000000..69bdf05 --- /dev/null +++ b/src/test/java/org/apache/sling/servlets/resolver/it/resourcehiding/NoHidingIT.java @@ -0,0 +1,35 @@ +package org.apache.sling.servlets.resolver.it.resourcehiding; + +import static org.junit.Assert.assertEquals; + +import org.junit.After; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.ops4j.pax.exam.junit.PaxExam; +import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy; +import org.ops4j.pax.exam.spi.reactors.PerClass; + +@RunWith(PaxExam.class) +@ExamReactorStrategy(PerClass.class) +public class NoHidingIT extends ResourceHidingITBase { + + @After + public void checkNothingHidden() { + assertEquals(0, hiddenResourcesCount); + } + + @Test + public void testExtApresent() throws Exception { + assertTestServlet("/." + EXT_A, EXT_A); + } + + @Test + public void testExtBpresent() throws Exception { + assertTestServlet("/." + EXT_B, EXT_B); + } + + @Test + public void testSelApresent() throws Exception { + assertTestServlet("/." + SEL_A + "." + EXT_A, SEL_A); + } +} diff --git a/src/test/java/org/apache/sling/servlets/resolver/it/resourcehiding/ResourceHidingITBase.java b/src/test/java/org/apache/sling/servlets/resolver/it/resourcehiding/ResourceHidingITBase.java new file mode 100644 index 0000000..86cd3bb --- /dev/null +++ b/src/test/java/org/apache/sling/servlets/resolver/it/resourcehiding/ResourceHidingITBase.java @@ -0,0 +1,82 @@ +/* + * 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.servlets.resolver.it.resourcehiding; + +import java.util.Hashtable; +import java.util.UUID; +import java.util.function.Predicate; + +import org.apache.sling.servlets.resolver.it.ServletResolverTestSupport; +import org.apache.sling.servlets.resolver.it.TestServlet; +import org.junit.Before; + +/** Base for all our hiding tests, so that they all use the same set of servlets */ +public class ResourceHidingITBase extends ServletResolverTestSupport { + + protected final static String EXT_A = "EXT_A" + UUID.randomUUID(); + protected final static String EXT_B = "EXT_B" + UUID.randomUUID(); + protected final static String SEL_A = "SEL_A" + UUID.randomUUID(); + protected int hiddenResourcesCount = 0; + + @Before + public void reset() { + hiddenResourcesCount = 0; + } + + @Before + public void setupTestServletsAndResourceHiding() throws Exception { + // Register two servlets differing only in extensions + new TestServlet(EXT_A) + .with(P_RESOURCE_TYPES, RT_DEFAULT) + .with(P_METHODS, M_GET) + .with(P_EXTENSIONS, EXT_A) + .register(bundleContext); + + new TestServlet(EXT_B) + .with(P_RESOURCE_TYPES, RT_DEFAULT) + .with(P_METHODS, M_GET) + .with(P_EXTENSIONS, EXT_B) + .register(bundleContext); + + // And one more specific servlet, that will fall back + // to EXT_A when hidden + new TestServlet(SEL_A) + .with(P_RESOURCE_TYPES, RT_DEFAULT) + .with(P_METHODS, M_GET) + .with(P_EXTENSIONS, EXT_A) + .with(P_SELECTORS, SEL_A) + .register(bundleContext); + } + + protected void registerPredicate(Predicate p) { + final Predicate wrappedPredicate = new Predicate() { + @Override + public boolean test(String path) { + final boolean result = p.test(path); + if(result) { + hiddenResourcesCount++; + } + return result; + } + }; + final Hashtable props = new Hashtable<>(); + props.put("name","sling.servlet.resolver.resource.hiding"); + bundleContext.registerService(Predicate.class.getName(), wrappedPredicate, props); + } +} \ No newline at end of file From 9a905702ad48dc79edd024575e416ad4d6c8375d Mon Sep 17 00:00:00 2001 From: Bertrand Delacretaz Date: Fri, 11 Apr 2025 16:47:31 +0200 Subject: [PATCH 4/6] SLING-12739 - add missing license --- .../resolver/it/resourcehiding/NoHidingIT.java | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/test/java/org/apache/sling/servlets/resolver/it/resourcehiding/NoHidingIT.java b/src/test/java/org/apache/sling/servlets/resolver/it/resourcehiding/NoHidingIT.java index 69bdf05..4fae143 100644 --- a/src/test/java/org/apache/sling/servlets/resolver/it/resourcehiding/NoHidingIT.java +++ b/src/test/java/org/apache/sling/servlets/resolver/it/resourcehiding/NoHidingIT.java @@ -1,3 +1,21 @@ +/* + * 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.servlets.resolver.it.resourcehiding; import static org.junit.Assert.assertEquals; From 2ebbb8e1ff23fecabe5b5b0100ac3f7be196dfb1 Mon Sep 17 00:00:00 2001 From: Bertrand Delacretaz Date: Fri, 11 Apr 2025 16:51:00 +0200 Subject: [PATCH 5/6] SLING-12739 - setup for external, independent tests --- pom.xml | 35 ++++++++ src/ext-it/.gitignore | 1 + src/ext-it/pom.xml | 87 +++++++++++++++++++ .../resolver/external/it/TestSetupTest.java | 40 +++++++++ 4 files changed, 163 insertions(+) create mode 100644 src/ext-it/.gitignore create mode 100644 src/ext-it/pom.xml create mode 100644 src/ext-it/src/test/java/org/apache/sling/servlets/resolver/external/it/TestSetupTest.java diff --git a/pom.xml b/pom.xml index 85c3d33..f7f32b3 100644 --- a/pom.xml +++ b/pom.xml @@ -129,6 +129,41 @@ + + org.codehaus.mojo + exec-maven-plugin + 3.1.0 + + + external-IT + integration-test + + exec + + + mvn + + clean + verify + -f + ${project.basedir}/src/ext-it/pom.xml + -D + + bundle.filename=${basedir}/target/${project.build.finalName}.jar + + + + + + + org.apache.rat + apache-rat-plugin + + + src/ext-it/target/** + + + diff --git a/src/ext-it/.gitignore b/src/ext-it/.gitignore new file mode 100644 index 0000000..2f7896d --- /dev/null +++ b/src/ext-it/.gitignore @@ -0,0 +1 @@ +target/ diff --git a/src/ext-it/pom.xml b/src/ext-it/pom.xml new file mode 100644 index 0000000..d439ced --- /dev/null +++ b/src/ext-it/pom.xml @@ -0,0 +1,87 @@ + + + + + 4.0.0 + + org.apache.sling + sling + 49 + + + + org.apache.sling.servlets.resolver.external.it + 0.0.1 + jar + + Apache Sling Servlets Resolver External Integration Tests + + Additional external integrations tests for the Servlets Resolver + + + + 4.13.3 + + + + + + org.apache.maven.plugins + maven-failsafe-plugin + + + integration-test + integration-test + + integration-test + + + + verify + integration-test + + verify + + + + + true + + + bundle.filename + MUST_BE_SET_BY_EXEC_PLUGIN + + + + + + + + + + junit + junit + test + + + + \ No newline at end of file diff --git a/src/ext-it/src/test/java/org/apache/sling/servlets/resolver/external/it/TestSetupTest.java b/src/ext-it/src/test/java/org/apache/sling/servlets/resolver/external/it/TestSetupTest.java new file mode 100644 index 0000000..ee698c2 --- /dev/null +++ b/src/ext-it/src/test/java/org/apache/sling/servlets/resolver/external/it/TestSetupTest.java @@ -0,0 +1,40 @@ +/* + * 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.servlets.resolver.external.it; + +import static org.junit.Assert.assertTrue; + +import java.util.regex.Pattern; + +import org.junit.Test; + +/** The idea is to run tests here which are independent from the existing + * test setup of the resourceresolver module. More recent dependencies, + * latest version of the pax exam tools, etc, while making as few changes + * as possible to the original module. + */ +public class TestSetupTest { + @Test + public void testTheTestSetup() { + // We'll need the filename of the bundle to test + final String filename = System.getProperty("bundle.filename"); + final Pattern regexp = Pattern.compile(".*org.apache.sling.servlets.resolver.*jar"); + assertTrue("Expecting " + filename + " to match " + regexp, regexp.matcher(filename).matches()); + } +} \ No newline at end of file From d559fc0b4e0edb1b5a65c34da3651afc01f3f567 Mon Sep 17 00:00:00 2001 From: Bertrand Delacretaz Date: Wed, 16 Apr 2025 11:16:26 +0200 Subject: [PATCH 6/6] SLING-12739 - remove ext-it tests --- pom.xml | 35 -------- src/ext-it/.gitignore | 1 - src/ext-it/pom.xml | 87 ------------------- .../resolver/external/it/TestSetupTest.java | 40 --------- 4 files changed, 163 deletions(-) delete mode 100644 src/ext-it/.gitignore delete mode 100644 src/ext-it/pom.xml delete mode 100644 src/ext-it/src/test/java/org/apache/sling/servlets/resolver/external/it/TestSetupTest.java diff --git a/pom.xml b/pom.xml index f7f32b3..85c3d33 100644 --- a/pom.xml +++ b/pom.xml @@ -129,41 +129,6 @@ - - org.codehaus.mojo - exec-maven-plugin - 3.1.0 - - - external-IT - integration-test - - exec - - - mvn - - clean - verify - -f - ${project.basedir}/src/ext-it/pom.xml - -D - - bundle.filename=${basedir}/target/${project.build.finalName}.jar - - - - - - - org.apache.rat - apache-rat-plugin - - - src/ext-it/target/** - - - diff --git a/src/ext-it/.gitignore b/src/ext-it/.gitignore deleted file mode 100644 index 2f7896d..0000000 --- a/src/ext-it/.gitignore +++ /dev/null @@ -1 +0,0 @@ -target/ diff --git a/src/ext-it/pom.xml b/src/ext-it/pom.xml deleted file mode 100644 index d439ced..0000000 --- a/src/ext-it/pom.xml +++ /dev/null @@ -1,87 +0,0 @@ - - - - - 4.0.0 - - org.apache.sling - sling - 49 - - - - org.apache.sling.servlets.resolver.external.it - 0.0.1 - jar - - Apache Sling Servlets Resolver External Integration Tests - - Additional external integrations tests for the Servlets Resolver - - - - 4.13.3 - - - - - - org.apache.maven.plugins - maven-failsafe-plugin - - - integration-test - integration-test - - integration-test - - - - verify - integration-test - - verify - - - - - true - - - bundle.filename - MUST_BE_SET_BY_EXEC_PLUGIN - - - - - - - - - - junit - junit - test - - - - \ No newline at end of file diff --git a/src/ext-it/src/test/java/org/apache/sling/servlets/resolver/external/it/TestSetupTest.java b/src/ext-it/src/test/java/org/apache/sling/servlets/resolver/external/it/TestSetupTest.java deleted file mode 100644 index ee698c2..0000000 --- a/src/ext-it/src/test/java/org/apache/sling/servlets/resolver/external/it/TestSetupTest.java +++ /dev/null @@ -1,40 +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.servlets.resolver.external.it; - -import static org.junit.Assert.assertTrue; - -import java.util.regex.Pattern; - -import org.junit.Test; - -/** The idea is to run tests here which are independent from the existing - * test setup of the resourceresolver module. More recent dependencies, - * latest version of the pax exam tools, etc, while making as few changes - * as possible to the original module. - */ -public class TestSetupTest { - @Test - public void testTheTestSetup() { - // We'll need the filename of the bundle to test - final String filename = System.getProperty("bundle.filename"); - final Pattern regexp = Pattern.compile(".*org.apache.sling.servlets.resolver.*jar"); - assertTrue("Expecting " + filename + " to match " + regexp, regexp.matcher(filename).matches()); - } -} \ No newline at end of file