Skip to content

Commit b5b6ae3

Browse files
committed
8245241: Incorrect locale provider preference is not logged
Reviewed-by: joehw, dfuchs
1 parent e3be308 commit b5b6ae3

7 files changed

Lines changed: 111 additions & 114 deletions

File tree

src/java.base/share/classes/sun/util/locale/provider/HostLocaleProviderAdapter.java

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -26,8 +26,8 @@
2626
package sun.util.locale.provider;
2727

2828
import java.lang.reflect.InvocationTargetException;
29-
import java.lang.reflect.Method;
3029
import java.text.DecimalFormat;
30+
import java.util.ServiceConfigurationError;
3131
import java.util.spi.LocaleServiceProvider;
3232

3333
/**
@@ -50,16 +50,20 @@ public LocaleProviderAdapter.Type getAdapterType() {
5050
@SuppressWarnings("unchecked")
5151
protected <P extends LocaleServiceProvider> P findInstalledProvider(final Class<P> c) {
5252
try {
53-
Method getter = HostLocaleProviderAdapterImpl.class.getMethod(
54-
"get" + c.getSimpleName(), (Class<?>[]) null);
55-
return (P)getter.invoke(null, (Object[]) null);
56-
} catch (NoSuchMethodException |
57-
IllegalAccessException |
58-
IllegalArgumentException |
59-
InvocationTargetException ex) {
60-
LocaleServiceProviderPool.config(HostLocaleProviderAdapter.class, ex.toString());
53+
return (P)Class.forName(
54+
"sun.util.locale.provider.HostLocaleProviderAdapterImpl")
55+
.getMethod("get" + c.getSimpleName(), (Class<?>[]) null)
56+
.invoke(null, (Object[]) null);
57+
} catch (ClassNotFoundException |
58+
NoSuchMethodException ex) {
59+
// permissible exceptions as platform may not support host adapter
60+
return null;
61+
} catch (IllegalAccessException |
62+
IllegalArgumentException |
63+
InvocationTargetException ex) {
64+
throw new ServiceConfigurationError(
65+
"Host locale provider cannot be located.", ex);
6166
}
62-
return null;
6367
}
6468

6569
/**

src/java.base/share/classes/sun/util/locale/provider/LocaleProviderAdapter.java

Lines changed: 34 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -25,6 +25,7 @@
2525

2626
package sun.util.locale.provider;
2727

28+
import java.lang.reflect.InvocationTargetException;
2829
import java.text.spi.BreakIteratorProvider;
2930
import java.text.spi.CollatorProvider;
3031
import java.text.spi.DateFormatProvider;
@@ -37,6 +38,7 @@
3738
import java.util.Locale;
3839
import java.util.Map;
3940
import java.util.ResourceBundle;
41+
import java.util.ServiceConfigurationError;
4042
import java.util.Set;
4143
import java.util.concurrent.ConcurrentHashMap;
4244
import java.util.concurrent.ConcurrentMap;
@@ -50,6 +52,8 @@
5052
import sun.text.spi.JavaTimeDateTimePatternProvider;
5153
import sun.util.spi.CalendarProvider;
5254

55+
import static java.lang.System.*;
56+
5357
/**
5458
* The LocaleProviderAdapter abstract class.
5559
*
@@ -60,7 +64,7 @@ public abstract class LocaleProviderAdapter {
6064
/**
6165
* Adapter type.
6266
*/
63-
public static enum Type {
67+
public enum Type {
6468
JRE("sun.util.locale.provider.JRELocaleProviderAdapter", "sun.util.resources", "sun.text.resources"),
6569
CLDR("sun.util.cldr.CLDRLocaleProviderAdapter", "sun.util.resources.cldr", "sun.text.resources.cldr"),
6670
SPI("sun.util.locale.provider.SPILocaleProviderAdapter"),
@@ -71,11 +75,11 @@ public static enum Type {
7175
private final String UTIL_RESOURCES_PACKAGE;
7276
private final String TEXT_RESOURCES_PACKAGE;
7377

74-
private Type(String className) {
78+
Type(String className) {
7579
this(className, null, null);
7680
}
7781

78-
private Type(String className, String util, String text) {
82+
Type(String className, String util, String text) {
7983
CLASSNAME = className;
8084
UTIL_RESOURCES_PACKAGE = util;
8185
TEXT_RESOURCES_PACKAGE = text;
@@ -113,12 +117,13 @@ public String getTextResourcesPackage() {
113117
/**
114118
* Adapter lookup cache.
115119
*/
116-
private static ConcurrentMap<Class<? extends LocaleServiceProvider>, ConcurrentMap<Locale, LocaleProviderAdapter>>
120+
private static final ConcurrentMap<Class<? extends LocaleServiceProvider>, ConcurrentMap<Locale, LocaleProviderAdapter>>
117121
adapterCache = new ConcurrentHashMap<>();
118122

119123
static {
120124
String order = GetPropertyAction.privilegedGetProperty("java.locale.providers");
121-
List<Type> typeList = new ArrayList<>();
125+
ArrayList<Type> typeList = new ArrayList<>();
126+
String invalidTypeMessage = null;
122127

123128
// Check user specified adapter preference
124129
if (order != null && !order.isEmpty()) {
@@ -133,18 +138,17 @@ public String getTextResourcesPackage() {
133138
if (!typeList.contains(aType)) {
134139
typeList.add(aType);
135140
}
136-
} catch (IllegalArgumentException | UnsupportedOperationException e) {
137-
// could be caused by the user specifying wrong
138-
// provider name or format in the system property
139-
LocaleServiceProviderPool.config(LocaleProviderAdapter.class, e.toString());
141+
} catch (IllegalArgumentException e) {
142+
// construct a log message.
143+
invalidTypeMessage = "Invalid locale provider adapter \"" + type + "\" ignored.";
140144
}
141145
}
142146
}
143147

144148
defaultLocaleProviderAdapter = Type.CLDR;
145149
if (!typeList.isEmpty()) {
146150
// bona fide preference exists
147-
if (!(typeList.contains(Type.CLDR) || (typeList.contains(Type.JRE)))) {
151+
if (!(typeList.contains(Type.CLDR) || typeList.contains(Type.JRE))) {
148152
// Append FALLBACK as the last resort when no ResourceBundleBasedAdapter is available.
149153
typeList.add(Type.FALLBACK);
150154
defaultLocaleProviderAdapter = Type.FALLBACK;
@@ -155,6 +159,15 @@ public String getTextResourcesPackage() {
155159
typeList.add(Type.JRE);
156160
}
157161
adapterPreference = Collections.unmodifiableList(typeList);
162+
163+
// Emit logs, if any, after 'adapterPreference' is initialized which is needed
164+
// for logging.
165+
if (invalidTypeMessage != null) {
166+
// could be caused by the user specifying wrong
167+
// provider name or format in the system property
168+
getLogger(LocaleProviderAdapter.class.getCanonicalName())
169+
.log(Logger.Level.INFO, invalidTypeMessage);
170+
}
158171
}
159172

160173
/**
@@ -167,30 +180,25 @@ public static LocaleProviderAdapter forType(Type type) {
167180
case SPI:
168181
case HOST:
169182
case FALLBACK:
170-
LocaleProviderAdapter adapter = null;
171-
LocaleProviderAdapter cached = adapterInstances.get(type);
172-
if (cached == null) {
183+
LocaleProviderAdapter adapter = adapterInstances.get(type);
184+
if (adapter == null) {
173185
try {
174186
// lazily load adapters here
175-
@SuppressWarnings("deprecation")
176-
Object tmp = Class.forName(type.getAdapterClassName()).newInstance();
177-
adapter = (LocaleProviderAdapter)tmp;
178-
cached = adapterInstances.putIfAbsent(type, adapter);
187+
adapter = (LocaleProviderAdapter)Class.forName(type.getAdapterClassName())
188+
.getDeclaredConstructor().newInstance();
189+
LocaleProviderAdapter cached = adapterInstances.putIfAbsent(type, adapter);
179190
if (cached != null) {
180191
adapter = cached;
181192
}
182-
} catch (ClassNotFoundException |
193+
} catch (NoSuchMethodException |
194+
InvocationTargetException |
195+
ClassNotFoundException |
183196
IllegalAccessException |
184197
InstantiationException |
185198
UnsupportedOperationException e) {
186-
LocaleServiceProviderPool.config(LocaleProviderAdapter.class, e.toString());
187-
adapterInstances.putIfAbsent(type, NONEXISTENT_ADAPTER);
188-
if (defaultLocaleProviderAdapter == type) {
189-
defaultLocaleProviderAdapter = Type.FALLBACK;
190-
}
199+
throw new ServiceConfigurationError("Locale provider adapter \"" +
200+
type + "\"cannot be instantiated.", e);
191201
}
192-
} else if (cached != NONEXISTENT_ADAPTER) {
193-
adapter = cached;
194202
}
195203
return adapter;
196204
default:
@@ -440,14 +448,4 @@ public static Locale[] toLocaleArray(Set<String> tags) {
440448
public abstract LocaleResources getLocaleResources(Locale locale);
441449

442450
public abstract Locale[] getAvailableLocales();
443-
444-
private static final LocaleProviderAdapter NONEXISTENT_ADAPTER = new NonExistentAdapter();
445-
private static final class NonExistentAdapter extends FallbackLocaleProviderAdapter {
446-
@Override
447-
public LocaleProviderAdapter.Type getAdapterType() {
448-
return null;
449-
}
450-
451-
private NonExistentAdapter() {};
452-
}
453451
}

src/java.base/share/classes/sun/util/locale/provider/LocaleServiceProviderPool.java

Lines changed: 13 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2005, 2020, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -38,7 +38,6 @@
3838
import java.util.concurrent.ConcurrentHashMap;
3939
import java.util.concurrent.ConcurrentMap;
4040
import java.util.spi.LocaleServiceProvider;
41-
import sun.util.logging.PlatformLogger;
4241

4342
/**
4443
* An instance of this class holds a set of the third party implementations of a particular
@@ -121,11 +120,6 @@ private LocaleServiceProviderPool (final Class<? extends LocaleServiceProvider>
121120
providerClass = c;
122121
}
123122

124-
static void config(Class<? extends Object> caller, String message) {
125-
PlatformLogger logger = PlatformLogger.getLogger(caller.getCanonicalName());
126-
logger.config(message);
127-
}
128-
129123
/**
130124
* Lazy loaded set of available locales.
131125
* Loading all locales is a very long operation.
@@ -282,9 +276,10 @@ private <P extends LocaleServiceProvider, S> S getLocalizedObjectImpl(LocalizedO
282276
if (providersObj != null) {
283277
return providersObj;
284278
} else if (isObjectProvider) {
285-
config(LocaleServiceProviderPool.class,
286-
"A locale sensitive service object provider returned null, " +
287-
"which should not happen. Provider: " + lsp + " Locale: " + locale);
279+
System.getLogger(LocaleServiceProviderPool.class.getCanonicalName())
280+
.log(System.Logger.Level.INFO,
281+
"A locale sensitive service object provider returned null, " +
282+
"which should not happen. Provider: " + lsp + " Locale: " + locale);
288283
}
289284
}
290285
}
@@ -341,9 +336,8 @@ static List<Locale> getLookupLocales(Locale locale) {
341336
// ResourceBundle.Control.getCandidateLocales. The result
342337
// returned by getCandidateLocales are already normalized
343338
// (no extensions) for service look up.
344-
List<Locale> lookupLocales = Control.getNoFallbackControl(Control.FORMAT_DEFAULT)
339+
return Control.getNoFallbackControl(Control.FORMAT_DEFAULT)
345340
.getCandidateLocales("", locale);
346-
return lookupLocales;
347341
}
348342

349343
/**
@@ -370,8 +364,9 @@ static Locale getLookupLocale(Locale locale) {
370364
// should have well-formed fields except
371365
// for ja_JP_JP and th_TH_TH. Therefore,
372366
// it should never enter in this catch clause.
373-
config(LocaleServiceProviderPool.class,
374-
"A locale(" + locale + ") has non-empty extensions, but has illformed fields.");
367+
System.getLogger(LocaleServiceProviderPool.class.getCanonicalName())
368+
.log(System.Logger.Level.INFO,
369+
"A locale(" + locale + ") has non-empty extensions, but has illformed fields.");
375370

376371
// Fallback - script field will be lost.
377372
lookupLocale = new Locale(locale.getLanguage(), locale.getCountry(), locale.getVariant());
@@ -402,9 +397,9 @@ public interface LocalizedObjectGetter<P extends LocaleServiceProvider, S> {
402397
* @param params provider specific params
403398
* @return localized object from the provider
404399
*/
405-
public S getObject(P lsp,
406-
Locale locale,
407-
String key,
408-
Object... params);
400+
S getObject(P lsp,
401+
Locale locale,
402+
String key,
403+
Object... params);
409404
}
410405
}

src/java.base/share/classes/sun/util/locale/provider/SPILocaleProviderAdapter.java

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -43,9 +43,9 @@
4343
import java.util.Arrays;
4444
import java.util.Locale;
4545
import java.util.Map;
46+
import java.util.ServiceConfigurationError;
4647
import java.util.ServiceLoader;
4748
import java.util.concurrent.ConcurrentHashMap;
48-
import java.util.concurrent.ConcurrentMap;
4949
import java.util.spi.CalendarDataProvider;
5050
import java.util.spi.CalendarNameProvider;
5151
import java.util.spi.CurrencyNameProvider;
@@ -72,7 +72,7 @@ public LocaleProviderAdapter.Type getAdapterType() {
7272
@Override
7373
protected <P extends LocaleServiceProvider> P findInstalledProvider(final Class<P> c) {
7474
try {
75-
return AccessController.doPrivileged(new PrivilegedExceptionAction<P>() {
75+
return AccessController.doPrivileged(new PrivilegedExceptionAction<>() {
7676
@Override
7777
@SuppressWarnings(value={"unchecked", "deprecation"})
7878
public P run() {
@@ -91,8 +91,8 @@ public P run() {
9191
} catch (ClassNotFoundException |
9292
InstantiationException |
9393
IllegalAccessException e) {
94-
LocaleServiceProviderPool.config(SPILocaleProviderAdapter.class, e.toString());
95-
return null;
94+
throw new ServiceConfigurationError(
95+
"SPI locale provider cannot be instantiated.", e);
9696
}
9797
}
9898

@@ -102,17 +102,17 @@ public P run() {
102102
}
103103
});
104104
} catch (PrivilegedActionException e) {
105-
LocaleServiceProviderPool.config(SPILocaleProviderAdapter.class, e.toString());
105+
throw new ServiceConfigurationError(
106+
"SPI locale provider cannot be instantiated.", e);
106107
}
107-
return null;
108108
}
109109

110110
/*
111111
* Delegate interface. All the implementations have to have the class name
112112
* following "<provider class name>Delegate" convention.
113113
*/
114114
private interface Delegate<P extends LocaleServiceProvider> {
115-
default public void addImpl(P impl) {
115+
default void addImpl(P impl) {
116116
for (Locale l : impl.getAvailableLocales()) {
117117
getDelegateMap().putIfAbsent(l, impl);
118118
}
@@ -121,7 +121,7 @@ default public void addImpl(P impl) {
121121
/*
122122
* Obtain the real SPI implementation, using locale fallback
123123
*/
124-
default public P getImpl(Locale locale) {
124+
default P getImpl(Locale locale) {
125125
for (Locale l : LocaleServiceProviderPool.getLookupLocales(locale.stripExtensions())) {
126126
P ret = getDelegateMap().get(l);
127127
if (ret != null) {
@@ -131,13 +131,13 @@ default public P getImpl(Locale locale) {
131131
return null;
132132
}
133133

134-
public Map<Locale, P> getDelegateMap();
134+
Map<Locale, P> getDelegateMap();
135135

136-
default public Locale[] getAvailableLocalesDelegate() {
137-
return getDelegateMap().keySet().stream().toArray(Locale[]::new);
136+
default Locale[] getAvailableLocalesDelegate() {
137+
return getDelegateMap().keySet().toArray(new Locale[0]);
138138
}
139139

140-
default public boolean isSupportedLocaleDelegate(Locale locale) {
140+
default boolean isSupportedLocaleDelegate(Locale locale) {
141141
Map<Locale, P> map = getDelegateMap();
142142
Locale override = CalendarDataUtility.findRegionOverride(locale);
143143

0 commit comments

Comments
 (0)