io.github.oliviercailloux.gitjfs.impl.QueryUtils Maven / Gradle / Ivy
package io.github.oliviercailloux.gitjfs.impl;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
import com.google.common.net.PercentEscaper;
import java.net.URI;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.util.AbstractMap.SimpleImmutableEntry;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
class QueryUtils {
public static final PercentEscaper QUERY_ENTRY_ESCAPER =
new PercentEscaper("-_.*~!$'(),;@:/+?", false);
private static final PercentEscaper RESTRICTED_ESCAPER = new PercentEscaper("-_.*%", false);
/**
* Thanks to https://stackoverflow.com/a/13592567/.
*/
public static Map splitQuery(URI uri) {
if (Strings.isNullOrEmpty(uri.getRawQuery())) {
return Collections.emptyMap();
}
final Map> asLists =
Arrays.stream(uri.getRawQuery().split("&")).map(QueryUtils::splitQueryParameter)
.collect(Collectors.groupingBy(SimpleImmutableEntry::getKey, LinkedHashMap::new,
Collectors.mapping(Map.Entry::getValue, Collectors.toList())));
if (asLists.keySet().stream().anyMatch(k -> asLists.get(k).size() >= 2)) {
throw new IllegalArgumentException();
}
return asLists.keySet().stream().collect(
ImmutableMap.toImmutableMap(k -> k, k -> Iterables.getOnlyElement(asLists.get(k))));
}
/**
* Thanks to https://stackoverflow.com/a/13592567/.
*/
private static SimpleImmutableEntry splitQueryParameter(String it) {
final int idx = it.indexOf("=");
final String key = idx > 0 ? it.substring(0, idx) : it;
final String value = idx > 0 && it.length() > idx + 1 ? it.substring(idx + 1) : null;
/*
* Because URLDecoder only decodes very restricted strings, I need to encode a bit more before
* decoding. Importantly, I need to encode plus, otherwise converted back to space instead of
* left alone. But I need to leave % alone as this indicates a percent-escape, not a percent
* sign. Sob.
*/
final String decodedKey =
URLDecoder.decode(RESTRICTED_ESCAPER.escape(key), StandardCharsets.UTF_8);
final String decodedValue =
URLDecoder.decode(RESTRICTED_ESCAPER.escape(value), StandardCharsets.UTF_8);
return new SimpleImmutableEntry<>(decodedKey, decodedValue);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy