From 4d46f014fb8ee44386feb5fec52509f35d0e36ea Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Thu, 3 Jan 2013 06:19:52 +0000 Subject: [PATCH] [LANG-865] LocaleUtils.toLocale does not parse strings starting with an underscore. git-svn-id: https://svn.apache.org/repos/asf/commons/proper/lang/trunk@1428174 13f79535-47bb-0310-9956-ffa450edef68 --- src/changes/changes.xml | 1 + .../org/apache/commons/lang3/LocaleUtils.java | 61 +++++++++++++------ .../apache/commons/lang3/LocaleUtilsTest.java | 46 ++++++++++++++ 3 files changed, 90 insertions(+), 18 deletions(-) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 4263d9ac7..a8a376932 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -22,6 +22,7 @@ + LocaleUtils.toLocale does not parse strings starting with an underscore StrBuilder should support StringBuilder as an input parameter StringEscapeUtils.escapeJava() and escapeEcmaScript() do not output the escaped surrogate pairs that are Java parsable StringIndexOutOfBoundsException in CharSequenceTranslator diff --git a/src/main/java/org/apache/commons/lang3/LocaleUtils.java b/src/main/java/org/apache/commons/lang3/LocaleUtils.java index 7568f2c66..a7a60511b 100644 --- a/src/main/java/org/apache/commons/lang3/LocaleUtils.java +++ b/src/main/java/org/apache/commons/lang3/LocaleUtils.java @@ -85,41 +85,66 @@ public LocaleUtils() { * @return a Locale, null if null input * @throws IllegalArgumentException if the string is an invalid format */ - public static Locale toLocale(String str) { + public static Locale toLocale(final String str) { if (str == null) { return null; } - int len = str.length(); - if (len != 2 && len != 5 && len < 7) { + final int len = str.length(); + if (len < 2) { throw new IllegalArgumentException("Invalid locale format: " + str); } - char ch0 = str.charAt(0); - char ch1 = str.charAt(1); - if (ch0 < 'a' || ch0 > 'z' || ch1 < 'a' || ch1 > 'z') { - throw new IllegalArgumentException("Invalid locale format: " + str); - } - if (len == 2) { - return new Locale(str, ""); + final char ch0 = str.charAt(0); + if (ch0 == '_') { + if (len < 3) { + throw new IllegalArgumentException("Invalid locale format: " + str); + } + final char ch1 = str.charAt(1); + final char ch2 = str.charAt(2); + if (!Character.isUpperCase(ch1) || !Character.isUpperCase(ch2)) { + throw new IllegalArgumentException("Invalid locale format: " + str); + } + if (len == 3) { + return new Locale("", str.substring(1, 3)); + } + if (len < 5) { + throw new IllegalArgumentException("Invalid locale format: " + str); + } + if (str.charAt(3) != '_') { + throw new IllegalArgumentException("Invalid locale format: " + str); + } + return new Locale("", str.substring(1, 3), str.substring(4)); } else { + final char ch1 = str.charAt(1); + if (!Character.isLowerCase(ch0) || !Character.isLowerCase(ch1)) { + throw new IllegalArgumentException("Invalid locale format: " + str); + } + if (len == 2) { + return new Locale(str); + } + if (len < 5) { + throw new IllegalArgumentException("Invalid locale format: " + str); + } if (str.charAt(2) != '_') { throw new IllegalArgumentException("Invalid locale format: " + str); } - char ch3 = str.charAt(3); + final char ch3 = str.charAt(3); if (ch3 == '_') { return new Locale(str.substring(0, 2), "", str.substring(4)); } - char ch4 = str.charAt(4); - if (ch3 < 'A' || ch3 > 'Z' || ch4 < 'A' || ch4 > 'Z') { + final char ch4 = str.charAt(4); + if (!Character.isUpperCase(ch3) || !Character.isUpperCase(ch4)) { throw new IllegalArgumentException("Invalid locale format: " + str); } if (len == 5) { return new Locale(str.substring(0, 2), str.substring(3, 5)); - } else { - if (str.charAt(5) != '_') { - throw new IllegalArgumentException("Invalid locale format: " + str); - } - return new Locale(str.substring(0, 2), str.substring(3, 5), str.substring(6)); } + if (len < 7) { + throw new IllegalArgumentException("Invalid locale format: " + str); + } + if (str.charAt(5) != '_') { + throw new IllegalArgumentException("Invalid locale format: " + str); + } + return new Locale(str.substring(0, 2), str.substring(3, 5), str.substring(6)); } } diff --git a/src/test/java/org/apache/commons/lang3/LocaleUtilsTest.java b/src/test/java/org/apache/commons/lang3/LocaleUtilsTest.java index 84e3b66d4..b30b3e327 100644 --- a/src/test/java/org/apache/commons/lang3/LocaleUtilsTest.java +++ b/src/test/java/org/apache/commons/lang3/LocaleUtilsTest.java @@ -493,7 +493,53 @@ private static void assertUnmodifiableCollection(Collection coll) { */ @Test public void testLang328() { + assertValidToLocale("fr__P", "fr", "", "P"); assertValidToLocale("fr__POSIX", "fr", "", "POSIX"); } + /** + * Tests #LANG-865, strings starting with an underscore. + */ + @Test + public void testLang865() { + assertValidToLocale("_GB", "", "GB", ""); + assertValidToLocale("_GB_P", "", "GB", "P"); + assertValidToLocale("_GB_POSIX", "", "GB", "POSIX"); + try { + LocaleUtils.toLocale("_G"); + fail("Must be at least 3 chars if starts with underscore"); + } catch (final IllegalArgumentException iae) { + } + try { + LocaleUtils.toLocale("_Gb"); + fail("Must be uppercase if starts with underscore"); + } catch (final IllegalArgumentException iae) { + } + try { + LocaleUtils.toLocale("_gB"); + fail("Must be uppercase if starts with underscore"); + } catch (final IllegalArgumentException iae) { + } + try { + LocaleUtils.toLocale("_1B"); + fail("Must be letter if starts with underscore"); + } catch (final IllegalArgumentException iae) { + } + try { + LocaleUtils.toLocale("_G1"); + fail("Must be letter if starts with underscore"); + } catch (final IllegalArgumentException iae) { + } + try { + LocaleUtils.toLocale("_GB_"); + fail("Must be at least 5 chars if starts with underscore"); + } catch (final IllegalArgumentException iae) { + } + try { + LocaleUtils.toLocale("_GBAP"); + fail("Must have underscore after the country if starts with underscore and is at least 5 chars"); + } catch (final IllegalArgumentException iae) { + } + } + }