From f2c59a3cb781f3e9816e018c19351b1df876f97c Mon Sep 17 00:00:00 2001 From: Olivier Lamy Date: Thu, 23 May 2019 09:01:36 +1000 Subject: [PATCH] add convenient StringUtil isEmpty method (#3687) * add StringUtil.isEmpty Signed-off-by: olivier lamy --- .../jetty/client/HttpClientTLSTest.java | 3 +- .../jetty/client/HttpClientURITest.java | 3 +- .../fcgi/server/HttpChannelOverFCGI.java | 3 +- .../org/eclipse/jetty/http/HttpParser.java | 3 +- .../server/HTTP2ServerConnectionFactory.java | 3 +- .../jetty/util/StringIsEmptyBenchmark.java | 66 +++++++++++++++++++ .../jetty/server/session/SessionHandler.java | 2 +- .../org/eclipse/jetty/util/StringUtil.java | 25 ++++++- .../eclipse/jetty/util/StringUtilTest.java | 16 +++++ 9 files changed, 117 insertions(+), 7 deletions(-) create mode 100644 jetty-jmh/src/main/java/org/eclipse/jetty/util/StringIsEmptyBenchmark.java diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientTLSTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientTLSTest.java index 959e9ac2639..8aebfe94044 100644 --- a/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientTLSTest.java +++ b/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientTLSTest.java @@ -45,6 +45,7 @@ import org.eclipse.jetty.io.ssl.SslHandshakeListener; import org.eclipse.jetty.server.Handler; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.ServerConnector; +import org.eclipse.jetty.util.StringUtil; import org.eclipse.jetty.util.ssl.SslContextFactory; import org.eclipse.jetty.util.thread.ExecutorThreadPool; import org.eclipse.jetty.util.thread.QueuedThreadPool; @@ -501,7 +502,7 @@ public class HttpClientTLSTest while (true) { String line = reader.readLine(); - if (line == null || line.isEmpty()) + if (StringUtil.isEmpty(line)) break; } diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientURITest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientURITest.java index c5a7158f96c..0863fcc770d 100644 --- a/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientURITest.java +++ b/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientURITest.java @@ -44,6 +44,7 @@ import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.server.handler.AbstractHandler; import org.eclipse.jetty.toolchain.test.Net; import org.eclipse.jetty.util.Fields; +import org.eclipse.jetty.util.StringUtil; import org.eclipse.jetty.util.URIUtil; import org.junit.jupiter.api.Assumptions; import org.junit.jupiter.params.ParameterizedTest; @@ -609,7 +610,7 @@ public class HttpClientURITest extends AbstractHttpClientServerTest while (true) { String line = reader.readLine(); - if (line == null || line.isEmpty()) + if (StringUtil.isEmpty(line)) break; } diff --git a/jetty-fcgi/fcgi-server/src/main/java/org/eclipse/jetty/fcgi/server/HttpChannelOverFCGI.java b/jetty-fcgi/fcgi-server/src/main/java/org/eclipse/jetty/fcgi/server/HttpChannelOverFCGI.java index db67c560a8d..1e75f083490 100644 --- a/jetty-fcgi/fcgi-server/src/main/java/org/eclipse/jetty/fcgi/server/HttpChannelOverFCGI.java +++ b/jetty-fcgi/fcgi-server/src/main/java/org/eclipse/jetty/fcgi/server/HttpChannelOverFCGI.java @@ -35,6 +35,7 @@ import org.eclipse.jetty.server.Connector; import org.eclipse.jetty.server.HttpChannel; import org.eclipse.jetty.server.HttpConfiguration; import org.eclipse.jetty.server.HttpTransport; +import org.eclipse.jetty.util.StringUtil; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; @@ -87,7 +88,7 @@ public class HttpChannelOverFCGI extends HttpChannel public void onRequest() { String uri = path; - if (query != null && !query.isEmpty()) + if (!StringUtil.isEmpty(query)) uri += "?" + query; // TODO https? onRequest(new MetaData.Request(method, HttpScheme.HTTP.asString(), hostPort, uri, HttpVersion.fromString(version), fields,Long.MIN_VALUE)); diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpParser.java b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpParser.java index 13a807ce131..93efdc5dfa6 100644 --- a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpParser.java +++ b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpParser.java @@ -28,6 +28,7 @@ import org.eclipse.jetty.http.HttpTokens.EndOfContent; import org.eclipse.jetty.util.ArrayTernaryTrie; import org.eclipse.jetty.util.ArrayTrie; import org.eclipse.jetty.util.BufferUtil; +import org.eclipse.jetty.util.StringUtil; import org.eclipse.jetty.util.Trie; import org.eclipse.jetty.util.Utf8StringBuilder; import org.eclipse.jetty.util.log.Log; @@ -1132,7 +1133,7 @@ public class HttpParser throw new BadMessageException(HttpStatus.BAD_REQUEST_400,"Header Folding"); // header value without name - continuation? - if (_valueString==null || _valueString.isEmpty()) + if ( StringUtil.isEmpty(_valueString)) { _string.setLength(0); _length=0; diff --git a/jetty-http2/http2-server/src/main/java/org/eclipse/jetty/http2/server/HTTP2ServerConnectionFactory.java b/jetty-http2/http2-server/src/main/java/org/eclipse/jetty/http2/server/HTTP2ServerConnectionFactory.java index 9ae23123000..f2add0f087f 100644 --- a/jetty-http2/http2-server/src/main/java/org/eclipse/jetty/http2/server/HTTP2ServerConnectionFactory.java +++ b/jetty-http2/http2-server/src/main/java/org/eclipse/jetty/http2/server/HTTP2ServerConnectionFactory.java @@ -38,6 +38,7 @@ import org.eclipse.jetty.server.Connector; import org.eclipse.jetty.server.HttpConfiguration; import org.eclipse.jetty.server.NegotiatingServerConnection.CipherDiscriminator; import org.eclipse.jetty.util.Callback; +import org.eclipse.jetty.util.StringUtil; import org.eclipse.jetty.util.annotation.Name; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; @@ -116,7 +117,7 @@ public class HTTP2ServerConnectionFactory extends AbstractHTTP2ServerConnectionF public void onClose(Session session, GoAwayFrame frame, Callback callback) { String reason = frame.tryConvertPayload(); - if (reason != null && !reason.isEmpty()) + if (!StringUtil.isEmpty(reason)) reason = " (" + reason + ")"; getConnection().onSessionFailure(new EofException(String.format("Close %s/%s", ErrorCode.toString(frame.getError(), null), reason)), callback); } diff --git a/jetty-jmh/src/main/java/org/eclipse/jetty/util/StringIsEmptyBenchmark.java b/jetty-jmh/src/main/java/org/eclipse/jetty/util/StringIsEmptyBenchmark.java new file mode 100644 index 00000000000..42e51760e8f --- /dev/null +++ b/jetty-jmh/src/main/java/org/eclipse/jetty/util/StringIsEmptyBenchmark.java @@ -0,0 +1,66 @@ +// +// ======================================================================== +// Copyright (c) 1995-2019 Mort Bay Consulting Pty. Ltd. +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// +// The Apache License v2.0 is available at +// http://www.opensource.org/licenses/apache2.0.php +// +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== +// + +package org.eclipse.jetty.util; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Threads; +import org.openjdk.jmh.annotations.Warmup; + +import java.util.concurrent.TimeUnit; + +@State( Scope.Benchmark) +@Threads(4) +@Warmup(iterations = 7, time = 500, timeUnit = TimeUnit.MILLISECONDS) +@Measurement(iterations = 9, time = 800, timeUnit = TimeUnit.MILLISECONDS) +public class StringIsEmptyBenchmark +{ + + private static final String SHORT = "beer.com/foo"; + + private static final String MEDIUM = "beer.com/foobarbeeerbe/bebbebbebebbe/bebbeghdegde/foobarbeeerbe/bebbebbebebbe/bebbeghdegde"; + + private static final String LONG = "beer.com/foobarbeeerbe/bebbebbebebbe/bebbeghdegde/foobarbeeerbe/bebbebbebebbe/bebbeghdegde/foobarbeeerbe/bebbebbebebbe/bebbeghdegde/foobarbeeerbe/bebbebbebebbe/bebbeghdegde/foobarbeeerbe/bebbebbebebbe/bebbeghdegde/foobarbeeerbe/bebbebbebebbe/bebbeghdegde/foobarbeeerbe/bebbebbebebbe/bebbeghdegde"; + + + @Benchmark + @BenchmarkMode( Mode.Throughput) + public void shortIsEmpty() + { + StringUtil.isEmpty(SHORT); + } + + @Benchmark + @BenchmarkMode( Mode.Throughput) + public void mediumIsEmpty() + { + StringUtil.isEmpty(MEDIUM); + } + + @Benchmark + @BenchmarkMode( Mode.Throughput) + public void longIsEmpty() + { + StringUtil.isEmpty(LONG); + } +} diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/session/SessionHandler.java b/jetty-server/src/main/java/org/eclipse/jetty/server/session/SessionHandler.java index a3f74e63807..0165eda509c 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/session/SessionHandler.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/session/SessionHandler.java @@ -725,7 +725,7 @@ public class SessionHandler extends ScopedHandler if (isUsingCookies()) { String sessionPath = (_cookieConfig.getPath()==null) ? contextPath : _cookieConfig.getPath(); - sessionPath = (sessionPath==null||sessionPath.isEmpty()) ? "/" : sessionPath; + sessionPath = (StringUtil.isEmpty(sessionPath)) ? "/" : sessionPath; String id = getExtendedId(session); HttpCookie cookie = null; if (_sessionComment == null) diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/StringUtil.java b/jetty-util/src/main/java/org/eclipse/jetty/util/StringUtil.java index 60104d69f72..d32870b7df8 100644 --- a/jetty-util/src/main/java/org/eclipse/jetty/util/StringUtil.java +++ b/jetty-util/src/main/java/org/eclipse/jetty/util/StringUtil.java @@ -470,7 +470,30 @@ public class StringUtil // only whitespace return true; } - + + /** + *

Checks if a String is empty ("") or null.

+ * + *
+     *   isEmpty(null)   == true
+     *   isEmpty("")     == true
+     *   isEmpty("\r\n") == false
+     *   isEmpty("\t")   == false
+     *   isEmpty("   ")  == false
+     *   isEmpty("a")    == false
+     *   isEmpty(".")    == false
+     *   isEmpty(";\n")  == false
+     * 
+ * + * @param str + * the string to test. + * @return true if string is null or empty. + */ + public static boolean isEmpty(String str) + { + return str == null || str.isEmpty(); + } + /* ------------------------------------------------------------ */ /** * Test if a string is not null and contains at least 1 non-whitespace characters in it. diff --git a/jetty-util/src/test/java/org/eclipse/jetty/util/StringUtilTest.java b/jetty-util/src/test/java/org/eclipse/jetty/util/StringUtilTest.java index 8069b1fc595..51d53110410 100644 --- a/jetty-util/src/test/java/org/eclipse/jetty/util/StringUtilTest.java +++ b/jetty-util/src/test/java/org/eclipse/jetty/util/StringUtilTest.java @@ -261,6 +261,22 @@ public class StringUtilTest assertTrue(StringUtil.isNotBlank(".")); assertTrue(StringUtil.isNotBlank(";\n")); } + + @Test + public void testIsEmpty() + { + assertTrue(StringUtil.isEmpty(null)); + assertTrue(StringUtil.isEmpty("")); + assertFalse(StringUtil.isEmpty("\r\n")); + assertFalse(StringUtil.isEmpty("\t")); + assertFalse(StringUtil.isEmpty(" ")); + + assertFalse(StringUtil.isEmpty("a")); + assertFalse(StringUtil.isEmpty(" a")); + assertFalse(StringUtil.isEmpty("a ")); + assertFalse(StringUtil.isEmpty(".")); + assertFalse(StringUtil.isEmpty(";\n")); + } @Test public void testSanitizeHTML()