From c7ae614824b4c158b9998575294d94fe9a746c41 Mon Sep 17 00:00:00 2001 From: Lukasz Lenart Date: Sun, 24 Mar 2024 11:29:12 +0100 Subject: [PATCH] WW-5402 Auto loads Tiles definitions from classpath --- plugins/tiles/pom.xml | 3 - .../tiles/StrutsTilesContainerFactory.java | 28 +++- .../StrutsTilesContainerFactoryTest.java | 128 ++++++++++++++++++ 3 files changed, 149 insertions(+), 10 deletions(-) create mode 100644 plugins/tiles/src/test/java/org/apache/struts2/tiles/StrutsTilesContainerFactoryTest.java diff --git a/plugins/tiles/pom.xml b/plugins/tiles/pom.xml index 440f6ee797..1a6caf2c12 100644 --- a/plugins/tiles/pom.xml +++ b/plugins/tiles/pom.xml @@ -35,9 +35,6 @@ build-autotags - - true - diff --git a/plugins/tiles/src/main/java/org/apache/struts2/tiles/StrutsTilesContainerFactory.java b/plugins/tiles/src/main/java/org/apache/struts2/tiles/StrutsTilesContainerFactory.java index 205476467d..ed03f8268f 100644 --- a/plugins/tiles/src/main/java/org/apache/struts2/tiles/StrutsTilesContainerFactory.java +++ b/plugins/tiles/src/main/java/org/apache/struts2/tiles/StrutsTilesContainerFactory.java @@ -25,11 +25,6 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.apache.tiles.api.TilesContainer; -import org.apache.tiles.request.ApplicationContext; -import org.apache.tiles.request.ApplicationResource; -import org.apache.tiles.request.Request; -import org.apache.tiles.request.render.BasicRendererFactory; -import org.apache.tiles.request.render.ChainedDelegateRenderer; import org.apache.tiles.core.definition.DefinitionsFactory; import org.apache.tiles.core.definition.pattern.DefinitionPatternMatcherFactory; import org.apache.tiles.core.definition.pattern.PatternDefinitionResolver; @@ -57,6 +52,11 @@ import org.apache.tiles.ognl.ScopePropertyAccessor; import org.apache.tiles.ognl.TilesApplicationContextNestedObjectExtractor; import org.apache.tiles.ognl.TilesContextPropertyAccessorDelegateFactory; +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.ApplicationResource; +import org.apache.tiles.request.Request; +import org.apache.tiles.request.render.BasicRendererFactory; +import org.apache.tiles.request.render.ChainedDelegateRenderer; import org.apache.tiles.request.render.Renderer; import javax.el.ArrayELResolver; @@ -68,7 +68,10 @@ import javax.el.ResourceBundleELResolver; import javax.servlet.jsp.JspFactory; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; import java.util.List; import java.util.Locale; import java.util.Map; @@ -100,10 +103,21 @@ public class StrutsTilesContainerFactory extends BasicTilesContainerFactory { public static final String PATTERN_WILDCARD = "WILDCARD"; public static final String PATTERN_REGEXP = "REGEXP"; + /** + * Default pattern to be used to collect Tiles definitions if user didn't configure any + * + * @deprecated since Struts 6.4.0, use {@link #TILES_DEFAULT_PATTERNS} instead + */ + @Deprecated + public static final String TILES_DEFAULT_PATTERN = "/WEB-INF/**/tiles*.xml,classpath*:META-INF/**/tiles*.xml"; + /** * Default pattern to be used to collect Tiles definitions if user didn't configure any */ - public static final String TILES_DEFAULT_PATTERN = "tiles*.xml"; + public static final Set TILES_DEFAULT_PATTERNS = Collections.unmodifiableSet(new HashSet<>(Arrays.asList( + "/WEB-INF/**/tiles*.xml", + "classpath*:META-INF/**/tiles*.xml" + ))); /** * Supported expression languages @@ -213,7 +227,7 @@ protected Set getTilesDefinitions(Map params) { if (params.containsKey(DefinitionsFactory.DEFINITIONS_CONFIG)) { return TextParseUtil.commaDelimitedStringToSet(params.get(DefinitionsFactory.DEFINITIONS_CONFIG)); } - return TextParseUtil.commaDelimitedStringToSet(TILES_DEFAULT_PATTERN); + return TILES_DEFAULT_PATTERNS; } protected ELAttributeEvaluator createELEvaluator(ApplicationContext applicationContext) { diff --git a/plugins/tiles/src/test/java/org/apache/struts2/tiles/StrutsTilesContainerFactoryTest.java b/plugins/tiles/src/test/java/org/apache/struts2/tiles/StrutsTilesContainerFactoryTest.java new file mode 100644 index 0000000000..122bfe51d1 --- /dev/null +++ b/plugins/tiles/src/test/java/org/apache/struts2/tiles/StrutsTilesContainerFactoryTest.java @@ -0,0 +1,128 @@ +/* + * 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.struts2.tiles; + +import org.apache.tiles.api.TilesContainer; +import org.apache.tiles.core.evaluator.AttributeEvaluatorFactory; +import org.apache.tiles.core.evaluator.impl.DirectAttributeEvaluator; +import org.apache.tiles.core.locale.LocaleResolver; +import org.apache.tiles.core.prepare.factory.BasicPreparerFactory; +import org.apache.tiles.core.prepare.factory.PreparerFactory; +import org.apache.tiles.ognl.OGNLAttributeEvaluator; +import org.apache.tiles.request.ApplicationContext; +import org.apache.tiles.request.ApplicationResource; +import org.apache.tiles.request.locale.URLApplicationResource; +import org.apache.tiles.request.render.BasicRendererFactory; +import org.apache.tiles.request.render.ChainedDelegateRenderer; +import org.apache.tiles.request.render.Renderer; +import org.junit.Before; +import org.junit.Test; + +import javax.servlet.ServletContext; +import javax.servlet.jsp.JspFactory; +import java.util.Collections; +import java.util.List; +import java.util.Objects; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +public class StrutsTilesContainerFactoryTest { + + private StrutsTilesContainerFactory factory; + private ApplicationContext applicationContext; + + @Before + public void setUp() throws Exception { + applicationContext = mock(ApplicationContext.class); + factory = new StrutsTilesContainerFactory(); + } + + @Test + public void getSources() { + ApplicationResource pathResource = new URLApplicationResource( + "/org/apache/tiles/core/config/tiles-defs.xml", + Objects.requireNonNull(getClass().getResource("/org/apache/tiles/core/config/tiles-defs.xml")) + ); + ApplicationResource classpathResource = new URLApplicationResource( + "/org/apache/tiles/core/config/defs1.xml", + Objects.requireNonNull(getClass().getResource("/org/apache/tiles/core/config/defs1.xml")) + ); + when(applicationContext.getInitParams()).thenReturn(Collections.emptyMap()); + when(applicationContext.getResources("/WEB-INF/**/tiles*.xml")).thenReturn(Collections.singleton(pathResource)); + when(applicationContext.getResources("classpath*:META-INF/**/tiles*.xml")).thenReturn(Collections.singleton(classpathResource)); + + List resources = factory.getSources(applicationContext); + assertEquals("The urls list is not two-sized", 2, resources.size()); + assertEquals("The URL is not correct", pathResource, resources.get(0)); + assertEquals("The URL is not correct", classpathResource, resources.get(1)); + } + + @Test + public void createAttributeEvaluatorFactory() { + LocaleResolver resolver = factory.createLocaleResolver(applicationContext); + // explicitly disables support for EL + JspFactory.setDefaultFactory(null); + + AttributeEvaluatorFactory attributeEvaluatorFactory = factory.createAttributeEvaluatorFactory(applicationContext, resolver); + assertTrue("The class of the evaluator is not correct", + attributeEvaluatorFactory.getAttributeEvaluator((String) null) instanceof DirectAttributeEvaluator); + assertTrue("The class of the evaluator is not correct", + attributeEvaluatorFactory.getAttributeEvaluator("S2") instanceof StrutsAttributeEvaluator); + assertTrue("The class of the evaluator is not correct", + attributeEvaluatorFactory.getAttributeEvaluator("OGNL") instanceof OGNLAttributeEvaluator); + assertTrue("The class of the evaluator is not correct", + attributeEvaluatorFactory.getAttributeEvaluator("I18N") instanceof I18NAttributeEvaluator); + assertTrue("The class of the evaluator is not correct", + attributeEvaluatorFactory.getAttributeEvaluator("EL") instanceof DirectAttributeEvaluator); + } + + @Test + public void createPreparerFactory() { + PreparerFactory preparerFactory = factory.createPreparerFactory(applicationContext); + assertTrue("The class of the preparer factory is not correct", preparerFactory instanceof BasicPreparerFactory); + } + + @Test + public void createDefaultAttributeRenderer() { + TilesContainer container = mock(TilesContainer.class); + AttributeEvaluatorFactory attributeEvaluatorFactory = mock(AttributeEvaluatorFactory.class); + BasicRendererFactory rendererFactory = mock(BasicRendererFactory.class); + Renderer stringRenderer = mock(Renderer.class); + Renderer templateRenderer = mock(Renderer.class); + Renderer definitionRenderer = mock(Renderer.class); + + when(rendererFactory.getRenderer("string")).thenReturn(stringRenderer); + when(rendererFactory.getRenderer("template")).thenReturn(templateRenderer); + when(rendererFactory.getRenderer("definition")).thenReturn(definitionRenderer); + when(rendererFactory.getRenderer("freemarker")).thenReturn(definitionRenderer); + + Renderer renderer = factory.createDefaultAttributeRenderer(rendererFactory, applicationContext, container, attributeEvaluatorFactory); + + assertTrue("The default renderer class is not correct", renderer instanceof ChainedDelegateRenderer); + verify(rendererFactory).getRenderer("string"); + verify(rendererFactory).getRenderer("template"); + verify(rendererFactory).getRenderer("definition"); + verify(rendererFactory).getRenderer("freemarker"); + } + +} \ No newline at end of file