mirror of
https://github.com/apache/commons-lang.git
synced 2025-02-08 11:05:09 +00:00
Add and use LocaleUtils.toLocale(Locale) to avoid NPEs and use the
default locale when an input locale is null.
This commit is contained in:
parent
b5de0ef280
commit
c9e825e823
@ -81,6 +81,7 @@ The <action> type attribute can be add,update,fix,remove.
|
|||||||
<action issue="LANG-1596" type="update" dev="aherbert" due-to="Richard Eckart de Castilho">ArrayUtils.toPrimitive(Object) does not support boolean and other types #607.</action>
|
<action issue="LANG-1596" type="update" dev="aherbert" due-to="Richard Eckart de Castilho">ArrayUtils.toPrimitive(Object) does not support boolean and other types #607.</action>
|
||||||
<action type="add" dev="ggregory" due-to="Gary Gregory">Add fluent-style ArrayUtils.sort(Object[]).</action>
|
<action type="add" dev="ggregory" due-to="Gary Gregory">Add fluent-style ArrayUtils.sort(Object[]).</action>
|
||||||
<action type="add" dev="ggregory" due-to="Gary Gregory">Add fluent-style ArrayUtils.sort(Object[], Comparable).</action>
|
<action type="add" dev="ggregory" due-to="Gary Gregory">Add fluent-style ArrayUtils.sort(Object[], Comparable).</action>
|
||||||
|
<action type="add" dev="ggregory" due-to="Gary Gregory">Add and use LocaleUtils.toLocale(Locale) to avoid NPEs.</action>
|
||||||
<!-- UPDATES -->
|
<!-- UPDATES -->
|
||||||
<action type="update" dev="ggregory" due-to="Gary Gregory">Enable Dependabot #587.</action>
|
<action type="update" dev="ggregory" due-to="Gary Gregory">Enable Dependabot #587.</action>
|
||||||
<action type="update" dev="chtompki">Bump junit-jupiter from 5.6.2 to 5.7.0.</action>
|
<action type="update" dev="chtompki">Bump junit-jupiter from 5.6.2 to 5.7.0.</action>
|
||||||
|
@ -276,7 +276,17 @@ private static Locale parseLocale(final String str) {
|
|||||||
throw new IllegalArgumentException("Invalid locale format: " + str);
|
throw new IllegalArgumentException("Invalid locale format: " + str);
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------
|
/**
|
||||||
|
* Returns the given locale if non-{@code null}, otherwise {@link Locale#getDefault()}.
|
||||||
|
*
|
||||||
|
* @param locale a locale or {@code null}.
|
||||||
|
* @return the given locale if non-{@code null}, otherwise {@link Locale#getDefault()}.
|
||||||
|
* @since 3.12
|
||||||
|
*/
|
||||||
|
public static Locale toLocale(final Locale locale) {
|
||||||
|
return locale != null ? locale : Locale.getDefault();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>Converts a String to a Locale.</p>
|
* <p>Converts a String to a Locale.</p>
|
||||||
*
|
*
|
||||||
|
@ -5406,7 +5406,7 @@ public static String lowerCase(final String str, final Locale locale) {
|
|||||||
if (str == null) {
|
if (str == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return str.toLowerCase(locale);
|
return str.toLowerCase(LocaleUtils.toLocale(locale));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int[] matches(final CharSequence first, final CharSequence second) {
|
private static int[] matches(final CharSequence first, final CharSequence second) {
|
||||||
@ -9414,7 +9414,7 @@ public static String upperCase(final String str, final Locale locale) {
|
|||||||
if (str == null) {
|
if (str == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return str.toUpperCase(locale);
|
return str.toUpperCase(LocaleUtils.toLocale(locale));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.LocaleUtils;
|
||||||
import org.apache.commons.lang3.ObjectUtils;
|
import org.apache.commons.lang3.ObjectUtils;
|
||||||
import org.apache.commons.lang3.Validate;
|
import org.apache.commons.lang3.Validate;
|
||||||
|
|
||||||
@ -118,14 +119,14 @@ public ExtendedMessageFormat(final String pattern, final Map<String, ? extends F
|
|||||||
/**
|
/**
|
||||||
* Create a new ExtendedMessageFormat.
|
* Create a new ExtendedMessageFormat.
|
||||||
*
|
*
|
||||||
* @param pattern the pattern to use, not null
|
* @param pattern the pattern to use, not null.
|
||||||
* @param locale the locale to use, not null
|
* @param locale the locale to use.
|
||||||
* @param registry the registry of format factories, may be null
|
* @param registry the registry of format factories, may be null.
|
||||||
* @throws IllegalArgumentException in case of a bad pattern.
|
* @throws IllegalArgumentException in case of a bad pattern.
|
||||||
*/
|
*/
|
||||||
public ExtendedMessageFormat(final String pattern, final Locale locale, final Map<String, ? extends FormatFactory> registry) {
|
public ExtendedMessageFormat(final String pattern, final Locale locale, final Map<String, ? extends FormatFactory> registry) {
|
||||||
super(DUMMY_PATTERN);
|
super(DUMMY_PATTERN);
|
||||||
setLocale(locale);
|
setLocale(LocaleUtils.toLocale(locale));
|
||||||
this.registry = registry;
|
this.registry = registry;
|
||||||
applyPattern(pattern);
|
applyPattern(pattern);
|
||||||
}
|
}
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
import java.util.TimeZone;
|
import java.util.TimeZone;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.LocaleUtils;
|
||||||
import org.apache.commons.lang3.Validate;
|
import org.apache.commons.lang3.Validate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -367,7 +368,7 @@ private static Date parseDateWithLeniency(final String str, final Locale locale,
|
|||||||
}
|
}
|
||||||
|
|
||||||
final TimeZone tz = TimeZone.getDefault();
|
final TimeZone tz = TimeZone.getDefault();
|
||||||
final Locale lcl = locale == null ? Locale.getDefault() : locale;
|
final Locale lcl = LocaleUtils.toLocale(locale);
|
||||||
final ParsePosition pos = new ParsePosition(0);
|
final ParsePosition pos = new ParsePosition(0);
|
||||||
final Calendar calendar = Calendar.getInstance(tz, lcl);
|
final Calendar calendar = Calendar.getInstance(tz, lcl);
|
||||||
calendar.setLenient(lenient);
|
calendar.setLenient(lenient);
|
||||||
|
@ -39,6 +39,8 @@
|
|||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.LocaleUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>FastDateParser is a fast and thread-safe version of
|
* <p>FastDateParser is a fast and thread-safe version of
|
||||||
* {@link java.text.SimpleDateFormat}.</p>
|
* {@link java.text.SimpleDateFormat}.</p>
|
||||||
@ -125,15 +127,15 @@ protected FastDateParser(final String pattern, final TimeZone timeZone, final Lo
|
|||||||
protected FastDateParser(final String pattern, final TimeZone timeZone, final Locale locale, final Date centuryStart) {
|
protected FastDateParser(final String pattern, final TimeZone timeZone, final Locale locale, final Date centuryStart) {
|
||||||
this.pattern = pattern;
|
this.pattern = pattern;
|
||||||
this.timeZone = timeZone;
|
this.timeZone = timeZone;
|
||||||
this.locale = locale;
|
this.locale = LocaleUtils.toLocale(locale);
|
||||||
|
|
||||||
final Calendar definingCalendar = Calendar.getInstance(timeZone, locale);
|
final Calendar definingCalendar = Calendar.getInstance(timeZone, this.locale);
|
||||||
|
|
||||||
int centuryStartYear;
|
int centuryStartYear;
|
||||||
if (centuryStart!=null) {
|
if (centuryStart!=null) {
|
||||||
definingCalendar.setTime(centuryStart);
|
definingCalendar.setTime(centuryStart);
|
||||||
centuryStartYear = definingCalendar.get(Calendar.YEAR);
|
centuryStartYear = definingCalendar.get(Calendar.YEAR);
|
||||||
} else if (locale.equals(JAPANESE_IMPERIAL)) {
|
} else if (this.locale.equals(JAPANESE_IMPERIAL)) {
|
||||||
centuryStartYear = 0;
|
centuryStartYear = 0;
|
||||||
} else {
|
} else {
|
||||||
// from 80 years ago to 20 years from now
|
// from 80 years ago to 20 years from now
|
||||||
@ -458,9 +460,9 @@ private static StringBuilder simpleQuote(final StringBuilder sb, final String va
|
|||||||
* @param regex The regular expression to build
|
* @param regex The regular expression to build
|
||||||
* @return The map of string display names to field values
|
* @return The map of string display names to field values
|
||||||
*/
|
*/
|
||||||
private static Map<String, Integer> appendDisplayNames(final Calendar cal, final Locale locale, final int field, final StringBuilder regex) {
|
private static Map<String, Integer> appendDisplayNames(final Calendar cal, Locale locale, final int field, final StringBuilder regex) {
|
||||||
final Map<String, Integer> values = new HashMap<>();
|
final Map<String, Integer> values = new HashMap<>();
|
||||||
|
locale = LocaleUtils.toLocale(locale);
|
||||||
final Map<String, Integer> displayNames = cal.getDisplayNames(field, Calendar.ALL_STYLES, locale);
|
final Map<String, Integer> displayNames = cal.getDisplayNames(field, Calendar.ALL_STYLES, locale);
|
||||||
final TreeSet<String> sorted = new TreeSet<>(LONGER_FIRST_LOWERCASE);
|
final TreeSet<String> sorted = new TreeSet<>(LONGER_FIRST_LOWERCASE);
|
||||||
for (final Map.Entry<String, Integer> displayName : displayNames.entrySet()) {
|
for (final Map.Entry<String, Integer> displayName : displayNames.entrySet()) {
|
||||||
@ -697,7 +699,7 @@ private static class CaseInsensitiveTextStrategy extends PatternStrategy {
|
|||||||
*/
|
*/
|
||||||
CaseInsensitiveTextStrategy(final int field, final Calendar definingCalendar, final Locale locale) {
|
CaseInsensitiveTextStrategy(final int field, final Calendar definingCalendar, final Locale locale) {
|
||||||
this.field = field;
|
this.field = field;
|
||||||
this.locale = locale;
|
this.locale = LocaleUtils.toLocale(locale);
|
||||||
|
|
||||||
final StringBuilder regex = new StringBuilder();
|
final StringBuilder regex = new StringBuilder();
|
||||||
regex.append("((?iu)");
|
regex.append("((?iu)");
|
||||||
@ -837,7 +839,7 @@ private static class TzInfo {
|
|||||||
* @param locale The Locale
|
* @param locale The Locale
|
||||||
*/
|
*/
|
||||||
TimeZoneStrategy(final Locale locale) {
|
TimeZoneStrategy(final Locale locale) {
|
||||||
this.locale = locale;
|
this.locale = LocaleUtils.toLocale(locale);
|
||||||
|
|
||||||
final StringBuilder sb = new StringBuilder();
|
final StringBuilder sb = new StringBuilder();
|
||||||
sb.append("((?iu)" + RFC_822_TIME_ZONE + "|" + GMT_OPTION );
|
sb.append("((?iu)" + RFC_822_TIME_ZONE + "|" + GMT_OPTION );
|
||||||
|
@ -31,6 +31,7 @@
|
|||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.ConcurrentMap;
|
import java.util.concurrent.ConcurrentMap;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.LocaleUtils;
|
||||||
import org.apache.commons.lang3.exception.ExceptionUtils;
|
import org.apache.commons.lang3.exception.ExceptionUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -150,7 +151,7 @@ public class FastDatePrinter implements DatePrinter, Serializable {
|
|||||||
protected FastDatePrinter(final String pattern, final TimeZone timeZone, final Locale locale) {
|
protected FastDatePrinter(final String pattern, final TimeZone timeZone, final Locale locale) {
|
||||||
mPattern = pattern;
|
mPattern = pattern;
|
||||||
mTimeZone = timeZone;
|
mTimeZone = timeZone;
|
||||||
mLocale = locale;
|
mLocale = LocaleUtils.toLocale(locale);
|
||||||
|
|
||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
@ -1342,7 +1343,7 @@ private static class TimeZoneNameRule implements Rule {
|
|||||||
* @param style the style
|
* @param style the style
|
||||||
*/
|
*/
|
||||||
TimeZoneNameRule(final TimeZone timeZone, final Locale locale, final int style) {
|
TimeZoneNameRule(final TimeZone timeZone, final Locale locale, final int style) {
|
||||||
mLocale = locale;
|
mLocale = LocaleUtils.toLocale(locale);
|
||||||
mStyle = style;
|
mStyle = style;
|
||||||
|
|
||||||
mStandard = getTimeZoneDisplay(timeZone, false, style, locale);
|
mStandard = getTimeZoneDisplay(timeZone, false, style, locale);
|
||||||
@ -1539,7 +1540,7 @@ private static class TimeZoneDisplayKey {
|
|||||||
} else {
|
} else {
|
||||||
mStyle = style;
|
mStyle = style;
|
||||||
}
|
}
|
||||||
mLocale = locale;
|
mLocale = LocaleUtils.toLocale(locale);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.ConcurrentMap;
|
import java.util.concurrent.ConcurrentMap;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.LocaleUtils;
|
||||||
import org.apache.commons.lang3.Validate;
|
import org.apache.commons.lang3.Validate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -73,9 +74,7 @@ public F getInstance(final String pattern, TimeZone timeZone, Locale locale) {
|
|||||||
if (timeZone == null) {
|
if (timeZone == null) {
|
||||||
timeZone = TimeZone.getDefault();
|
timeZone = TimeZone.getDefault();
|
||||||
}
|
}
|
||||||
if (locale == null) {
|
locale = LocaleUtils.toLocale(locale);
|
||||||
locale = Locale.getDefault();
|
|
||||||
}
|
|
||||||
final MultipartKey key = new MultipartKey(pattern, timeZone, locale);
|
final MultipartKey key = new MultipartKey(pattern, timeZone, locale);
|
||||||
F format = cInstanceCache.get(key);
|
F format = cInstanceCache.get(key);
|
||||||
if (format == null) {
|
if (format == null) {
|
||||||
@ -118,9 +117,7 @@ public F getInstance(final String pattern, TimeZone timeZone, Locale locale) {
|
|||||||
*/
|
*/
|
||||||
// This must remain private, see LANG-884
|
// This must remain private, see LANG-884
|
||||||
private F getDateTimeInstance(final Integer dateStyle, final Integer timeStyle, final TimeZone timeZone, Locale locale) {
|
private F getDateTimeInstance(final Integer dateStyle, final Integer timeStyle, final TimeZone timeZone, Locale locale) {
|
||||||
if (locale == null) {
|
locale = LocaleUtils.toLocale(locale);
|
||||||
locale = Locale.getDefault();
|
|
||||||
}
|
|
||||||
final String pattern = getPatternForStyle(dateStyle, timeStyle, locale);
|
final String pattern = getPatternForStyle(dateStyle, timeStyle, locale);
|
||||||
return getInstance(pattern, timeZone, locale);
|
return getInstance(pattern, timeZone, locale);
|
||||||
}
|
}
|
||||||
@ -188,18 +185,19 @@ F getTimeInstance(final int timeStyle, final TimeZone timeZone, final Locale loc
|
|||||||
*/
|
*/
|
||||||
// package protected, for access from test code; do not make public or protected
|
// package protected, for access from test code; do not make public or protected
|
||||||
static String getPatternForStyle(final Integer dateStyle, final Integer timeStyle, final Locale locale) {
|
static String getPatternForStyle(final Integer dateStyle, final Integer timeStyle, final Locale locale) {
|
||||||
final MultipartKey key = new MultipartKey(dateStyle, timeStyle, locale);
|
final Locale safeLocale = LocaleUtils.toLocale(locale);
|
||||||
|
final MultipartKey key = new MultipartKey(dateStyle, timeStyle, safeLocale);
|
||||||
|
|
||||||
String pattern = cDateTimeInstanceCache.get(key);
|
String pattern = cDateTimeInstanceCache.get(key);
|
||||||
if (pattern == null) {
|
if (pattern == null) {
|
||||||
try {
|
try {
|
||||||
DateFormat formatter;
|
DateFormat formatter;
|
||||||
if (dateStyle == null) {
|
if (dateStyle == null) {
|
||||||
formatter = DateFormat.getTimeInstance(timeStyle.intValue(), locale);
|
formatter = DateFormat.getTimeInstance(timeStyle.intValue(), safeLocale);
|
||||||
} else if (timeStyle == null) {
|
} else if (timeStyle == null) {
|
||||||
formatter = DateFormat.getDateInstance(dateStyle.intValue(), locale);
|
formatter = DateFormat.getDateInstance(dateStyle.intValue(), safeLocale);
|
||||||
} else {
|
} else {
|
||||||
formatter = DateFormat.getDateTimeInstance(dateStyle.intValue(), timeStyle.intValue(), locale);
|
formatter = DateFormat.getDateTimeInstance(dateStyle.intValue(), timeStyle.intValue(), safeLocale);
|
||||||
}
|
}
|
||||||
pattern = ((SimpleDateFormat) formatter).toPattern();
|
pattern = ((SimpleDateFormat) formatter).toPattern();
|
||||||
final String previous = cDateTimeInstanceCache.putIfAbsent(key, pattern);
|
final String previous = cDateTimeInstanceCache.putIfAbsent(key, pattern);
|
||||||
@ -210,13 +208,12 @@ static String getPatternForStyle(final Integer dateStyle, final Integer timeStyl
|
|||||||
pattern = previous;
|
pattern = previous;
|
||||||
}
|
}
|
||||||
} catch (final ClassCastException ex) {
|
} catch (final ClassCastException ex) {
|
||||||
throw new IllegalArgumentException("No date time pattern for locale: " + locale);
|
throw new IllegalArgumentException("No date time pattern for locale: " + safeLocale);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return pattern;
|
return pattern;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------
|
|
||||||
/**
|
/**
|
||||||
* <p>Helper class to hold multi-part Map keys</p>
|
* <p>Helper class to hold multi-part Map keys</p>
|
||||||
*/
|
*/
|
||||||
|
@ -123,11 +123,30 @@ private static void assertValidToLocale(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test toLocale() method.
|
* Test toLocale(Locale) method.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testToLocale_Locale_defaults() {
|
||||||
|
assertNull(LocaleUtils.toLocale((String) null));
|
||||||
|
assertEquals(Locale.getDefault(), LocaleUtils.toLocale((Locale) null));
|
||||||
|
assertEquals(Locale.getDefault(), LocaleUtils.toLocale(Locale.getDefault()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test toLocale(Locale) method.
|
||||||
|
*/
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("java.util.Locale#getAvailableLocales")
|
||||||
|
public void testToLocales(final Locale actualLocale) {
|
||||||
|
assertEquals(actualLocale, LocaleUtils.toLocale(actualLocale));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test toLocale(String) method.
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testToLocale_1Part() {
|
public void testToLocale_1Part() {
|
||||||
assertNull(LocaleUtils.toLocale(null));
|
assertNull(LocaleUtils.toLocale((String) null));
|
||||||
|
|
||||||
assertValidToLocale("us");
|
assertValidToLocale("us");
|
||||||
assertValidToLocale("fr");
|
assertValidToLocale("fr");
|
||||||
@ -524,11 +543,11 @@ public void testLang865() {
|
|||||||
|
|
||||||
@ParameterizedTest
|
@ParameterizedTest
|
||||||
@MethodSource("java.util.Locale#getAvailableLocales")
|
@MethodSource("java.util.Locale#getAvailableLocales")
|
||||||
public void testParseAllLocales(final Locale l) {
|
public void testParseAllLocales(final Locale actualLocale) {
|
||||||
// Check if it's possible to recreate the Locale using just the standard constructor
|
// Check if it's possible to recreate the Locale using just the standard constructor
|
||||||
final Locale locale = new Locale(l.getLanguage(), l.getCountry(), l.getVariant());
|
final Locale locale = new Locale(actualLocale.getLanguage(), actualLocale.getCountry(), actualLocale.getVariant());
|
||||||
if (l.equals(locale)) { // it is possible for LocaleUtils.toLocale to handle these Locales
|
if (actualLocale.equals(locale)) { // it is possible for LocaleUtils.toLocale to handle these Locales
|
||||||
final String str = l.toString();
|
final String str = actualLocale.toString();
|
||||||
// Look for the script/extension suffix
|
// Look for the script/extension suffix
|
||||||
int suff = str.indexOf("_#");
|
int suff = str.indexOf("_#");
|
||||||
if (suff == - 1) {
|
if (suff == - 1) {
|
||||||
@ -541,7 +560,7 @@ public void testParseAllLocales(final Locale l) {
|
|||||||
localeStr = str.substring(0, suff);
|
localeStr = str.substring(0, suff);
|
||||||
}
|
}
|
||||||
final Locale loc = LocaleUtils.toLocale(localeStr);
|
final Locale loc = LocaleUtils.toLocale(localeStr);
|
||||||
assertEquals(l, loc);
|
assertEquals(actualLocale, loc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user