You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@turbine.apache.org by gk...@apache.org on 2021/01/13 16:39:11 UTC

svn commit: r1885436 - in /turbine/core/branches/URLMapperService: ./ conf/ conf/test/ src/java/org/apache/turbine/services/pull/ src/java/org/apache/turbine/services/pull/tools/ src/java/org/apache/turbine/services/urlmapper/ src/java/org/apache/turbi...

Author: gk
Date: Wed Jan 13 16:39:10 2021
New Revision: 1885436

URL: http://svn.apache.org/viewvc?rev=1885436&view=rev
Log:
- added more tests (using junit5), configurations
- added optional support for yaml urlmapper, added maven profile
- added hacky check (to be idempotent) in method mapToURL call check (TurbineURLMapperService)
- update BaseTestCase logging with log4j2
- fixed deprecated getInstance in TurbinePullService.java
- typo fix in MappedTemplateLink.java

Added:
    turbine/core/branches/URLMapperService/conf/turbine-url-mapping.yml
    turbine/core/branches/URLMapperService/src/test/org/apache/turbine/services/urlmapper/TurbineYamlURLMapperServiceTest.java
    turbine/core/branches/URLMapperService/src/test/org/apache/turbine/services/urlmapper/model/YamlURLMappingContainerTest.java
Modified:
    turbine/core/branches/URLMapperService/conf/test/TurbineURLMapperServiceTest.properties
    turbine/core/branches/URLMapperService/conf/test/log4j2.xml
    turbine/core/branches/URLMapperService/conf/turbine-url-mapping.xml
    turbine/core/branches/URLMapperService/pom.xml
    turbine/core/branches/URLMapperService/src/java/org/apache/turbine/services/pull/TurbinePullService.java
    turbine/core/branches/URLMapperService/src/java/org/apache/turbine/services/pull/tools/TemplateLink.java
    turbine/core/branches/URLMapperService/src/java/org/apache/turbine/services/urlmapper/MappedTemplateLink.java
    turbine/core/branches/URLMapperService/src/java/org/apache/turbine/services/urlmapper/TurbineURLMapperService.java
    turbine/core/branches/URLMapperService/src/java/org/apache/turbine/services/urlmapper/model/URLMapEntry.java
    turbine/core/branches/URLMapperService/src/java/org/apache/turbine/services/urlmapper/model/URLMappingContainer.java
    turbine/core/branches/URLMapperService/src/test/org/apache/turbine/services/urlmapper/TurbineURLMapperServiceTest.java
    turbine/core/branches/URLMapperService/src/test/org/apache/turbine/test/BaseTestCase.java

Modified: turbine/core/branches/URLMapperService/conf/test/TurbineURLMapperServiceTest.properties
URL: http://svn.apache.org/viewvc/turbine/core/branches/URLMapperService/conf/test/TurbineURLMapperServiceTest.properties?rev=1885436&r1=1885435&r2=1885436&view=diff
==============================================================================
--- turbine/core/branches/URLMapperService/conf/test/TurbineURLMapperServiceTest.properties (original)
+++ turbine/core/branches/URLMapperService/conf/test/TurbineURLMapperServiceTest.properties Wed Jan 13 16:39:10 2021
@@ -68,8 +68,10 @@ services.AvalonComponentService.classnam
 services.RunDataService.classname=org.apache.turbine.services.rundata.TurbineRunDataService
 services.AssemblerBrokerService.classname=org.apache.turbine.services.assemblerbroker.TurbineAssemblerBrokerService
 services.TemplateService.classname=org.apache.turbine.services.template.TurbineTemplateService
+
 # required by url mapper service
 services.ServletService.classname=org.apache.turbine.services.servlet.TurbineServletService
+
 services.URLMapperService.classname=org.apache.turbine.services.urlmapper.TurbineURLMapperService
 
 # -------------------------------------------------------------------

Modified: turbine/core/branches/URLMapperService/conf/test/log4j2.xml
URL: http://svn.apache.org/viewvc/turbine/core/branches/URLMapperService/conf/test/log4j2.xml?rev=1885436&r1=1885435&r2=1885436&view=diff
==============================================================================
--- turbine/core/branches/URLMapperService/conf/test/log4j2.xml (original)
+++ turbine/core/branches/URLMapperService/conf/test/log4j2.xml Wed Jan 13 16:39:10 2021
@@ -30,15 +30,18 @@
     <Loggers>
          <Logger name="org.apache.turbine" level="debug" additivity="false">
           <AppenderRef ref="logfile"/>
+          <AppenderRef ref="console"/>
         </Logger>
         <Logger name="avalon" level="info" additivity="false">
 	      <AppenderRef ref="logfile"/>
+	      <AppenderRef ref="console"/>
 	    </Logger>
       <Logger name="org.apache.logging.log4j" level="debug" additivity="false">
 	      <AppenderRef ref="logfile"/>
-	    </Logger>
-	    <Root level="error">
-	      <AppenderRef ref="logfile"/>
-	    </Root>
+	  </Logger>
+	  <Root>
+	      <AppenderRef ref="logfile" level="error"/>
+	      <AppenderRef ref="console" level="debug"/>
+	  </Root>
     </Loggers>
 </Configuration>
\ No newline at end of file

Modified: turbine/core/branches/URLMapperService/conf/turbine-url-mapping.xml
URL: http://svn.apache.org/viewvc/turbine/core/branches/URLMapperService/conf/turbine-url-mapping.xml?rev=1885436&r1=1885435&r2=1885436&view=diff
==============================================================================
--- turbine/core/branches/URLMapperService/conf/turbine-url-mapping.xml (original)
+++ turbine/core/branches/URLMapperService/conf/turbine-url-mapping.xml Wed Jan 13 16:39:10 2021
@@ -35,5 +35,33 @@
                 <parameter key="view" />
             </ignore-parameters>
         </map>
+        <map>
+            <pattern>/(?&lt;contextPath&gt;\w+)/register</pattern>
+            <implicit-parameters>
+                <parameter key="media-type">html</parameter>
+                <parameter key="role">anon</parameter>
+                <parameter key="template">Registerone.vm</parameter>
+                <parameter key="js_pane">random-id-123-abc</parameter>
+            </implicit-parameters>
+        </map>
+        <map>
+            <pattern>/(?&lt;contextPath&gt;\w+)/contact</pattern>
+            <implicit-parameters>
+                <parameter key="media-type">html</parameter>
+                <parameter key="role">anon</parameter>
+                <parameter key="page">Contact</parameter>
+                <parameter key="js_pane">another-random-id-876-dfg</parameter>
+            </implicit-parameters>
+            <override-parameters>
+                <parameter key="role">anon</parameter>
+            </override-parameters>
+        </map>
+        <map>
+            <pattern>/(?&lt;contextPath&gt;\w+)/(?&lt;id&gt;\d+)/(?&lt;role&gt;\w+)/(?&lt;language&gt;\w+)</pattern>
+            <implicit-parameters>
+                <parameter key="media-type">html</parameter>
+                <parameter key="template">default.vm</parameter>
+            </implicit-parameters>
+        </map>
     </maps>
 </url-mapping>
\ No newline at end of file

Added: turbine/core/branches/URLMapperService/conf/turbine-url-mapping.yml
URL: http://svn.apache.org/viewvc/turbine/core/branches/URLMapperService/conf/turbine-url-mapping.yml?rev=1885436&view=auto
==============================================================================
--- turbine/core/branches/URLMapperService/conf/turbine-url-mapping.yml (added)
+++ turbine/core/branches/URLMapperService/conf/turbine-url-mapping.yml Wed Jan 13 16:39:10 2021
@@ -0,0 +1,31 @@
+
+name: default
+maps:
+    - pattern: /(?<contextPath>\w+)/book/(?<bookId>\d+)
+      implicit-parameters:
+        template: Book.vm
+        detail: 0      
+    - pattern: /(?<contextPath>\w+)/book/(?<bookId>\d+)/(?<detail>\d)
+      implicit-parameters:
+        template: Book.vm
+      ignore-parameters:
+        view: null
+    - pattern: /(?<contextPath>\w+)/register
+      implicit-parameters:
+        media-type: html
+        role: anon
+        template: Registerone.vm
+        js_pane: random-id-123-abc
+    - pattern: /(?<contextPath>\w+)/contact
+      implicit-parameters:
+        media-type: html
+        page: Contact
+        js_pane: another-random-id-876-dfg       
+        role: anon
+      override-parameters:
+        role: anon
+    - pattern: /(?<contextPath>\w+)/(?<id>\d+)/(?<role>\w+)/(?<language>\w+)
+      implicit-parameters:
+        media-type: html
+        template: default.vm    
+                
\ No newline at end of file

Modified: turbine/core/branches/URLMapperService/pom.xml
URL: http://svn.apache.org/viewvc/turbine/core/branches/URLMapperService/pom.xml?rev=1885436&r1=1885435&r2=1885436&view=diff
==============================================================================
--- turbine/core/branches/URLMapperService/pom.xml (original)
+++ turbine/core/branches/URLMapperService/pom.xml Wed Jan 13 16:39:10 2021
@@ -547,14 +547,18 @@
       <plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-surefire-plugin</artifactId>
-         <version>3.0.0-M5</version>
-        <configuration>
-          <!--default setting is forkCount=1/reuseForks=true -->
-          <reuseForks>false</reuseForks>
-          <forkCount>1</forkCount>
-          <excludedGroups>performance,docker</excludedGroups>
-          <!--useSystemClassLoader>false</useSystemClassLoader-->
-        </configuration>
+        <version>3.0.0-M5</version>
+        <executions>
+                <execution>
+                   <id>default-test</id>
+                    <configuration>
+                      <!--default setting is forkCount=1/reuseForks=true -->
+                      <reuseForks>false</reuseForks>
+                      <forkCount>1</forkCount>
+                      <excludedGroups>performance,docker,yaml</excludedGroups>
+                    </configuration>
+             </execution>
+         </executions>
       </plugin>
       <plugin>
         <groupId>org.apache.torque</groupId>
@@ -888,6 +892,12 @@
       <version>1.9.4</version>
     </dependency>
     <dependency>
+      <groupId>com.fasterxml.jackson.dataformat</groupId>
+      <artifactId>jackson-dataformat-yaml</artifactId>
+      <version>2.11.2</version>
+      <optional>true</optional>
+    </dependency>
+    <dependency>
       <groupId>nl.basjes.parse.useragent</groupId>
       <artifactId>yauaa</artifactId>
       <version>5.19</version>
@@ -1177,7 +1187,7 @@
                    <id>default-test</id>
                   <configuration>
                     <groups>docker</groups>
-                    <excludedGroups>performance</excludedGroups>
+                    <excludedGroups>performance,yaml</excludedGroups>
                   </configuration>
                 </execution>
               </executions>
@@ -1229,6 +1239,37 @@
           </dependency>
       </dependencies>
     </profile>
+    <profile>
+        <id>yaml</id>
+      <activation>
+        <activeByDefault>false</activeByDefault>
+      </activation>
+      <build>
+      <plugins>
+            <plugin>
+              <groupId>org.apache.maven.plugins</groupId>
+              <artifactId>maven-surefire-plugin</artifactId>
+               <version>3.0.0-M5</version>
+              <executions>
+                <execution>
+                   <id>default-test</id>
+                  <configuration><!-- to override excludedGroups set something else (bug?)-->
+                    <groups>yaml</groups>
+                     <excludedGroups>docker,performance</excludedGroups>
+                  </configuration>
+                </execution>
+              </executions>
+            </plugin>
+          </plugins>
+      </build>
+      <dependencies>
+           <dependency>
+               <groupId>com.fasterxml.jackson.dataformat</groupId>
+               <artifactId>jackson-dataformat-yaml</artifactId>
+               <version>2.11.2</version>
+           </dependency>
+       </dependencies>
+    </profile>
   </profiles>
 
   <properties>
@@ -1246,3 +1287,4 @@
   </properties>
 
 </project>
+

Modified: turbine/core/branches/URLMapperService/src/java/org/apache/turbine/services/pull/TurbinePullService.java
URL: http://svn.apache.org/viewvc/turbine/core/branches/URLMapperService/src/java/org/apache/turbine/services/pull/TurbinePullService.java?rev=1885436&r1=1885435&r2=1885436&view=diff
==============================================================================
--- turbine/core/branches/URLMapperService/src/java/org/apache/turbine/services/pull/TurbinePullService.java (original)
+++ turbine/core/branches/URLMapperService/src/java/org/apache/turbine/services/pull/TurbinePullService.java Wed Jan 13 16:39:10 2021
@@ -466,7 +466,7 @@ public class TurbinePullService
         {
             try
             {
-                Object tool = toolData.toolClass.newInstance();
+                Object tool = toolData.toolClass.getDeclaredConstructor().newInstance();
 
                 // global tools are init'd with a null data parameter
                 initTool(tool, null);

Modified: turbine/core/branches/URLMapperService/src/java/org/apache/turbine/services/pull/tools/TemplateLink.java
URL: http://svn.apache.org/viewvc/turbine/core/branches/URLMapperService/src/java/org/apache/turbine/services/pull/tools/TemplateLink.java?rev=1885436&r1=1885435&r2=1885436&view=diff
==============================================================================
--- turbine/core/branches/URLMapperService/src/java/org/apache/turbine/services/pull/tools/TemplateLink.java (original)
+++ turbine/core/branches/URLMapperService/src/java/org/apache/turbine/services/pull/tools/TemplateLink.java Wed Jan 13 16:39:10 2021
@@ -520,7 +520,7 @@ public class TemplateLink
      * tui.getRelativeLink();
      * </pre>
      *
-     * The above call to absoluteLink() would return the String:
+     * The above call to relativeLink() would return the String:
      * <p>
      * /servlets/Turbine/screen/UserScreen/user/jon
      * <p>

Modified: turbine/core/branches/URLMapperService/src/java/org/apache/turbine/services/urlmapper/MappedTemplateLink.java
URL: http://svn.apache.org/viewvc/turbine/core/branches/URLMapperService/src/java/org/apache/turbine/services/urlmapper/MappedTemplateLink.java?rev=1885436&r1=1885435&r2=1885436&view=diff
==============================================================================
--- turbine/core/branches/URLMapperService/src/java/org/apache/turbine/services/urlmapper/MappedTemplateLink.java (original)
+++ turbine/core/branches/URLMapperService/src/java/org/apache/turbine/services/urlmapper/MappedTemplateLink.java Wed Jan 13 16:39:10 2021
@@ -54,6 +54,7 @@ public class MappedTemplateLink extends
      */
     @TurbineService
     private URLMapperService urlMapperService;
+    
 
     /**
      * Builds the URL with all of the data URL-encoded as well as
@@ -95,7 +96,7 @@ public class MappedTemplateLink extends
      * tui.getRelativeLink();
      * </pre>
      *
-     * The above call to absoluteLink() would return the String:
+     * The above call to relativeLink() would return the String:
      * <p>
      * /servlets/Turbine/screen/UserScreen/user/jon
      * <p>
@@ -111,4 +112,5 @@ public class MappedTemplateLink extends
         urlMapperService.mapToURL(templateURI);
         return super.getRelativeLink();
     }
+    
 }

Modified: turbine/core/branches/URLMapperService/src/java/org/apache/turbine/services/urlmapper/TurbineURLMapperService.java
URL: http://svn.apache.org/viewvc/turbine/core/branches/URLMapperService/src/java/org/apache/turbine/services/urlmapper/TurbineURLMapperService.java?rev=1885436&r1=1885435&r2=1885436&view=diff
==============================================================================
--- turbine/core/branches/URLMapperService/src/java/org/apache/turbine/services/urlmapper/TurbineURLMapperService.java (original)
+++ turbine/core/branches/URLMapperService/src/java/org/apache/turbine/services/urlmapper/TurbineURLMapperService.java Wed Jan 13 16:39:10 2021
@@ -50,6 +50,9 @@ import org.apache.turbine.services.urlma
 import org.apache.turbine.util.uri.TurbineURI;
 import org.apache.turbine.util.uri.URIParam;
 
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
+
 /**
  * The URL mapper service provides methods to map a set of parameters to a
  * simplified URL and vice-versa. This service was inspired by the
@@ -140,6 +143,10 @@ public class TurbineURLMapperService
                         LinkedHashMap::new));
 
         Set<String> keys = new HashSet<>(uriParameterMap.keySet());
+        
+        if (keys.isEmpty() && uri.getQueryData().isEmpty() || uri.getPathInfo().isEmpty()) {
+        	return; // no mapping or mapping already done
+        }
 
         for (URLMapEntry urlMap : container.getMapEntries())
         {
@@ -306,14 +313,21 @@ public class TurbineURLMapperService
 
         try (InputStream reader = servletService.getResourceAsStream(configFile))
         {
-            JAXBContext jaxb = JAXBContext.newInstance(URLMappingContainer.class);
-            Unmarshaller unmarshaller = jaxb.createUnmarshaller();
-            container = (URLMappingContainer) unmarshaller.unmarshal(reader);
+            if (configFile.endsWith(".xml")) {
+	            JAXBContext jaxb = JAXBContext.newInstance(URLMappingContainer.class);
+	            Unmarshaller unmarshaller = jaxb.createUnmarshaller();
+	            container = (URLMappingContainer) unmarshaller.unmarshal(reader);
+            } else if (configFile.endsWith(".yml")) {
+            	// org.apache.commons.configuration2.YAMLConfiguration does only expose property like configuration values,
+            	// which is not what we need here -> java object deserialization.
+            	ObjectMapper mapper = new ObjectMapper(new YAMLFactory());
+            	container = mapper.readValue(reader, URLMappingContainer.class);
+            }
         }
         catch (IOException | JAXBException e)
         {
             throw new InitializationException("Could not load configuration file " + configFile, e);
-        }
+        } 
 
         // Get groupNamesMap for every Pattern and store it in the entry
         try

Modified: turbine/core/branches/URLMapperService/src/java/org/apache/turbine/services/urlmapper/model/URLMapEntry.java
URL: http://svn.apache.org/viewvc/turbine/core/branches/URLMapperService/src/java/org/apache/turbine/services/urlmapper/model/URLMapEntry.java?rev=1885436&r1=1885435&r2=1885436&view=diff
==============================================================================
--- turbine/core/branches/URLMapperService/src/java/org/apache/turbine/services/urlmapper/model/URLMapEntry.java (original)
+++ turbine/core/branches/URLMapperService/src/java/org/apache/turbine/services/urlmapper/model/URLMapEntry.java Wed Jan 13 16:39:10 2021
@@ -30,6 +30,9 @@ import javax.xml.bind.annotation.XmlElem
 import javax.xml.bind.annotation.XmlType;
 import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
 
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
 /**
  * The url map model class
  *
@@ -37,6 +40,7 @@ import javax.xml.bind.annotation.adapter
  */
 @XmlType(name="map")
 @XmlAccessorType(XmlAccessType.NONE)
+@JsonIgnoreProperties(ignoreUnknown = true)
 public class URLMapEntry
 {
     private Pattern urlPattern;
@@ -52,6 +56,7 @@ public class URLMapEntry
      */
     @XmlElement(name="pattern")
     @XmlJavaTypeAdapter(XmlPatternAdapter.class)
+    @JsonProperty("pattern")
     public Pattern getUrlPattern()
     {
         return urlPattern;
@@ -70,6 +75,7 @@ public class URLMapEntry
      */
     @XmlElement(name="implicit-parameters")
     @XmlJavaTypeAdapter(XmlParameterAdapter.class)
+    @JsonProperty("implicit-parameters")
     public Map<String, String> getImplicitParameters()
     {
         return implicit;
@@ -88,6 +94,7 @@ public class URLMapEntry
      */
     @XmlElement(name="ignore-parameters")
     @XmlJavaTypeAdapter(XmlParameterAdapter.class)
+    @JsonProperty("ignore-parameters")
     public Map<String, String> getIgnoreParameters()
     {
         return ignore;
@@ -106,6 +113,7 @@ public class URLMapEntry
      */
     @XmlElement(name="override-parameters")
     @XmlJavaTypeAdapter(XmlParameterAdapter.class)
+    @JsonProperty("override-parameters")
     public Map<String, String> getOverrideParameters()
     {
         return override;
@@ -158,4 +166,9 @@ public class URLMapEntry
     {
         this.relevantKeys = relevantKeys;
     }
+    
+    @Override
+    public String toString() {
+    	return "URLMapEntry: [ pattern: " + urlPattern + ", implicit-parameters: " + implicit + ", override-parameters: " + override + ", ignore-parameters:" + ignore + " ]";
+    }
 }

Modified: turbine/core/branches/URLMapperService/src/java/org/apache/turbine/services/urlmapper/model/URLMappingContainer.java
URL: http://svn.apache.org/viewvc/turbine/core/branches/URLMapperService/src/java/org/apache/turbine/services/urlmapper/model/URLMappingContainer.java?rev=1885436&r1=1885435&r2=1885436&view=diff
==============================================================================
--- turbine/core/branches/URLMapperService/src/java/org/apache/turbine/services/urlmapper/model/URLMappingContainer.java (original)
+++ turbine/core/branches/URLMapperService/src/java/org/apache/turbine/services/urlmapper/model/URLMappingContainer.java Wed Jan 13 16:39:10 2021
@@ -29,6 +29,9 @@ import javax.xml.bind.annotation.XmlElem
 import javax.xml.bind.annotation.XmlElementWrapper;
 import javax.xml.bind.annotation.XmlRootElement;
 
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
 /**
  * URL Map Container Model Class
  *
@@ -36,8 +39,10 @@ import javax.xml.bind.annotation.XmlRoot
  */
 @XmlRootElement(name="url-mapping")
 @XmlAccessorType(XmlAccessType.NONE)
+@JsonIgnoreProperties(ignoreUnknown = true)
 public class URLMappingContainer
 {
+
     /**
      * Name of this map.
      */
@@ -47,7 +52,8 @@ public class URLMappingContainer
     /**
      * The list of map entries
      */
-    private CopyOnWriteArrayList<URLMapEntry> urlMapEntries = new CopyOnWriteArrayList<>();
+    @JsonProperty("maps")
+    private List<URLMapEntry> urlMapEntries = new CopyOnWriteArrayList<>();
 
     /**
      * Set the name of this map.

Modified: turbine/core/branches/URLMapperService/src/test/org/apache/turbine/services/urlmapper/TurbineURLMapperServiceTest.java
URL: http://svn.apache.org/viewvc/turbine/core/branches/URLMapperService/src/test/org/apache/turbine/services/urlmapper/TurbineURLMapperServiceTest.java?rev=1885436&r1=1885435&r2=1885436&view=diff
==============================================================================
--- turbine/core/branches/URLMapperService/src/test/org/apache/turbine/services/urlmapper/TurbineURLMapperServiceTest.java (original)
+++ turbine/core/branches/URLMapperService/src/test/org/apache/turbine/services/urlmapper/TurbineURLMapperServiceTest.java Wed Jan 13 16:39:10 2021
@@ -19,9 +19,13 @@ package org.apache.turbine.services.urlm
  * under the License.
  */
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+
+import java.util.*;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.function.IntConsumer;
+import java.util.stream.IntStream;
 
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
@@ -31,43 +35,56 @@ import org.apache.turbine.Turbine;
 import org.apache.turbine.pipeline.PipelineData;
 import org.apache.turbine.services.TurbineServices;
 import org.apache.turbine.test.BaseTestCase;
+import org.apache.turbine.util.RunData;
 import org.apache.turbine.util.TurbineConfig;
 import org.apache.turbine.util.uri.TemplateURI;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Tag;
+import org.junit.jupiter.api.Test;
 import org.mockito.Mockito;
 
-public class TurbineURLMapperServiceTest extends BaseTestCase
-{
+public class TurbineURLMapperServiceTest extends BaseTestCase {
     private TurbineConfig tc = null;
 
     private URLMapperService urlMapper = null;
 
-    @Before
-    public void setUp() throws Exception
-    {
+    @BeforeEach
+    public void setUp() throws Exception {
         tc =
-            new TurbineConfig(
-                ".",
-                "/conf/test/TurbineURLMapperServiceTest.properties");
+                new TurbineConfig(
+                        ".",
+                        "/conf/test/TurbineURLMapperServiceTest.properties");
         tc.initialize();
 
-        urlMapper = (URLMapperService)TurbineServices.getInstance().getService(URLMapperService.SERVICE_NAME);
+        urlMapper = (URLMapperService) TurbineServices.getInstance().getService(URLMapperService.SERVICE_NAME);
     }
 
-    @After
-    public void tearDown() throws Exception
-    {
-        if (tc != null)
-        {
+    @AfterEach
+    public void tearDown() throws Exception {
+        if (tc != null) {
             tc.dispose();
         }
     }
 
+    /**
+     * Tests
+     *
+     * <code>scheme://bob/wow/damn2/bookId/123</code>
+     * <code>scheme://bob/wow/book/123</code>
+     * <p>
+     * and
+     *
+     * <code>scheme://bob/wow/damn2/bookId/123/template/Book.vm?detail=1&detail=2&view=collapsed</code>
+     * <code>scheme://bob/wow/book/123/1?view=collapsed</code>
+     *
+     * @throws Exception
+     */
     @Test
-    public void testMapToURL() throws Exception
-    {
+    public void testMapToURL() throws Exception {
         assertNotNull(urlMapper);
         HttpServletRequest request = getMockRequest();
         HttpServletResponse response = Mockito.mock(HttpServletResponse.class);
@@ -100,9 +117,16 @@ public class TurbineURLMapperServiceTest
         assertEquals(1, uri.getQueryData().size());
     }
 
+    /**
+     * Tests
+     *
+     * <code>scheme:///app/book/123/4</code>
+     * <code>scheme:///wow/damn2/detail/4/bookId/123</code>
+     *
+     * @throws Exception
+     */
     @Test
-    public void testMapFromURL() throws Exception
-    {
+    public void testMapFromURL() throws Exception {
         assertNotNull(urlMapper);
         HttpServletRequest request = getMockRequest();
         HttpServletResponse response = Mockito.mock(HttpServletResponse.class);
@@ -119,6 +143,175 @@ public class TurbineURLMapperServiceTest
         assertEquals(123, pp.getInt("bookId"));
         assertEquals("Book.vm", pp.getString("template"));
         assertEquals(4, pp.getInt("detail"));
+
+        // double check
+        TemplateURI uri = new TemplateURI(pipelineData.getRunData());
+        uri.clearResponse();
+        uri.addPathInfo(pp);
+        assertEquals("/wow/damn2/detail/4/bookId/123", uri.getRelativeLink());
+        urlMapper.mapToURL(uri);
+        assertEquals("/wow/book/123/4", uri.getRelativeLink());
+
     }
 
+
+    @Tag("performance")
+    @Test
+    public void testPerformance() throws Exception {
+
+        assertNotNull(urlMapper);
+        int templateURIs = 5;
+        List<AtomicLong> counterSum = new ArrayList();
+        List<AtomicInteger> counters = new ArrayList();
+        for (int i = 0; i < templateURIs; i++) {
+            counters.add(i, new AtomicInteger(0));
+            counterSum.add(i, new AtomicLong(0l));
+        }
+        int calls = 1_000; // above 1000 the experiment begins ..
+        boolean parallel = false;
+        IntStream range = IntStream.range(0, calls);
+        if (parallel) range = range.parallel();
+        SplittableRandom sr = new SplittableRandom();
+        Spliterator.OfInt spliterator1 = range.spliterator();
+        Spliterator.OfInt spliterator2 = spliterator1.trySplit();
+
+        System.out.println("s1 estimateSize: " + spliterator1.estimateSize());
+        spliterator1.forEachRemaining((IntConsumer) i ->
+        {
+            runCheck(templateURIs, counterSum, counters, parallel, sr);
+        });
+        System.out.println("s2 estimateSize: " + spliterator2.estimateSize());
+        spliterator2.forEachRemaining((IntConsumer) i ->
+        {
+            runCheck(templateURIs, counterSum, counters, parallel, sr);
+        });
+
+        for (int i = 0; i < counters.size() - 1; i++) {
+            long time = counterSum.get(i).longValue() / 1_000_000;
+            int count = counters.get(i).get();
+            TemplateURI turi = getURI(i);
+            String relativeLink = turi.getRelativeLink();
+            callMapToUrl(turi);
+            System.out.printf("time = %dms (%d calls),average time = %5.3fmics, uri=%s, map=%s%n", time, count,
+                    (double) (count > 0 ? ((double) time * 1000 / (double) count) : 0),
+                    relativeLink, turi.getRelativeLink());
+        }
+        System.out.printf("total time = %dms (%d total calls) parallel:%s%n",
+                counterSum.stream().mapToInt(i -> i.intValue()).sum() / 1_000_000,
+                counters.stream().mapToInt(i -> i.intValue()).sum(),
+                parallel
+        );
+    }
+
+    private void runCheck(int templateURIs, List<AtomicLong> counterSum, List<AtomicInteger> counters, boolean parallel, SplittableRandom sr) {
+        int randomNum = sr.nextInt(templateURIs);
+        TemplateURI turi = getURI(randomNum);
+        long time = System.nanoTime();
+        try {
+            callMapToUrl(turi);
+        } finally {
+            time = System.nanoTime() - time;
+        	counterSum.get(randomNum).addAndGet(time);
+        	counters.get(randomNum).incrementAndGet();
+        }
+    }
+
+    /**
+     * to get a fresh URI
+     *
+     * @param tnr
+     * @return
+     */
+    private TemplateURI getURI(int tnr) {
+        TemplateURI turi = null;
+        switch (tnr) {
+            case 0:
+                turi = getURI1();
+                break;
+            case 1:
+                turi = getURI2();
+                break;
+            case 2:
+                turi = getURI3();
+                break;
+            case 3:
+                turi = getURI4();
+                break;
+            case 4:
+                turi = getURI5();
+                break;
+            default:
+                break;
+        }
+        return turi;
+    }
+
+    private TemplateURI getURI1() {
+        TemplateURI uri = new TemplateURI(getRunData());
+        uri.clearResponse(); // avoid encoding on mocked HTTPServletResponse
+        uri.addPathInfo("bookId", 123);
+        uri.setTemplate("Book.vm");
+        uri.addQueryData("detail", 0);
+        return uri;
+
+    }
+
+    private TemplateURI getURI2() {
+        TemplateURI uri2 = new TemplateURI(getRunData());
+        uri2.clearResponse();
+        uri2.addPathInfo("bookId", 123);
+        uri2.setTemplate("Book.vm");
+        uri2.addQueryData("detail", 1);
+        uri2.addQueryData("detail", 2);
+        uri2.addQueryData("view", "collapsed");
+        return uri2;
+    }
+
+    private TemplateURI getURI3() {
+        TemplateURI uri3 = new TemplateURI(getRunData());
+        uri3.clearResponse();
+        uri3.addPathInfo("id", 1234);
+        uri3.addPathInfo("role", "guest");
+        uri3.addPathInfo("language", "de");
+        return uri3;
+    }
+
+    private TemplateURI getURI4() {
+        TemplateURI uri4 = new TemplateURI(getRunData());
+        uri4.clearResponse();
+        uri4.addPathInfo("js_pane", "random-id-123-abc");
+        uri4.addPathInfo("role", "anon");
+        uri4.addPathInfo("media-type", "html");
+        uri4.setTemplate("Registerone.vm");
+        return uri4;
+    }
+
+    private TemplateURI getURI5() {
+        TemplateURI uri5 = new TemplateURI(getRunData());
+        uri5.clearResponse();
+        uri5.addPathInfo("js_pane", "another-random-id-876-dfg");
+        uri5.addPathInfo("role", "anon");
+        uri5.addPathInfo("media-type", "html");
+        uri5.addPathInfo("page", "Contact");
+        return uri5;
+    }
+
+
+    private RunData getRunData() {
+        HttpServletRequest request = getMockRequest();
+        HttpServletResponse response = Mockito.mock(HttpServletResponse.class);
+        try {
+            PipelineData pipelineData = getPipelineData(request, response, tc.getTurbine().getServletConfig());
+            assertNotNull(pipelineData);
+            return pipelineData.getRunData();
+        } catch (Exception e) {
+            fail();
+        }
+        return null;
+    }
+
+    private void callMapToUrl(TemplateURI uri) {
+        urlMapper.mapToURL(uri);
+        assertTrue(uri.getPathInfo().isEmpty(), "path is not empty:" + uri.getPathInfo());
+    }
 }

Added: turbine/core/branches/URLMapperService/src/test/org/apache/turbine/services/urlmapper/TurbineYamlURLMapperServiceTest.java
URL: http://svn.apache.org/viewvc/turbine/core/branches/URLMapperService/src/test/org/apache/turbine/services/urlmapper/TurbineYamlURLMapperServiceTest.java?rev=1885436&view=auto
==============================================================================
--- turbine/core/branches/URLMapperService/src/test/org/apache/turbine/services/urlmapper/TurbineYamlURLMapperServiceTest.java (added)
+++ turbine/core/branches/URLMapperService/src/test/org/apache/turbine/services/urlmapper/TurbineYamlURLMapperServiceTest.java Wed Jan 13 16:39:10 2021
@@ -0,0 +1,206 @@
+package org.apache.turbine.services.urlmapper;
+
+/*
+ * 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.
+ */
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.fulcrum.parser.ParameterParser;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.apache.turbine.Turbine;
+import org.apache.turbine.pipeline.PipelineData;
+import org.apache.turbine.services.TurbineServices;
+import org.apache.turbine.test.BaseTestCase;
+import org.apache.turbine.util.RunData;
+import org.apache.turbine.util.TurbineConfig;
+import org.apache.turbine.util.uri.TemplateURI;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Tag;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mockito;
+
+@Tag("yaml")
+public class TurbineYamlURLMapperServiceTest extends BaseTestCase {
+	
+	private static TurbineConfig tc = null;
+
+	private static URLMapperService urlMapper = null;
+
+	private RunData data;
+	
+	Logger log = LogManager.getLogger();
+
+	@BeforeAll
+	public static void setUp() throws Exception {
+		tc = new TurbineConfig(".", "/conf/test/TurbineYamlURLMapperServiceTest.properties");
+		tc.initialize();
+
+		urlMapper = (URLMapperService) TurbineServices.getInstance().getService(URLMapperService.SERVICE_NAME);
+	}
+
+	@AfterAll
+	public static void tearDown() throws Exception {
+		if (tc != null) {
+			tc.dispose();
+		}
+	}
+
+	@BeforeEach
+	public void init() throws Exception {
+
+		ServletConfig config = tc.getTurbine().getServletConfig();
+		// mock(ServletConfig.class);
+		HttpServletRequest request = getMockRequest();
+		HttpServletResponse response = mock(HttpServletResponse.class);
+
+		data = getRunData(request, response, config);
+		
+		Mockito.when(response.encodeURL(Mockito.anyString())).thenAnswer(invocation -> invocation.getArgument(0));
+	}
+
+	@Test
+	public void testMapToAnotherURL() throws Exception {
+
+		PipelineData pipelineData = data;
+
+		assertNotNull(urlMapper);
+
+		TemplateURI uri = new TemplateURI(pipelineData.getRunData());
+		uri.addPathInfo("id", 1234);
+		uri.addPathInfo("role", "guest");
+		uri.addPathInfo("language", "de");
+
+		String unMappedURL = uri.getAbsoluteLink(); // scheme://bob/wow/damn2/id/1234/role/guest
+
+		urlMapper.mapToURL(uri);
+		urlMapper.mapToURL(uri); // should be idempotent
+
+		String mappedLink = uri.getRelativeLink(); // wow/damn2/id/1234/role/guest
+		log.info(unMappedURL);
+		log.info(mappedLink);
+
+		String expectedMappedURL = "/wow/1234/guest/de";
+		String expectedRawURL = "scheme://bob/wow/damn2/id/1234/role/guest/language/de";
+		// raw url
+		assertEquals(expectedRawURL, unMappedURL);
+		assertEquals(expectedMappedURL, mappedLink);
+
+		ParameterParser pp = pipelineData.get(Turbine.class, ParameterParser.class);
+		assertNotNull(pp);
+		assertTrue(pp.keySet().isEmpty());
+		urlMapper.mapFromURL(mappedLink, pp);
+
+		assertEquals(5, pp.keySet().size());
+		assertEquals(1234, pp.getInt("id"));
+		assertEquals("guest", pp.getString("role"));
+		assertEquals("de", pp.getString("language"));
+		assertEquals("html", pp.getString("media-type"));
+
+		TemplateURI uri2 = new TemplateURI(pipelineData.getRunData());
+		uri2.clearResponse();
+		uri2.setTemplate("default.vm");
+		uri2.addPathInfo(pp);
+		// this is an artifical url
+		assertEquals("scheme://bob/wow/damn2/template/default.vm/media-type/html/role/guest/id/1234/language/de",
+				uri2.getAbsoluteLink());
+		urlMapper.mapToURL(uri2);
+		assertEquals(expectedMappedURL, uri2.getRelativeLink());
+	}
+
+	@Test
+	public void testOverrideShortURL() throws Exception {
+
+		PipelineData pipelineData = data;
+		
+		assertNotNull(urlMapper);
+
+		ParameterParser pp = pipelineData.get(Turbine.class, ParameterParser.class);
+		assertNotNull(pp);
+		assertTrue(pp.keySet().isEmpty());
+		
+		pp.add("role", "admin"); // will not be overridden
+		urlMapper.mapFromURL("/app/register", pp);
+
+		assertEquals(4, pp.keySet().size());
+		assertEquals("random-id-123-abc", pp.getString("js_pane"));
+		assertEquals("admin", pp.getString("role"));
+//        assertEquals("de", pp.getString("language"));
+		assertEquals("html", pp.getString("media-type"));
+		assertEquals("Registerone.vm", pp.getString("template"));
+
+		TemplateURI uri2 = new TemplateURI(pipelineData.getRunData());
+		uri2.clearResponse();
+		uri2.setTemplate("Registerone.vm");
+		pp.remove("role");
+		pp.add("role", "anon");
+		uri2.addPathInfo(pp);
+
+		// this is an artifical url, as the exact sequence could not be reconstructed as
+		// ParameterParser uses expicitely a random access table
+		assertEquals(
+				"scheme://bob/wow/damn2/template/Registerone.vm/media-type/html/js_pane/random-id-123-abc/role/anon",
+				uri2.getAbsoluteLink());
+		urlMapper.mapToURL(uri2);
+		String expectedMappedURL = "/wow/register";
+		assertEquals(expectedMappedURL, uri2.getRelativeLink());
+
+		pp.clear();
+		pp.add("role", "admin");// will be overridden
+		urlMapper.mapFromURL("/app/contact", pp);
+		assertEquals(4, pp.keySet().size());
+		assertEquals("anon", pp.getString("role"));
+		assertEquals("another-random-id-876-dfg", pp.getString("js_pane"));
+
+		uri2 = new TemplateURI(pipelineData.getRunData());
+		uri2.clearResponse();
+		uri2.addPathInfo(pp);
+
+		// this is an artifical url
+		assertEquals("scheme://bob/wow/damn2/page/Contact/media-type/html/js_pane/another-random-id-876-dfg/role/anon",
+				uri2.getAbsoluteLink());
+		urlMapper.mapToURL(uri2);
+		expectedMappedURL = "/wow/contact";
+		assertEquals(expectedMappedURL, uri2.getRelativeLink());
+
+	}
+	
+//	/**
+//	 * 		Not implemented Test for MappedTemplateLink:
+//	 * - To work with <i>MappedTemplateLink</i>, we need access to the urlmapperservice in order to 
+//	 * - simulate a request without pipeline (setting velocity context and initializing the service):
+//	 */
+//   @Test
+//   public void testMappedURILink() {   
+//   	MappedTemplateLink ml = MappedTemplateLink.class.getDeclaredConstructor().newInstance();
+//   	assertNotNull(ml);
+//   	ml.setUrlMapperService(urlMapper);
+//   	ml.init(data);
+//   }
+
+}

Added: turbine/core/branches/URLMapperService/src/test/org/apache/turbine/services/urlmapper/model/YamlURLMappingContainerTest.java
URL: http://svn.apache.org/viewvc/turbine/core/branches/URLMapperService/src/test/org/apache/turbine/services/urlmapper/model/YamlURLMappingContainerTest.java?rev=1885436&view=auto
==============================================================================
--- turbine/core/branches/URLMapperService/src/test/org/apache/turbine/services/urlmapper/model/YamlURLMappingContainerTest.java (added)
+++ turbine/core/branches/URLMapperService/src/test/org/apache/turbine/services/urlmapper/model/YamlURLMappingContainerTest.java Wed Jan 13 16:39:10 2021
@@ -0,0 +1,66 @@
+package org.apache.turbine.services.urlmapper.model;
+
+
+import static org.junit.jupiter.api.Assertions.*;
+
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Pattern;
+
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Tag;
+import org.junit.jupiter.api.Test;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
+
+@Tag("yaml")
+public class YamlURLMappingContainerTest
+{
+    private static URLMappingContainer container;
+
+    @BeforeAll
+    public static void setUp() throws Exception
+    {
+        try (InputStream reader = new FileInputStream("conf/turbine-url-mapping.yml"))
+        {
+        	ObjectMapper mapper = new ObjectMapper(new YAMLFactory());
+        	// List<URLMapEntry> urlList = 
+        	// mapper.readValue(reader, mapper.getTypeFactory().constructCollectionType(List.class, URLMapEntry.class));//            	
+        	container = mapper.readValue(reader, URLMappingContainer.class);
+        }
+    }
+
+    @Test
+    public void testGetName()
+    {
+        assertNotNull(container);
+        assertEquals("default", container.getName());
+    }
+
+    @Test
+    public void testGetMapEntries()
+    {
+        assertNotNull(container);
+
+        List<URLMapEntry> mapEntries = container.getMapEntries();
+        assertNotNull(mapEntries);
+        assertNotEquals(0, mapEntries.size());
+
+        URLMapEntry entry = mapEntries.get(0);
+        assertNotNull(entry);
+
+        Pattern pattern = entry.getUrlPattern();
+        assertNotNull(pattern);
+        assertTrue(pattern.matcher("/app/book/123").matches());
+
+        Map<String, String> implicit = entry.getImplicitParameters();
+        assertNotNull(implicit);
+        assertEquals(2, implicit.size());
+        assertEquals("Book.vm", implicit.get("template"));
+        assertEquals("0", implicit.get("detail"));
+    }
+
+}

Modified: turbine/core/branches/URLMapperService/src/test/org/apache/turbine/test/BaseTestCase.java
URL: http://svn.apache.org/viewvc/turbine/core/branches/URLMapperService/src/test/org/apache/turbine/test/BaseTestCase.java?rev=1885436&r1=1885435&r2=1885436&view=diff
==============================================================================
--- turbine/core/branches/URLMapperService/src/test/org/apache/turbine/test/BaseTestCase.java (original)
+++ turbine/core/branches/URLMapperService/src/test/org/apache/turbine/test/BaseTestCase.java Wed Jan 13 16:39:10 2021
@@ -41,10 +41,10 @@ import javax.servlet.ServletConfig;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import javax.servlet.http.HttpSession;
-import javax.xml.parsers.FactoryConfigurationError;
 
 import org.apache.log4j.PropertyConfigurator;
-import org.apache.log4j.xml.DOMConfigurator;
+import org.apache.logging.log4j.core.config.ConfigurationSource;
+import org.apache.logging.log4j.core.config.Configurator;
 import org.apache.turbine.TurbineConstants;
 import org.apache.turbine.pipeline.PipelineData;
 import org.apache.turbine.services.TurbineServices;
@@ -65,43 +65,13 @@ import org.mockito.stubbing.Answer;
  */
 public abstract class BaseTestCase
 {
-    static File log4jFile = new File("conf/test/log4j.xml");
+    static File log4j2File = new File("conf/test/log4j2.xml");
 
     @BeforeClass
     public static void baseInit()
             throws Exception
     {
-
-        if (log4jFile.getName().endsWith(".xml"))
-        {
-            // load XML type configuration
-            // NOTE: Only system property expansion available
-            try
-            {
-                DOMConfigurator.configure(log4jFile.getAbsolutePath());
-            }
-            catch (FactoryConfigurationError e)
-            {
-                System.err.println("Could not configure Log4J from configuration file "
-                        + log4jFile + ": ");
-                e.printStackTrace();
-            }
-        }
-        else {
-            Properties p = new Properties();
-            try
-            {
-                p.load(new FileInputStream(log4jFile));
-                p.setProperty(TurbineConstants.APPLICATION_ROOT_KEY, new File(".").getAbsolutePath());
-                PropertyConfigurator.configure(p);
-    
-            }
-            catch (FileNotFoundException fnf)
-            {
-                System.err.println("Could not open Log4J configuration file "
-                        + log4jFile);
-            }
-        }
+    	// auto load log4j2 file
     }
 
     protected RunData getRunData(HttpServletRequest request,HttpServletResponse response,ServletConfig config) throws Exception {