Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.base/share/classes/sun/util/locale/provider/LocaleProviderAdapter.java
41161 views
1
/*
2
* Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation. Oracle designates this
8
* particular file as subject to the "Classpath" exception as provided
9
* by Oracle in the LICENSE file that accompanied this code.
10
*
11
* This code is distributed in the hope that it will be useful, but WITHOUT
12
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
* version 2 for more details (a copy is included in the LICENSE file that
15
* accompanied this code).
16
*
17
* You should have received a copy of the GNU General Public License version
18
* 2 along with this work; if not, write to the Free Software Foundation,
19
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20
*
21
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22
* or visit www.oracle.com if you need additional information or have any
23
* questions.
24
*/
25
26
package sun.util.locale.provider;
27
28
import java.lang.reflect.InvocationTargetException;
29
import java.text.spi.BreakIteratorProvider;
30
import java.text.spi.CollatorProvider;
31
import java.text.spi.DateFormatProvider;
32
import java.text.spi.DateFormatSymbolsProvider;
33
import java.text.spi.DecimalFormatSymbolsProvider;
34
import java.text.spi.NumberFormatProvider;
35
import java.util.ArrayList;
36
import java.util.Collections;
37
import java.util.List;
38
import java.util.Locale;
39
import java.util.Map;
40
import java.util.ResourceBundle;
41
import java.util.ServiceConfigurationError;
42
import java.util.Set;
43
import java.util.concurrent.ConcurrentHashMap;
44
import java.util.concurrent.ConcurrentMap;
45
import java.util.spi.CalendarDataProvider;
46
import java.util.spi.CalendarNameProvider;
47
import java.util.spi.CurrencyNameProvider;
48
import java.util.spi.LocaleNameProvider;
49
import java.util.spi.LocaleServiceProvider;
50
import java.util.spi.TimeZoneNameProvider;
51
import sun.security.action.GetPropertyAction;
52
import sun.text.spi.JavaTimeDateTimePatternProvider;
53
import sun.util.spi.CalendarProvider;
54
55
import static java.lang.System.*;
56
57
/**
58
* The LocaleProviderAdapter abstract class.
59
*
60
* @author Naoto Sato
61
* @author Masayoshi Okutsu
62
*/
63
public abstract class LocaleProviderAdapter {
64
/**
65
* Adapter type.
66
*/
67
public enum Type {
68
JRE("sun.util.locale.provider.JRELocaleProviderAdapter", "sun.util.resources", "sun.text.resources"),
69
CLDR("sun.util.cldr.CLDRLocaleProviderAdapter", "sun.util.resources.cldr", "sun.text.resources.cldr"),
70
SPI("sun.util.locale.provider.SPILocaleProviderAdapter"),
71
HOST("sun.util.locale.provider.HostLocaleProviderAdapter"),
72
FALLBACK("sun.util.locale.provider.FallbackLocaleProviderAdapter", "sun.util.resources", "sun.text.resources");
73
74
private final String CLASSNAME;
75
private final String UTIL_RESOURCES_PACKAGE;
76
private final String TEXT_RESOURCES_PACKAGE;
77
78
Type(String className) {
79
this(className, null, null);
80
}
81
82
Type(String className, String util, String text) {
83
CLASSNAME = className;
84
UTIL_RESOURCES_PACKAGE = util;
85
TEXT_RESOURCES_PACKAGE = text;
86
}
87
88
public String getAdapterClassName() {
89
return CLASSNAME;
90
}
91
92
public String getUtilResourcesPackage() {
93
return UTIL_RESOURCES_PACKAGE;
94
}
95
96
public String getTextResourcesPackage() {
97
return TEXT_RESOURCES_PACKAGE;
98
}
99
}
100
101
/**
102
* LocaleProviderAdapter preference list.
103
*/
104
private static final List<Type> adapterPreference;
105
106
/**
107
* LocaleProviderAdapter instances
108
*/
109
private static final Map<Type, LocaleProviderAdapter> adapterInstances = new ConcurrentHashMap<>();
110
111
/**
112
* Default fallback adapter type, which should return something meaningful in any case.
113
* This is either CLDR or FALLBACK.
114
*/
115
static volatile LocaleProviderAdapter.Type defaultLocaleProviderAdapter;
116
117
/**
118
* Adapter lookup cache.
119
*/
120
private static final ConcurrentMap<Class<? extends LocaleServiceProvider>, ConcurrentMap<Locale, LocaleProviderAdapter>>
121
adapterCache = new ConcurrentHashMap<>();
122
123
static {
124
String order = GetPropertyAction.privilegedGetProperty("java.locale.providers");
125
ArrayList<Type> typeList = new ArrayList<>();
126
String invalidTypeMessage = null;
127
128
// Check user specified adapter preference
129
if (order != null && !order.isEmpty()) {
130
String[] types = order.split(",");
131
for (String type : types) {
132
type = type.trim().toUpperCase(Locale.ROOT);
133
if (type.equals("COMPAT")) {
134
type = "JRE";
135
}
136
try {
137
Type aType = Type.valueOf(type.trim().toUpperCase(Locale.ROOT));
138
if (!typeList.contains(aType)) {
139
typeList.add(aType);
140
}
141
} catch (IllegalArgumentException e) {
142
// construct a log message.
143
invalidTypeMessage = "Invalid locale provider adapter \"" + type + "\" ignored.";
144
}
145
}
146
}
147
148
defaultLocaleProviderAdapter = Type.CLDR;
149
if (!typeList.isEmpty()) {
150
// bona fide preference exists
151
if (!(typeList.contains(Type.CLDR) || typeList.contains(Type.JRE))) {
152
// Append FALLBACK as the last resort when no ResourceBundleBasedAdapter is available.
153
typeList.add(Type.FALLBACK);
154
defaultLocaleProviderAdapter = Type.FALLBACK;
155
}
156
} else {
157
// Default preference list.
158
typeList.add(Type.CLDR);
159
typeList.add(Type.JRE);
160
}
161
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
}
171
}
172
173
/**
174
* Returns the singleton instance for each adapter type
175
*/
176
public static LocaleProviderAdapter forType(Type type) {
177
switch (type) {
178
case JRE:
179
case CLDR:
180
case SPI:
181
case HOST:
182
case FALLBACK:
183
LocaleProviderAdapter adapter = adapterInstances.get(type);
184
if (adapter == null) {
185
try {
186
// lazily load adapters here
187
adapter = (LocaleProviderAdapter)Class.forName(type.getAdapterClassName())
188
.getDeclaredConstructor().newInstance();
189
LocaleProviderAdapter cached = adapterInstances.putIfAbsent(type, adapter);
190
if (cached != null) {
191
adapter = cached;
192
}
193
} catch (NoSuchMethodException |
194
InvocationTargetException |
195
ClassNotFoundException |
196
IllegalAccessException |
197
InstantiationException |
198
UnsupportedOperationException e) {
199
throw new ServiceConfigurationError("Locale provider adapter \"" +
200
type + "\"cannot be instantiated.", e);
201
}
202
}
203
return adapter;
204
default:
205
throw new InternalError("unknown locale data adapter type");
206
}
207
}
208
209
public static LocaleProviderAdapter forJRE() {
210
return forType(Type.JRE);
211
}
212
213
public static LocaleProviderAdapter getResourceBundleBased() {
214
for (Type type : getAdapterPreference()) {
215
if (type == Type.JRE || type == Type.CLDR || type == Type.FALLBACK) {
216
LocaleProviderAdapter adapter = forType(type);
217
if (adapter != null) {
218
return adapter;
219
}
220
}
221
}
222
// Shouldn't happen.
223
throw new InternalError();
224
}
225
226
/**
227
* Returns the preference order of LocaleProviderAdapter.Type
228
*/
229
public static List<Type> getAdapterPreference() {
230
return adapterPreference;
231
}
232
233
/**
234
* Returns a LocaleProviderAdapter for the given locale service provider that
235
* best matches the given locale. This method returns the LocaleProviderAdapter
236
* for JRE if none is found for the given locale.
237
*
238
* @param providerClass the class for the locale service provider
239
* @param locale the desired locale.
240
* @return a LocaleProviderAdapter
241
*/
242
public static LocaleProviderAdapter getAdapter(Class<? extends LocaleServiceProvider> providerClass,
243
Locale locale) {
244
LocaleProviderAdapter adapter;
245
246
// cache lookup
247
ConcurrentMap<Locale, LocaleProviderAdapter> adapterMap = adapterCache.get(providerClass);
248
if (adapterMap != null) {
249
if ((adapter = adapterMap.get(locale)) != null) {
250
return adapter;
251
}
252
} else {
253
adapterMap = new ConcurrentHashMap<>();
254
adapterCache.putIfAbsent(providerClass, adapterMap);
255
}
256
257
// Fast look-up for the given locale
258
adapter = findAdapter(providerClass, locale);
259
if (adapter != null) {
260
adapterMap.putIfAbsent(locale, adapter);
261
return adapter;
262
}
263
264
// Try finding an adapter in the normal candidate locales path of the given locale.
265
List<Locale> lookupLocales = ResourceBundle.Control.getControl(ResourceBundle.Control.FORMAT_DEFAULT)
266
.getCandidateLocales("", locale);
267
for (Locale loc : lookupLocales) {
268
if (loc.equals(locale)) {
269
// We've already done with this loc.
270
continue;
271
}
272
adapter = findAdapter(providerClass, loc);
273
if (adapter != null) {
274
adapterMap.putIfAbsent(locale, adapter);
275
return adapter;
276
}
277
}
278
279
// returns the adapter for FALLBACK as the last resort
280
adapterMap.putIfAbsent(locale, forType(Type.FALLBACK));
281
return forType(Type.FALLBACK);
282
}
283
284
private static LocaleProviderAdapter findAdapter(Class<? extends LocaleServiceProvider> providerClass,
285
Locale locale) {
286
for (Type type : getAdapterPreference()) {
287
LocaleProviderAdapter adapter = forType(type);
288
if (adapter != null) {
289
LocaleServiceProvider provider = adapter.getLocaleServiceProvider(providerClass);
290
if (provider != null) {
291
if (provider.isSupportedLocale(locale)) {
292
return adapter;
293
}
294
}
295
}
296
}
297
return null;
298
}
299
300
/**
301
* A utility method for implementing the default LocaleServiceProvider.isSupportedLocale
302
* for the JRE, CLDR, and FALLBACK adapters.
303
*/
304
public boolean isSupportedProviderLocale(Locale locale, Set<String> langtags) {
305
LocaleProviderAdapter.Type type = getAdapterType();
306
assert type == Type.JRE || type == Type.CLDR || type == Type.FALLBACK;
307
return false;
308
}
309
310
public static Locale[] toLocaleArray(Set<String> tags) {
311
Locale[] locs = new Locale[tags.size() + 1];
312
int index = 0;
313
locs[index++] = Locale.ROOT;
314
for (String tag : tags) {
315
switch (tag) {
316
case "ja-JP-JP":
317
locs[index++] = JRELocaleConstants.JA_JP_JP;
318
break;
319
case "th-TH-TH":
320
locs[index++] = JRELocaleConstants.TH_TH_TH;
321
break;
322
default:
323
locs[index++] = Locale.forLanguageTag(tag);
324
break;
325
}
326
}
327
return locs;
328
}
329
330
/**
331
* Returns the type of this LocaleProviderAdapter
332
*/
333
public abstract LocaleProviderAdapter.Type getAdapterType();
334
335
/**
336
* Getter method for Locale Service Providers.
337
*/
338
public abstract <P extends LocaleServiceProvider> P getLocaleServiceProvider(Class<P> c);
339
340
/**
341
* Returns a BreakIteratorProvider for this LocaleProviderAdapter, or null if no
342
* BreakIteratorProvider is available.
343
*
344
* @return a BreakIteratorProvider
345
*/
346
public abstract BreakIteratorProvider getBreakIteratorProvider();
347
348
/**
349
* Returns a ollatorProvider for this LocaleProviderAdapter, or null if no
350
* ollatorProvider is available.
351
*
352
* @return a ollatorProvider
353
*/
354
public abstract CollatorProvider getCollatorProvider();
355
356
/**
357
* Returns a DateFormatProvider for this LocaleProviderAdapter, or null if no
358
* DateFormatProvider is available.
359
*
360
* @return a DateFormatProvider
361
*/
362
public abstract DateFormatProvider getDateFormatProvider();
363
364
/**
365
* Returns a DateFormatSymbolsProvider for this LocaleProviderAdapter, or null if no
366
* DateFormatSymbolsProvider is available.
367
*
368
* @return a DateFormatSymbolsProvider
369
*/
370
public abstract DateFormatSymbolsProvider getDateFormatSymbolsProvider();
371
372
/**
373
* Returns a DecimalFormatSymbolsProvider for this LocaleProviderAdapter, or null if no
374
* DecimalFormatSymbolsProvider is available.
375
*
376
* @return a DecimalFormatSymbolsProvider
377
*/
378
public abstract DecimalFormatSymbolsProvider getDecimalFormatSymbolsProvider();
379
380
/**
381
* Returns a NumberFormatProvider for this LocaleProviderAdapter, or null if no
382
* NumberFormatProvider is available.
383
*
384
* @return a NumberFormatProvider
385
*/
386
public abstract NumberFormatProvider getNumberFormatProvider();
387
388
/*
389
* Getter methods for java.util.spi.* providers
390
*/
391
392
/**
393
* Returns a CurrencyNameProvider for this LocaleProviderAdapter, or null if no
394
* CurrencyNameProvider is available.
395
*
396
* @return a CurrencyNameProvider
397
*/
398
public abstract CurrencyNameProvider getCurrencyNameProvider();
399
400
/**
401
* Returns a LocaleNameProvider for this LocaleProviderAdapter, or null if no
402
* LocaleNameProvider is available.
403
*
404
* @return a LocaleNameProvider
405
*/
406
public abstract LocaleNameProvider getLocaleNameProvider();
407
408
/**
409
* Returns a TimeZoneNameProvider for this LocaleProviderAdapter, or null if no
410
* TimeZoneNameProvider is available.
411
*
412
* @return a TimeZoneNameProvider
413
*/
414
public abstract TimeZoneNameProvider getTimeZoneNameProvider();
415
416
/**
417
* Returns a CalendarDataProvider for this LocaleProviderAdapter, or null if no
418
* CalendarDataProvider is available.
419
*
420
* @return a CalendarDataProvider
421
*/
422
public abstract CalendarDataProvider getCalendarDataProvider();
423
424
/**
425
* Returns a CalendarNameProvider for this LocaleProviderAdapter, or null if no
426
* CalendarNameProvider is available.
427
*
428
* @return a CalendarNameProvider
429
*/
430
public abstract CalendarNameProvider getCalendarNameProvider();
431
432
/**
433
* Returns a CalendarProvider for this LocaleProviderAdapter, or null if no
434
* CalendarProvider is available.
435
*
436
* @return a CalendarProvider
437
*/
438
public abstract CalendarProvider getCalendarProvider();
439
440
/**
441
* Returns a JavaTimeDateTimePatternProvider for this LocaleProviderAdapter,
442
* or null if no JavaTimeDateTimePatternProvider is available.
443
*
444
* @return a JavaTimeDateTimePatternProvider
445
*/
446
public abstract JavaTimeDateTimePatternProvider getJavaTimeDateTimePatternProvider();
447
448
public abstract LocaleResources getLocaleResources(Locale locale);
449
450
public abstract Locale[] getAvailableLocales();
451
}
452
453