From 9735d1ad98678b15b04f65bd8f88daa32f6f5618 Mon Sep 17 00:00:00 2001 From: benoit Date: Wed, 31 Aug 2016 16:39:42 +0200 Subject: [PATCH] improve jwt parser memory allocation re-use buffer instead of creating new ones avoid creating unneeded buffers in the Strings util methods Stop continuously copying array with StringBuilder#deleteCharAt work directly on StringBuilder instead of creating a temporary String test added to cover the modified methods --- .../jsonwebtoken/impl/DefaultJwtParser.java | 5 ++- .../java/io/jsonwebtoken/lang/Strings.java | 30 +++++++++---- .../io/jsonwebtoken/lang/StringsTest.groovy | 42 +++++++++++++++++++ 3 files changed, 68 insertions(+), 9 deletions(-) diff --git a/src/main/java/io/jsonwebtoken/impl/DefaultJwtParser.java b/src/main/java/io/jsonwebtoken/impl/DefaultJwtParser.java index da2c4582..50df0c7e 100644 --- a/src/main/java/io/jsonwebtoken/impl/DefaultJwtParser.java +++ b/src/main/java/io/jsonwebtoken/impl/DefaultJwtParser.java @@ -213,7 +213,8 @@ public class DefaultJwtParser implements JwtParser { if (c == SEPARATOR_CHAR) { - String token = Strings.clean(sb.toString()); + CharSequence tokenSeq = Strings.clean(sb); + String token = tokenSeq!=null?tokenSeq.toString():null; if (delimiterCount == 0) { base64UrlEncodedHeader = token; @@ -222,7 +223,7 @@ public class DefaultJwtParser implements JwtParser { } delimiterCount++; - sb = new StringBuilder(128); + sb.setLength(0); } else { sb.append(c); } diff --git a/src/main/java/io/jsonwebtoken/lang/Strings.java b/src/main/java/io/jsonwebtoken/lang/Strings.java index d1974260..a93cf340 100644 --- a/src/main/java/io/jsonwebtoken/lang/Strings.java +++ b/src/main/java/io/jsonwebtoken/lang/Strings.java @@ -159,22 +159,38 @@ public final class Strings { * @see java.lang.Character#isWhitespace */ public static String trimWhitespace(String str) { + return (String) trimWhitespace((CharSequence)str); + } + + + private static CharSequence trimWhitespace(CharSequence str) { if (!hasLength(str)) { return str; } - StringBuilder sb = new StringBuilder(str); - while (sb.length() > 0 && Character.isWhitespace(sb.charAt(0))) { - sb.deleteCharAt(0); + final int length = str.length(); + + int start = 0; + while (start < length && Character.isWhitespace(str.charAt(start))) { + start++; } - while (sb.length() > 0 && Character.isWhitespace(sb.charAt(sb.length() - 1))) { - sb.deleteCharAt(sb.length() - 1); + + int end = length; + while (start < length && Character.isWhitespace(str.charAt(end - 1))) { + end--; } - return sb.toString(); + + return ((start > 0) || (end < length)) ? str.subSequence(start, end) : str; } public static String clean(String str) { + CharSequence result = clean((CharSequence) str); + + return result!=null?result.toString():null; + } + + public static CharSequence clean(CharSequence str) { str = trimWhitespace(str); - if ("".equals(str)) { + if (!hasLength(str)) { return null; } return str; diff --git a/src/test/groovy/io/jsonwebtoken/lang/StringsTest.groovy b/src/test/groovy/io/jsonwebtoken/lang/StringsTest.groovy index a06f5d57..def31169 100644 --- a/src/test/groovy/io/jsonwebtoken/lang/StringsTest.groovy +++ b/src/test/groovy/io/jsonwebtoken/lang/StringsTest.groovy @@ -14,4 +14,46 @@ class StringsTest { assertTrue Strings.hasText(" foo "); assertTrue Strings.hasText("foo") } + + @Test + void testClean() { + assertEquals "this is a test", Strings.clean("this is a test") + assertEquals "this is a test", Strings.clean(" this is a test") + assertEquals "this is a test", Strings.clean(" this is a test ") + assertEquals "this is a test", Strings.clean("\nthis is a test \t ") + assertNull Strings.clean(null) + assertNull Strings.clean("") + assertNull Strings.clean("\t") + assertNull Strings.clean(" ") + } + + @Test + void testCleanCharSequence() { + def result = Strings.clean(new StringBuilder("this is a test")) + assertNotNull result + assertEquals "this is a test", result.toString() + + result = Strings.clean(new StringBuilder(" this is a test")) + assertNotNull result + assertEquals "this is a test", result.toString() + + result = Strings.clean(new StringBuilder(" this is a test ")) + assertNotNull result + assertEquals "this is a test", result.toString() + + result = Strings.clean(new StringBuilder("\nthis is a test \t ")) + assertNotNull result + assertEquals "this is a test", result.toString() + + assertNull Strings.clean((StringBuilder) null) + assertNull Strings.clean(new StringBuilder("")) + assertNull Strings.clean(new StringBuilder("\t")) + assertNull Strings.clean(new StringBuilder(" ")) + } + + + @Test + void testTrimWhitespace() { + assertEquals "", Strings.trimWhitespace(" ") + } }