Replace dynamic regular expressions with precompiled Patterns or new StringUtil.split()

This commit is contained in:
Trustin Lee 2012-11-10 00:42:35 +09:00
parent 00d9111833
commit c34d0a2272
12 changed files with 131 additions and 42 deletions

View File

@ -15,17 +15,18 @@
*/
package org.jboss.netty.example.localtime;
import org.jboss.netty.bootstrap.ClientBootstrap;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory;
import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.Executors;
import org.jboss.netty.bootstrap.ClientBootstrap;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory;
import java.util.regex.Pattern;
/**
* Sends a list of continent/city pairs to a {@link LocalTimeServer} to
@ -108,10 +109,12 @@ public class LocalTimeClient {
" localhost 8080 America/New_York Asia/Seoul");
}
private static final Pattern CITY_PATTERN = Pattern.compile("^[_A-Za-z]+/[_A-Za-z]+$");
private static List<String> parseCities(String[] args, int offset) {
List<String> cities = new ArrayList<String>();
for (int i = offset; i < args.length; i ++) {
if (!args[i].matches("^[_A-Za-z]+/[_A-Za-z]+$")) {
if (!CITY_PATTERN.matcher(args[i]).matches()) {
System.err.println("Syntax error: '" + args[i] + "'");
printUsage();
return null;

View File

@ -15,15 +15,6 @@
*/
package org.jboss.netty.example.localtime;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Formatter;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelEvent;
import org.jboss.netty.channel.ChannelHandlerContext;
@ -37,11 +28,23 @@ import org.jboss.netty.example.localtime.LocalTimeProtocol.LocalTimes;
import org.jboss.netty.example.localtime.LocalTimeProtocol.Location;
import org.jboss.netty.example.localtime.LocalTimeProtocol.Locations;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Formatter;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Pattern;
public class LocalTimeClientHandler extends SimpleChannelUpstreamHandler {
private static final Logger logger = Logger.getLogger(
LocalTimeClientHandler.class.getName());
private static final Pattern DELIM = Pattern.compile("/");
// Stateful properties
private volatile Channel channel;
private final BlockingQueue<LocalTimes> answer = new LinkedBlockingQueue<LocalTimes>();
@ -50,7 +53,7 @@ public class LocalTimeClientHandler extends SimpleChannelUpstreamHandler {
Locations.Builder builder = Locations.newBuilder();
for (String c: cities) {
String[] components = c.split("/");
String[] components = DELIM.split(c);
builder.addLocation(Location.newBuilder().
setContinent(Continent.valueOf(components[0].toUpperCase())).
setCity(components[1]).build());

View File

@ -15,6 +15,8 @@
*/
package org.jboss.netty.handler.codec.http;
import org.jboss.netty.util.internal.StringUtil;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Collections;
@ -39,7 +41,7 @@ import java.util.TreeSet;
*/
public class CookieDecoder {
private static final String COMMA = ",";
private static final char COMMA = ',';
/**
* Creates a new decoder.
@ -146,7 +148,7 @@ public class CookieDecoder {
} else if (CookieHeaderNames.VERSION.equalsIgnoreCase(name)) {
version = Integer.parseInt(value);
} else if (CookieHeaderNames.PORT.equalsIgnoreCase(name)) {
String[] portList = value.split(COMMA);
String[] portList = StringUtil.split(value, COMMA);
for (String s1: portList) {
try {
ports.add(Integer.valueOf(s1));

View File

@ -21,6 +21,7 @@ import org.jboss.netty.handler.codec.compression.ZlibEncoder;
import org.jboss.netty.handler.codec.compression.ZlibWrapper;
import org.jboss.netty.handler.codec.embedder.EncoderEmbedder;
import org.jboss.netty.util.internal.DetectionUtil;
import org.jboss.netty.util.internal.StringUtil;
/**
* Compresses an {@link HttpMessage} and an {@link HttpChunk} in {@code gzip} or
@ -138,7 +139,7 @@ public class HttpContentCompressor extends HttpContentEncoder {
float starQ = -1.0f;
float gzipQ = -1.0f;
float deflateQ = -1.0f;
for (String encoding : acceptEncoding.split(",")) {
for (String encoding: StringUtil.split(acceptEncoding, ',')) {
float q = 1.0f;
int equalsPos = encoding.indexOf('=');
if (equalsPos != -1) {

View File

@ -26,6 +26,7 @@ import org.jboss.netty.handler.codec.http.multipart.HttpPostBodyUtil.SeekAheadNo
import org.jboss.netty.handler.codec.http.multipart.HttpPostBodyUtil.SeekAheadOptimize;
import org.jboss.netty.handler.codec.http.multipart.HttpPostBodyUtil.TransferEncodingMechanism;
import org.jboss.netty.util.internal.CaseIgnoringComparator;
import org.jboss.netty.util.internal.StringUtil;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
@ -966,7 +967,7 @@ public class HttpPostRequestDecoder {
if (checkSecondArg) {
// read next values and store them in the map as Attribute
for (int i = 2; i < contents.length; i ++) {
String[] values = contents[i].split("=");
String[] values = StringUtil.split(contents[i], '=');
Attribute attribute;
try {
attribute = factory.createAttribute(request, values[0].trim(),
@ -1012,7 +1013,7 @@ public class HttpPostRequestDecoder {
// Take care of possible "multipart/mixed"
if (contents[1].equalsIgnoreCase(HttpPostBodyUtil.MULTIPART_MIXED)) {
if (currentStatus == MultiPartStatus.DISPOSITION) {
String[] values = contents[2].split("=");
String[] values = StringUtil.split(contents[2], '=');
multipartMixedBoundary = "--" + values[1];
currentStatus = MultiPartStatus.MIXEDDELIMITER;
return decodeMultipart(MultiPartStatus.MIXEDDELIMITER);
@ -1024,7 +1025,7 @@ public class HttpPostRequestDecoder {
for (int i = 1; i < contents.length; i ++) {
if (contents[i].toLowerCase().startsWith(
HttpHeaders.Values.CHARSET)) {
String[] values = contents[i].split("=");
String[] values = StringUtil.split(contents[i], '=');
Attribute attribute;
try {
attribute = factory.createAttribute(request,
@ -1995,10 +1996,10 @@ public class HttpPostRequestDecoder {
headers.add(sb.substring(nameStart, nameEnd));
String svalue = sb.substring(valueStart, valueEnd);
String[] values = null;
if (svalue.indexOf(";") >= 0) {
values = svalue.split(";");
if (svalue.indexOf(';') >= 0) {
values = StringUtil.split(svalue, ';');
} else {
values = svalue.split(",");
values = StringUtil.split(svalue, ',');
}
for (String value: values) {
headers.add(value.trim());

View File

@ -15,15 +15,16 @@
*/
package org.jboss.netty.handler.codec.http.websocketx;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.Set;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ChannelFutureListener;
import org.jboss.netty.channel.Channels;
import org.jboss.netty.handler.codec.http.HttpRequest;
import org.jboss.netty.util.internal.StringUtil;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.Set;
/**
* Base class for server side web socket opening and closing handshakes
@ -90,7 +91,7 @@ public abstract class WebSocketServerHandshaker {
this.version = version;
this.webSocketUrl = webSocketUrl;
if (subprotocols != null) {
String[] subprotocolArray = subprotocols.split(",");
String[] subprotocolArray = StringUtil.split(subprotocols, ',');
for (int i = 0; i < subprotocolArray.length; i++) {
subprotocolArray[i] = subprotocolArray[i].trim();
}
@ -163,7 +164,7 @@ public abstract class WebSocketServerHandshaker {
return null;
}
String[] requestedSubprotocolArray = requestedSubprotocols.split(",");
String[] requestedSubprotocolArray = StringUtil.split(requestedSubprotocols, ',');
for (String p : requestedSubprotocolArray) {
String requestedSubprotocol = p.trim();

View File

@ -15,11 +15,12 @@
*/
package org.jboss.netty.handler.ipfilter;
import java.net.UnknownHostException;
import java.util.ArrayList;
import org.jboss.netty.logging.InternalLogger;
import org.jboss.netty.logging.InternalLoggerFactory;
import org.jboss.netty.util.internal.StringUtil;
import java.net.UnknownHostException;
import java.util.ArrayList;
/**
* The Class IpFilterRuleList is a helper class to generate a List of Rules from a string.
@ -58,7 +59,7 @@ public class IpFilterRuleList extends ArrayList<IpFilterRule> {
}
private void parseRules(String rules) {
String[] ruless = rules.split(",");
String[] ruless = StringUtil.split(rules, ',');
for (String rule : ruless) {
parseRule(rule.trim());
}

View File

@ -16,13 +16,14 @@
package org.jboss.netty.handler.ipfilter;
import org.jboss.netty.logging.InternalLogger;
import org.jboss.netty.logging.InternalLoggerFactory;
import org.jboss.netty.util.internal.StringUtil;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.regex.Pattern;
import org.jboss.netty.logging.InternalLogger;
import org.jboss.netty.logging.InternalLoggerFactory;
/**
* The Class PatternRule represents an IP filter rule using string patterns.
* <br>
@ -113,7 +114,7 @@ public class PatternRule implements IpFilterRule, Comparable<Object> {
return;
}
String[] acls = pattern.split(",");
String[] acls = StringUtil.split(pattern, ',');
String ip = "";
String name = "";

View File

@ -17,6 +17,7 @@ package org.jboss.netty.util.internal;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;
/**
* Conversion utility class to parse a property represented as a string or
@ -64,6 +65,8 @@ public final class ConversionUtil {
}
}
private static final Pattern ARRAY_DELIM = Pattern.compile("[, \\t\\n\\r\\f\\e\\a]");
/**
* Converts the specified object into an array of strings.
*/
@ -84,7 +87,7 @@ public final class ConversionUtil {
return answer.toArray(new String[answer.size()]);
}
return String.valueOf(value).split("[, \\t\\n\\r\\f\\e\\a]");
return ARRAY_DELIM.split(String.valueOf(value));
}
private static final String[] INTEGERS = {

View File

@ -15,7 +15,9 @@
*/
package org.jboss.netty.util.internal;
import java.util.ArrayList;
import java.util.Formatter;
import java.util.List;
/**
* String utility class.
@ -114,4 +116,47 @@ public final class StringUtil {
return buf.toString();
}
private static final String EMPTY_STRING = "";
/**
* Splits the specified {@link String} with the specified delimiter. This operation is a simplified and optimized
* version of {@link String#split(String)}.
*/
public static String[] split(String value, char delim) {
final int end = value.length();
final List<String> res = new ArrayList<String>();
int start = 0;
for (int i = 0; i < end; i ++) {
if (value.charAt(i) == delim) {
if (start == i) {
res.add(EMPTY_STRING);
} else {
res.add(value.substring(start, i));
}
start = i + 1;
}
}
if (start == 0) { // If no delimiter was found in the value
res.add(value);
} else {
if (start != end) {
// Add the last element if it's not empty.
res.add(value.substring(start, end));
} else {
// Truncate trailing empty elements.
for (int i = res.size() - 1; i >= 0; i --) {
if (res.get(i).length() == 0) {
res.remove(i);
} else {
break;
}
}
}
}
return res.toArray(new String[res.size()]);
}
}

View File

@ -20,6 +20,7 @@ import org.jboss.netty.logging.InternalLoggerFactory;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Pattern;
/**
* A collection of utility methods to retrieve and parse the values of the Java system properties.
@ -122,6 +123,8 @@ public final class SystemPropertyUtil {
return def;
}
private static final Pattern INTEGER_PATTERN = Pattern.compile("-?[0-9]+");
/**
* Returns the value of the Java system property with the specified
* {@code key}, while falling back to the specified default value if
@ -138,7 +141,7 @@ public final class SystemPropertyUtil {
}
value = value.trim().toLowerCase();
if (value.matches("-?[0-9]+")) {
if (INTEGER_PATTERN.matcher(value).matches()) {
try {
return Integer.parseInt(value);
} catch (Exception e) {
@ -169,7 +172,7 @@ public final class SystemPropertyUtil {
}
value = value.trim().toLowerCase();
if (value.matches("-?[0-9]+")) {
if (INTEGER_PATTERN.matcher(value).matches()) {
try {
return Long.parseLong(value);
} catch (Exception e) {

View File

@ -79,4 +79,29 @@ public class StringUtilTest {
final String stripped = StringUtil.stripControlCharacters(string);
assertEquals("The string should be unchanged", string, stripped);
}
@Test
public void splitSimple() {
assertArrayEquals(new String[] { "foo", "bar" }, StringUtil.split("foo:bar", ':'));
}
@Test
public void splitWithTrailingDelimiter() {
assertArrayEquals(new String[] { "foo", "bar" }, StringUtil.split("foo,bar,", ','));
}
@Test
public void splitWithTrailingDelimiters() {
assertArrayEquals(new String[] { "foo", "bar" }, StringUtil.split("foo!bar!!", '!'));
}
@Test
public void splitWithConsecutiveDelimiters() {
assertArrayEquals(new String[] { "foo", "", "bar" }, StringUtil.split("foo$$bar", '$'));
}
@Test
public void splitWithDelimiterAtBeginning() {
assertArrayEquals(new String[] { "", "foo", "bar" }, StringUtil.split("#foo#bar", '#'));
}
}