You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@struts.apache.org by lu...@apache.org on 2023/06/20 19:24:03 UTC

[struts] branch WW-5310-fragment updated: WW-5310 Deprecates the old API in favour of new one

This is an automated email from the ASF dual-hosted git repository.

lukaszlenart pushed a commit to branch WW-5310-fragment
in repository https://gitbox.apache.org/repos/asf/struts.git


The following commit(s) were added to refs/heads/WW-5310-fragment by this push:
     new e5c7a30f3 WW-5310 Deprecates the old API in favour of new one
e5c7a30f3 is described below

commit e5c7a30f3d4c608f1728d949f1a0ef0a4167f4ba
Author: Lukasz Lenart <lu...@apache.org>
AuthorDate: Tue Jun 20 21:23:57 2023 +0200

    WW-5310 Deprecates the old API in favour of new one
---
 .../struts2/components/ServletUrlRenderer.java     | 17 +++--
 .../struts2/result/ServletDispatcherResult.java    |  8 +-
 .../org/apache/struts2/url/QueryStringParser.java  | 14 +++-
 .../org/apache/struts2/url/QueryStringResult.java  | 89 ++++++++++++++++++++++
 .../struts2/url/StrutsQueryStringParser.java       | 44 +++++------
 .../struts2/url/StrutsQueryStringParserTest.java   | 23 +++---
 6 files changed, 146 insertions(+), 49 deletions(-)

diff --git a/core/src/main/java/org/apache/struts2/components/ServletUrlRenderer.java b/core/src/main/java/org/apache/struts2/components/ServletUrlRenderer.java
index d5281a8a0..18d866542 100644
--- a/core/src/main/java/org/apache/struts2/components/ServletUrlRenderer.java
+++ b/core/src/main/java/org/apache/struts2/components/ServletUrlRenderer.java
@@ -30,6 +30,7 @@ import org.apache.struts2.StrutsException;
 import org.apache.struts2.dispatcher.mapper.ActionMapper;
 import org.apache.struts2.dispatcher.mapper.ActionMapping;
 import org.apache.struts2.url.QueryStringParser;
+import org.apache.struts2.url.QueryStringResult;
 import org.apache.struts2.views.util.UrlHelper;
 
 import java.io.IOException;
@@ -159,10 +160,10 @@ public class ServletUrlRenderer implements UrlRenderer {
             }
         }
 
-        Map<String, Object> actionParams = null;
+        QueryStringResult queryStringResult = QueryStringResult.empty();
         if (action != null && action.indexOf('?') > 0) {
             String queryString = action.substring(action.indexOf('?') + 1);
-            actionParams = queryStringParser.parse(queryString, false);
+            queryStringResult = queryStringParser.parse(queryString);
             action = action.substring(0, action.indexOf('?'));
         }
 
@@ -176,7 +177,7 @@ public class ServletUrlRenderer implements UrlRenderer {
 
             ActionMapping mapping = new ActionMapping(actionName, namespace, actionMethod, formComponent.parameters);
             String result = urlHelper.buildUrl(formComponent.actionMapper.getUriFromActionMapping(mapping),
-                formComponent.request, formComponent.response, actionParams, scheme, formComponent.includeContext, true, false, false);
+                formComponent.request, formComponent.response, queryStringResult.getQueryParams(), scheme, formComponent.includeContext, true, false, false);
             formComponent.addParameter("action", result);
 
             // let's try to get the actual action class and name
@@ -213,7 +214,7 @@ public class ServletUrlRenderer implements UrlRenderer {
                 LOG.warn("No configuration found for the specified action: '{}' in namespace: '{}'. Form action defaulting to 'action' attribute's literal value.", actionName, namespace);
             }
 
-            String result = urlHelper.buildUrl(action, formComponent.request, formComponent.response, actionParams, scheme, formComponent.includeContext, true);
+            String result = urlHelper.buildUrl(action, formComponent.request, formComponent.response, queryStringResult.getQueryParams(), scheme, formComponent.includeContext, true);
             formComponent.addParameter("action", result);
 
             // namespace: cut out anything between the start and the last /
@@ -291,7 +292,11 @@ public class ServletUrlRenderer implements UrlRenderer {
 
     private void includeGetParameters(UrlProvider urlComponent) {
         String query = extractQueryString(urlComponent);
-        mergeRequestParameters(urlComponent.getValue(), urlComponent.getParameters(), queryStringParser.parse(query, false));
+        QueryStringResult result = queryStringParser.parse(query);
+        mergeRequestParameters(urlComponent.getValue(), urlComponent.getParameters(), result.getQueryParams());
+        if (!result.getQueryFragment().isEmpty()) {
+            urlComponent.setAnchor(result.getQueryFragment());
+        }
     }
 
     private String extractQueryString(UrlProvider urlComponent) {
@@ -339,7 +344,7 @@ public class ServletUrlRenderer implements UrlRenderer {
         if (StringUtils.contains(value, "?")) {
             String queryString = value.substring(value.indexOf('?') + 1);
 
-            mergedParams = queryStringParser.parse(queryString, false);
+            mergedParams = new LinkedHashMap<>(queryStringParser.parse(queryString).getQueryParams());
             for (Map.Entry<String, ?> entry : contextParameters.entrySet()) {
                 if (!mergedParams.containsKey(entry.getKey())) {
                     mergedParams.put(entry.getKey(), entry.getValue());
diff --git a/core/src/main/java/org/apache/struts2/result/ServletDispatcherResult.java b/core/src/main/java/org/apache/struts2/result/ServletDispatcherResult.java
index 6bc86725d..e1bc17eb8 100644
--- a/core/src/main/java/org/apache/struts2/result/ServletDispatcherResult.java
+++ b/core/src/main/java/org/apache/struts2/result/ServletDispatcherResult.java
@@ -28,12 +28,12 @@ import org.apache.struts2.ServletActionContext;
 import org.apache.struts2.StrutsStatics;
 import org.apache.struts2.dispatcher.HttpParameters;
 import org.apache.struts2.url.QueryStringParser;
+import org.apache.struts2.url.QueryStringResult;
 
 import javax.servlet.RequestDispatcher;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import javax.servlet.jsp.PageContext;
-import java.util.Map;
 
 /**
  * <!-- START SNIPPET: description -->
@@ -140,9 +140,9 @@ public class ServletDispatcherResult extends StrutsResultSupport {
             if (StringUtils.isNotEmpty(finalLocation) && finalLocation.indexOf('?') > 0) {
                 String queryString = finalLocation.substring(finalLocation.indexOf('?') + 1);
                 HttpParameters parameters = getParameters(invocation);
-                Map<String, Object> queryParams = queryStringParser.parse(queryString, true);
-                if (queryParams != null && !queryParams.isEmpty()) {
-                    parameters = HttpParameters.create(queryParams).withParent(parameters).build();
+                QueryStringResult queryParams = queryStringParser.parse(queryString);
+                if (!queryParams.isEmpty()) {
+                    parameters = HttpParameters.create(queryParams.getQueryParams()).withParent(parameters).build();
                     invocation.getInvocationContext().withParameters(parameters);
                     // put to extraContext, see Dispatcher#createContextMap
                     invocation.getInvocationContext().getContextMap().put("parameters", parameters);
diff --git a/core/src/main/java/org/apache/struts2/url/QueryStringParser.java b/core/src/main/java/org/apache/struts2/url/QueryStringParser.java
index 0f48cd293..d607ab817 100644
--- a/core/src/main/java/org/apache/struts2/url/QueryStringParser.java
+++ b/core/src/main/java/org/apache/struts2/url/QueryStringParser.java
@@ -22,11 +22,23 @@ import java.io.Serializable;
 import java.util.Map;
 
 /**
- * Used to parse Http Query String into a Map of parameters
+ * Used to parse Http Query String into a map of parameters with support for fragment
  * @since Struts 6.1.0
  */
 public interface QueryStringParser extends Serializable {
 
+    /**
+     * @deprecated since Struts 6.2.0, use {@link #parse(String)} instead
+     */
+    @Deprecated
     Map<String, Object> parse(String queryString, boolean forceValueArray);
 
+    /**
+     *
+     * @param queryString a query string to parse
+     * @return a {@link QueryStringResult} of parsing the query string
+     * @since Struts 6.2.0
+     */
+    QueryStringResult parse(String queryString);
+
 }
diff --git a/core/src/main/java/org/apache/struts2/url/QueryStringResult.java b/core/src/main/java/org/apache/struts2/url/QueryStringResult.java
new file mode 100644
index 000000000..0836d2eb8
--- /dev/null
+++ b/core/src/main/java/org/apache/struts2/url/QueryStringResult.java
@@ -0,0 +1,89 @@
+/*
+ * 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.url;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+public class QueryStringResult {
+
+    private final Map<String, Object> queryParams;
+    private String queryFragment;
+
+    public static QueryStringResult empty() {
+        return new QueryStringResult(Collections.emptyMap(), "");
+    }
+
+    public static QueryStringResult create() {
+        return new QueryStringResult(new LinkedHashMap<>(), "");
+    }
+
+    private QueryStringResult(Map<String, Object> queryParams, String queryFragment) {
+        this.queryParams = queryParams;
+        this.queryFragment = queryFragment;
+    }
+
+    public QueryStringResult addParam(String name, String value) {
+        if (queryParams.containsKey(name)) {
+            // WW-1619 append new param value to existing value(s)
+            Object currentParam = queryParams.get(name);
+            if (currentParam instanceof String) {
+                queryParams.put(name, new String[]{(String) currentParam, value});
+            } else {
+                String[] currentParamValues = (String[]) currentParam;
+                if (currentParamValues != null) {
+                    List<String> paramList = new ArrayList<>(Arrays.asList(currentParamValues));
+                    paramList.add(value);
+                    queryParams.put(name, paramList.toArray(new String[0]));
+                } else {
+                    queryParams.put(name, new String[]{value});
+                }
+            }
+        } else {
+            queryParams.put(name, value);
+        }
+
+        return this;
+    }
+
+    public QueryStringResult withQueryFragment(String queryFragment) {
+        this.queryFragment = queryFragment;
+        return this;
+    }
+
+    public Map<String, Object> getQueryParams() {
+        return Collections.unmodifiableMap(queryParams);
+    }
+
+    public String getQueryFragment() {
+        return queryFragment;
+    }
+
+    public boolean contains(String name) {
+        return queryParams.containsKey(name);
+    }
+
+    public boolean isEmpty() {
+        return queryParams.isEmpty();
+    }
+}
diff --git a/core/src/main/java/org/apache/struts2/url/StrutsQueryStringParser.java b/core/src/main/java/org/apache/struts2/url/StrutsQueryStringParser.java
index 4c31d4885..5cc50a01f 100644
--- a/core/src/main/java/org/apache/struts2/url/StrutsQueryStringParser.java
+++ b/core/src/main/java/org/apache/struts2/url/StrutsQueryStringParser.java
@@ -23,11 +23,6 @@ import org.apache.commons.lang3.StringUtils;
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
 
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.LinkedHashMap;
-import java.util.List;
 import java.util.Map;
 
 public class StrutsQueryStringParser implements QueryStringParser {
@@ -43,12 +38,17 @@ public class StrutsQueryStringParser implements QueryStringParser {
 
     @Override
     public Map<String, Object> parse(String queryString, boolean forceValueArray) {
+        return parse(queryString).getQueryParams();
+    }
+
+    @Override
+    public QueryStringResult parse(String queryString) {
         if (StringUtils.isEmpty(queryString)) {
             LOG.debug("Query String is empty, returning an empty map");
-            return Collections.emptyMap();
+            return QueryStringResult.empty();
         }
 
-        Map<String, Object> queryParams = new LinkedHashMap<>();
+        QueryStringResult queryParams = QueryStringResult.create();
         String[] params = extractParams(queryString);
         for (String param : params) {
             if (StringUtils.isBlank(param)) {
@@ -64,9 +64,9 @@ public class StrutsQueryStringParser implements QueryStringParser {
             } else {
                 paramName = param;
             }
-            extractParam(paramName, paramValue, queryParams, forceValueArray);
+            queryParams = extractParam(paramName, paramValue, queryParams);
         }
-        return queryParams;
+        return queryParams.withQueryFragment(extractFragment(queryString));
     }
 
     private String[] extractParams(String queryString) {
@@ -81,27 +81,17 @@ public class StrutsQueryStringParser implements QueryStringParser {
         return params;
     }
 
-    private void extractParam(String paramName, String paramValue, Map<String, Object> queryParams, boolean forceValueArray) {
+    private QueryStringResult extractParam(String paramName, String paramValue, QueryStringResult queryParams) {
         String decodedParamName = decoder.decode(paramName, true);
         String decodedParamValue = decoder.decode(paramValue, true);
+        return queryParams.addParam(decodedParamName, decodedParamValue);
+    }
 
-        if (queryParams.containsKey(decodedParamName) || forceValueArray) {
-            // WW-1619 append new param value to existing value(s)
-            Object currentParam = queryParams.get(decodedParamName);
-            if (currentParam instanceof String) {
-                queryParams.put(decodedParamName, new String[]{(String) currentParam, decodedParamValue});
-            } else {
-                String[] currentParamValues = (String[]) currentParam;
-                if (currentParamValues != null) {
-                    List<String> paramList = new ArrayList<>(Arrays.asList(currentParamValues));
-                    paramList.add(decodedParamValue);
-                    queryParams.put(decodedParamName, paramList.toArray(new String[0]));
-                } else {
-                    queryParams.put(decodedParamName, new String[]{decodedParamValue});
-                }
-            }
-        } else {
-            queryParams.put(decodedParamName, decodedParamValue);
+    private String extractFragment(String queryString) {
+        int fragmentIndex = queryString.lastIndexOf("#");
+        if (fragmentIndex > -1) {
+            return queryString.substring(fragmentIndex + 1);
         }
+        return "";
     }
 }
diff --git a/core/src/test/java/org/apache/struts2/url/StrutsQueryStringParserTest.java b/core/src/test/java/org/apache/struts2/url/StrutsQueryStringParserTest.java
index 93fd9bbaa..7f44fe834 100644
--- a/core/src/test/java/org/apache/struts2/url/StrutsQueryStringParserTest.java
+++ b/core/src/test/java/org/apache/struts2/url/StrutsQueryStringParserTest.java
@@ -35,7 +35,7 @@ public class StrutsQueryStringParserTest {
 
     @Test
     public void testParseQuery() {
-        Map<String, Object> result = parser.parse("aaa=aaaval&bbb=bbbval&ccc=&%3Ca%22%3E=%3Cval%3E", false);
+        Map<String, Object> result = parser.parse("aaa=aaaval&bbb=bbbval&ccc=&%3Ca%22%3E=%3Cval%3E").getQueryParams();
 
         assertEquals("aaaval", result.get("aaa"));
         assertEquals("bbbval", result.get("bbb"));
@@ -45,7 +45,7 @@ public class StrutsQueryStringParserTest {
 
     @Test
     public void testParseQueryIntoArray() {
-        Map<String, Object> result = parser.parse("a=1&a=2&a=3", true);
+        Map<String, Object> result = parser.parse("a=1&a=2&a=3").getQueryParams();
 
         Object actual = result.get("a");
         assertThat(actual).isInstanceOf(String[].class);
@@ -54,7 +54,7 @@ public class StrutsQueryStringParserTest {
 
     @Test
     public void testParseEmptyQuery() {
-        Map<String, Object> result = parser.parse("", false);
+        Map<String, Object> result = parser.parse("").getQueryParams();
 
         assertNotNull(result);
         assertEquals(0, result.size());
@@ -62,7 +62,7 @@ public class StrutsQueryStringParserTest {
 
     @Test
     public void testParseNullQuery() {
-        Map<String, Object> result = parser.parse(null, false);
+        Map<String, Object> result = parser.parse(null).getQueryParams();
 
         assertNotNull(result);
         assertEquals(0, result.size());
@@ -70,7 +70,7 @@ public class StrutsQueryStringParserTest {
 
     @Test
     public void testDecodeSpacesInQueryString() {
-        Map<String, Object> queryParameters = parser.parse("name=value+with+space", false);
+        Map<String, Object> queryParameters = parser.parse("name=value+with+space").getQueryParams();
 
         assertTrue(queryParameters.containsKey("name"));
         assertEquals("value with space", queryParameters.get("name"));
@@ -78,7 +78,7 @@ public class StrutsQueryStringParserTest {
 
     @Test
     public void shouldProperlySplitParamsWithDoubleEqualSign() {
-        Map<String, Object> queryParameters = parser.parse("id1=n123=&id2=n3456", false);
+        Map<String, Object> queryParameters = parser.parse("id1=n123=&id2=n3456").getQueryParams();
 
         assertTrue(queryParameters.containsKey("id1"));
         assertTrue(queryParameters.containsKey("id2"));
@@ -88,7 +88,7 @@ public class StrutsQueryStringParserTest {
 
     @Test
     public void shouldHandleParamWithNoValue1() {
-        Map<String, Object> queryParameters = parser.parse("paramNoValue", false);
+        Map<String, Object> queryParameters = parser.parse("paramNoValue").getQueryParams();
 
         assertTrue(queryParameters.containsKey("paramNoValue"));
         assertEquals("", queryParameters.get("paramNoValue"));
@@ -96,7 +96,7 @@ public class StrutsQueryStringParserTest {
 
     @Test
     public void shouldHandleParamWithNoValue2() {
-        Map<String, Object> queryParameters = parser.parse("paramNoValue&param1=1234", false);
+        Map<String, Object> queryParameters = parser.parse("paramNoValue&param1=1234").getQueryParams();
 
         assertTrue(queryParameters.containsKey("paramNoValue"));
         assertTrue(queryParameters.containsKey("param1"));
@@ -105,10 +105,11 @@ public class StrutsQueryStringParserTest {
 
     @Test
     public void shouldHandleParamAndFragment() {
-        Map<String, Object> queryParameters = parser.parse("param1=1234#test", false);
+        QueryStringResult queryParameters = parser.parse("param1=1234#test");
 
-        assertTrue(queryParameters.containsKey("param1"));
-        assertEquals("1234", queryParameters.get("param1"));
+        assertTrue(queryParameters.getQueryParams().containsKey("param1"));
+        assertEquals("1234", queryParameters.getQueryParams().get("param1"));
+        assertEquals("test", queryParameters.getQueryFragment());
     }
 
     @Before