Optimize / Cleanup QueryStringDecoder / QueryStringEncoder

Motivation:

QueryStringDecoder and QueryStringEncoder contained some code that could either cleaned-up or optimized.

Modifications:

- Fix typos in exception messages and javadocs
- Precompile Pattern
- Make use of StringUtil.EMPTY_STRING

Result:

Faster and cleaner code.
This commit is contained in:
Norman Maurer 2017-02-27 10:49:40 +01:00
parent ca2c349a4a
commit d675febf07
2 changed files with 27 additions and 42 deletions

View File

@ -26,6 +26,10 @@ import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import static io.netty.util.internal.ObjectUtil.checkNotNull;
import static io.netty.util.internal.ObjectUtil.checkPositive;
import static io.netty.util.internal.StringUtil.EMPTY_STRING;
/** /**
* Splits an HTTP query string into a path string and key-value parameter pairs. * Splits an HTTP query string into a path string and key-value parameter pairs.
* This decoder is for one time use only. Create a new instance for each URI: * This decoder is for one time use only. Create a new instance for each URI:
@ -102,16 +106,9 @@ public class QueryStringDecoder {
* specified charset. * specified charset.
*/ */
public QueryStringDecoder(String uri, Charset charset, boolean hasPath, int maxParams) { public QueryStringDecoder(String uri, Charset charset, boolean hasPath, int maxParams) {
if (uri == null) { checkNotNull(uri, "uri");
throw new NullPointerException("getUri"); checkNotNull(charset, "charset");
} checkPositive(maxParams, "maxParams");
if (charset == null) {
throw new NullPointerException("charset");
}
if (maxParams <= 0) {
throw new IllegalArgumentException(
"maxParams: " + maxParams + " (expected: a positive integer)");
}
this.uri = uri; this.uri = uri;
this.charset = charset; this.charset = charset;
@ -140,26 +137,19 @@ public class QueryStringDecoder {
* specified charset. * specified charset.
*/ */
public QueryStringDecoder(URI uri, Charset charset, int maxParams) { public QueryStringDecoder(URI uri, Charset charset, int maxParams) {
if (uri == null) { checkNotNull(uri, "uri");
throw new NullPointerException("getUri"); checkNotNull(charset, "charset");
} checkPositive(maxParams, "maxParams");
if (charset == null) {
throw new NullPointerException("charset");
}
if (maxParams <= 0) {
throw new IllegalArgumentException(
"maxParams: " + maxParams + " (expected: a positive integer)");
}
String rawPath = uri.getRawPath(); String rawPath = uri.getRawPath();
if (rawPath != null) { if (rawPath != null) {
hasPath = true; hasPath = true;
} else { } else {
rawPath = ""; rawPath = EMPTY_STRING;
hasPath = false; hasPath = false;
} }
// Also take care of cut of things like "http://localhost" // Also take care of cut of things like "http://localhost"
this.uri = rawPath + (uri.getRawQuery() == null? "" : '?' + uri.getRawQuery()); this.uri = uri.getRawQuery() == null? rawPath : rawPath + '?' + uri.getRawQuery();
this.charset = charset; this.charset = charset;
this.maxParams = maxParams; this.maxParams = maxParams;
@ -178,10 +168,10 @@ public class QueryStringDecoder {
public String path() { public String path() {
if (path == null) { if (path == null) {
if (!hasPath) { if (!hasPath) {
path = ""; path = EMPTY_STRING;
} else { } else {
int pathEndPos = uri.indexOf('?'); int pathEndPos = uri.indexOf('?');
path = decodeComponent(pathEndPos < 0 ? uri : uri.substring(0, pathEndPos), this.charset); path = decodeComponent(pathEndPos < 0 ? uri : uri.substring(0, pathEndPos), charset);
} }
} }
return path; return path;
@ -230,7 +220,7 @@ public class QueryStringDecoder {
// We haven't seen an `=' so far but moved forward. // We haven't seen an `=' so far but moved forward.
// Must be a param of the form '&a&' so add it with // Must be a param of the form '&a&' so add it with
// an empty value. // an empty value.
if (!addParam(params, decodeComponent(s.substring(pos, i), charset), "")) { if (!addParam(params, decodeComponent(s.substring(pos, i), charset), EMPTY_STRING)) {
return; return;
} }
} else if (name != null) { } else if (name != null) {
@ -245,7 +235,7 @@ public class QueryStringDecoder {
if (pos != i) { // Are there characters we haven't dealt with? if (pos != i) { // Are there characters we haven't dealt with?
if (name == null) { // Yes and we haven't seen any `='. if (name == null) { // Yes and we haven't seen any `='.
addParam(params, decodeComponent(s.substring(pos, i), charset), ""); addParam(params, decodeComponent(s.substring(pos, i), charset), EMPTY_STRING);
} else { // Yes and this must be the last value. } else { // Yes and this must be the last value.
addParam(params, name, decodeComponent(s.substring(pos, i), charset)); addParam(params, name, decodeComponent(s.substring(pos, i), charset));
} }
@ -308,7 +298,7 @@ public class QueryStringDecoder {
*/ */
public static String decodeComponent(final String s, final Charset charset) { public static String decodeComponent(final String s, final Charset charset) {
if (s == null) { if (s == null) {
return ""; return EMPTY_STRING;
} }
final int size = s.length(); final int size = s.length();
boolean modified = false; boolean modified = false;

View File

@ -15,6 +15,8 @@
*/ */
package io.netty.handler.codec.http; package io.netty.handler.codec.http;
import io.netty.util.internal.ObjectUtil;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.net.URI; import java.net.URI;
import java.net.URISyntaxException; import java.net.URISyntaxException;
@ -23,6 +25,7 @@ import java.nio.charset.Charset;
import java.nio.charset.UnsupportedCharsetException; import java.nio.charset.UnsupportedCharsetException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.regex.Pattern;
/** /**
* Creates an URL-encoded URI from a path string and key-value parameter pairs. * Creates an URL-encoded URI from a path string and key-value parameter pairs.
@ -37,6 +40,7 @@ import java.util.List;
*/ */
public class QueryStringEncoder { public class QueryStringEncoder {
private static final Pattern PATTERN = Pattern.compile("+", Pattern.LITERAL);
private final Charset charset; private final Charset charset;
private final String uri; private final String uri;
private final List<Param> params = new ArrayList<Param>(); private final List<Param> params = new ArrayList<Param>();
@ -54,31 +58,22 @@ public class QueryStringEncoder {
* path string in the specified charset. * path string in the specified charset.
*/ */
public QueryStringEncoder(String uri, Charset charset) { public QueryStringEncoder(String uri, Charset charset) {
if (uri == null) { this.uri = ObjectUtil.checkNotNull(uri, "uri");
throw new NullPointerException("getUri"); this.charset = ObjectUtil.checkNotNull(charset, "charset");
}
if (charset == null) {
throw new NullPointerException("charset");
}
this.uri = uri;
this.charset = charset;
} }
/** /**
* Adds a parameter with the specified name and value to this encoder. * Adds a parameter with the specified name and value to this encoder.
*/ */
public void addParam(String name, String value) { public void addParam(String name, String value) {
if (name == null) { ObjectUtil.checkNotNull(name, "name");
throw new NullPointerException("name");
}
params.add(new Param(name, value)); params.add(new Param(name, value));
} }
/** /**
* Returns the URL-encoded URI object which was created from the path string * Returns the URL-encoded URI object which was created from the path string
* specified in the constructor and the parameters added by * specified in the constructor and the parameters added by
* {@link #addParam(String, String)} getMethod. * {@link #addParam(String, String)} method.
*/ */
public URI toUri() throws URISyntaxException { public URI toUri() throws URISyntaxException {
return new URI(toString()); return new URI(toString());
@ -87,7 +82,7 @@ public class QueryStringEncoder {
/** /**
* Returns the URL-encoded URI which was created from the path string * Returns the URL-encoded URI which was created from the path string
* specified in the constructor and the parameters added by * specified in the constructor and the parameters added by
* {@link #addParam(String, String)} getMethod. * {@link #addParam(String, String)} method.
*/ */
@Override @Override
public String toString() { public String toString() {
@ -113,7 +108,7 @@ public class QueryStringEncoder {
private static String encodeComponent(String s, Charset charset) { private static String encodeComponent(String s, Charset charset) {
// TODO: Optimize me. // TODO: Optimize me.
try { try {
return URLEncoder.encode(s, charset.name()).replace("+", "%20"); return URLEncoder.encode(s, PATTERN.matcher(charset.name()).replaceAll("%20"));
} catch (UnsupportedEncodingException ignored) { } catch (UnsupportedEncodingException ignored) {
throw new UnsupportedCharsetException(charset.name()); throw new UnsupportedCharsetException(charset.name());
} }