Skip to content

Commit

Permalink
Improved: Refactor ‘UtilHttp#getPathInfoOnlyParameterMap’
Browse files Browse the repository at this point in the history
(OFBIZ-11138)


git-svn-id: https://svn.apache.org/repos/asf/ofbiz/ofbiz-framework/trunk@1863395 13f79535-47bb-0310-9956-ffa450edef68
  • Loading branch information
mthl committed Jul 19, 2019
1 parent b1f0137 commit caf4fe9
Showing 1 changed file with 35 additions and 48 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@
*******************************************************************************/
package org.apache.ofbiz.base.util;

import static java.util.stream.Collectors.collectingAndThen;
import static java.util.stream.Collectors.groupingBy;
import static java.util.stream.Collectors.mapping;
import static java.util.stream.Collectors.toList;
import static java.util.stream.Collectors.toMap;
import static org.apache.ofbiz.base.util.UtilGenerics.checkList;

import java.io.BufferedInputStream;
Expand All @@ -34,6 +39,7 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Currency;
import java.util.Enumeration;
import java.util.HashMap;
Expand All @@ -42,9 +48,11 @@
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.TimeZone;
import java.util.function.Function;

import javax.net.ssl.SSLContext;
import javax.servlet.http.HttpServletRequest;
Expand Down Expand Up @@ -158,7 +166,7 @@ public static Map<String, Object> getParameterMap(HttpServletRequest request, Se
paramMap.put(name, value);
}

paramMap.putAll(getPathInfoOnlyParameterMap(request.getPathInfo(), nameSet, onlyIncludeOrSkip));
paramMap.putAll(getPathInfoOnlyParameterMap(request.getPathInfo(), nameSet, onlyIncludeOrSkipPrim));

Map<String, Object> multiPartMap = new HashMap<>();
if (paramMap.size() == 0) {
Expand Down Expand Up @@ -306,58 +314,37 @@ public static Map<String, Object> getQueryStringOnlyParameterMap(String queryStr
return canonicalizeParameterMap(paramMap);
}

public static Map<String, Object> getPathInfoOnlyParameterMap(String pathInfoStr, Set<? extends String> nameSet, Boolean onlyIncludeOrSkip) {
boolean onlyIncludeOrSkipPrim = onlyIncludeOrSkip == null ? true : onlyIncludeOrSkip;
Map<String, Object> paramMap = new HashMap<>();

// now add in all path info parameters /~name1=value1/~name2=value2/
// note that if a parameter with a given name already exists it will be put into a list with all values

if (UtilValidate.isNotEmpty(pathInfoStr)) {
// make sure string ends with a trailing '/' so we get all values
if (!pathInfoStr.endsWith("/")) {
pathInfoStr += "/";
}

int current = pathInfoStr.indexOf('/');
int last = current;
while ((current = pathInfoStr.indexOf('/', last + 1)) != -1) {
String element = pathInfoStr.substring(last + 1, current);
last = current;
if (element.charAt(0) == '~' && element.indexOf('=') > -1) {
String name = element.substring(1, element.indexOf('='));
if (nameSet != null && (onlyIncludeOrSkipPrim ^ nameSet.contains(name))) {
continue;
}

String value = element.substring(element.indexOf('=') + 1);
Object curValue = paramMap.get(name);
if (curValue != null) {
List<String> paramList = null;
if (curValue instanceof List<?>) {
paramList = UtilGenerics.checkList(curValue);
paramList.add(value);
} else {
String paramString = (String) curValue;
paramList = new LinkedList<>();
paramList.add(paramString);
paramList.add(value);
}
paramMap.put(name, paramList);
} else {
paramMap.put(name, value);
}
}
}
}

return canonicalizeParameterMap(paramMap);
/**
* Extracts the parameters that are passed in the URI path.
* <p>
* path parameters are denoted by "/~KEY0=VALUE0/~KEY1=VALUE1/".
* This is an obsolete syntax for passing parameters to request handlers.
*
* @param path the URI path part which can be {@code null}
* @param nameSet the set of parameters keys to include or skip
* @param includeOrSkip toggle where {@code true} means including and {@code false} means skipping
* @return a canonicalized parameter map.
*/
static Map<String, Object> getPathInfoOnlyParameterMap(String path, Set<? extends String> nameSet,
boolean includeOrSkip) {
String path$ = Optional.ofNullable(path).orElse("");
Map<String, List<String>> allParams = Arrays.stream(path$.split("/"))
.filter(segment -> segment.startsWith("~") && segment.contains("="))
.map(kv -> kv.substring(1).split("="))
.collect(groupingBy(kv -> kv[0], mapping(kv -> kv[1], toList())));

// Filter and canonicalize the parameter map.
Function<List<String>, Object> canonicalize = val -> (val.size() == 1) ? val.get(0) : val;
return allParams.entrySet().stream()
.filter(e -> nameSet == null || !(includeOrSkip ^ nameSet.contains(e.getKey())))
.collect(collectingAndThen(toMap(Map.Entry::getKey, canonicalize.compose(Map.Entry::getValue)),
UtilHttp::canonicalizeParameterMap));
}

public static Map<String, Object> getUrlOnlyParameterMap(HttpServletRequest request) {
// NOTE: these have already been through canonicalizeParameterMap, so not doing it again here
Map<String, Object> paramMap = getQueryStringOnlyParameterMap(request.getQueryString());
paramMap.putAll(getPathInfoOnlyParameterMap(request.getPathInfo(), null, null));
paramMap.putAll(getPathInfoOnlyParameterMap(request.getPathInfo(), null, true));
return paramMap;
}

Expand Down

0 comments on commit caf4fe9

Please sign in to comment.