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/JRELocaleProviderAdapter.java
41161 views
1
/*
2
* Copyright (c) 2012, 2021, 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.security.AccessController;
29
import java.security.AccessControlException;
30
import java.security.PrivilegedAction;
31
import java.security.PrivilegedActionException;
32
import java.security.PrivilegedExceptionAction;
33
import java.text.spi.BreakIteratorProvider;
34
import java.text.spi.CollatorProvider;
35
import java.text.spi.DateFormatProvider;
36
import java.text.spi.DateFormatSymbolsProvider;
37
import java.text.spi.DecimalFormatSymbolsProvider;
38
import java.text.spi.NumberFormatProvider;
39
import java.util.Collections;
40
import java.util.HashSet;
41
import java.util.List;
42
import java.util.Locale;
43
import java.util.ResourceBundle;
44
import java.util.ServiceLoader;
45
import java.util.ServiceConfigurationError;
46
import java.util.Set;
47
import java.util.StringTokenizer;
48
import java.util.concurrent.ConcurrentHashMap;
49
import java.util.concurrent.ConcurrentMap;
50
import java.util.spi.CalendarDataProvider;
51
import java.util.spi.CalendarNameProvider;
52
import java.util.spi.CurrencyNameProvider;
53
import java.util.spi.LocaleNameProvider;
54
import java.util.spi.LocaleServiceProvider;
55
import java.util.spi.TimeZoneNameProvider;
56
import sun.text.spi.JavaTimeDateTimePatternProvider;
57
import sun.util.resources.LocaleData;
58
import sun.util.spi.CalendarProvider;
59
60
/**
61
* LocaleProviderAdapter implementation for the legacy JRE locale data.
62
*
63
* @author Naoto Sato
64
* @author Masayoshi Okutsu
65
*/
66
public class JRELocaleProviderAdapter extends LocaleProviderAdapter implements ResourceBundleBasedAdapter {
67
68
private final ConcurrentMap<String, Set<String>> langtagSets
69
= new ConcurrentHashMap<>();
70
71
private final ConcurrentMap<Locale, LocaleResources> localeResourcesMap
72
= new ConcurrentHashMap<>();
73
74
// LocaleData specific to this LocaleProviderAdapter.
75
private volatile LocaleData localeData;
76
77
/**
78
* Returns the type of this LocaleProviderAdapter
79
*/
80
@Override
81
public LocaleProviderAdapter.Type getAdapterType() {
82
return Type.JRE;
83
}
84
85
/**
86
* Getter method for Locale Service Providers
87
*/
88
@Override
89
@SuppressWarnings("unchecked")
90
public <P extends LocaleServiceProvider> P getLocaleServiceProvider(Class<P> c) {
91
switch (c.getSimpleName()) {
92
case "BreakIteratorProvider":
93
return (P) getBreakIteratorProvider();
94
case "CollatorProvider":
95
return (P) getCollatorProvider();
96
case "DateFormatProvider":
97
return (P) getDateFormatProvider();
98
case "DateFormatSymbolsProvider":
99
return (P) getDateFormatSymbolsProvider();
100
case "DecimalFormatSymbolsProvider":
101
return (P) getDecimalFormatSymbolsProvider();
102
case "NumberFormatProvider":
103
return (P) getNumberFormatProvider();
104
case "CurrencyNameProvider":
105
return (P) getCurrencyNameProvider();
106
case "LocaleNameProvider":
107
return (P) getLocaleNameProvider();
108
case "TimeZoneNameProvider":
109
return (P) getTimeZoneNameProvider();
110
case "CalendarDataProvider":
111
return (P) getCalendarDataProvider();
112
case "CalendarNameProvider":
113
return (P) getCalendarNameProvider();
114
case "CalendarProvider":
115
return (P) getCalendarProvider();
116
case "JavaTimeDateTimePatternProvider":
117
return (P) getJavaTimeDateTimePatternProvider();
118
default:
119
throw new InternalError("should not come down here");
120
}
121
}
122
123
private volatile BreakIteratorProvider breakIteratorProvider;
124
private volatile CollatorProvider collatorProvider;
125
private volatile DateFormatProvider dateFormatProvider;
126
private volatile DateFormatSymbolsProvider dateFormatSymbolsProvider;
127
private volatile DecimalFormatSymbolsProvider decimalFormatSymbolsProvider;
128
private volatile NumberFormatProvider numberFormatProvider;
129
130
private volatile CurrencyNameProvider currencyNameProvider;
131
private volatile LocaleNameProvider localeNameProvider;
132
protected volatile TimeZoneNameProvider timeZoneNameProvider;
133
protected volatile CalendarDataProvider calendarDataProvider;
134
protected volatile CalendarNameProvider calendarNameProvider;
135
136
private volatile CalendarProvider calendarProvider;
137
private volatile JavaTimeDateTimePatternProvider javaTimeDateTimePatternProvider;
138
139
/*
140
* Getter methods for java.text.spi.* providers
141
*/
142
@Override
143
public BreakIteratorProvider getBreakIteratorProvider() {
144
if (breakIteratorProvider == null) {
145
@SuppressWarnings("removal")
146
BreakIteratorProvider provider = AccessController.doPrivileged(
147
(PrivilegedAction<BreakIteratorProvider>) () ->
148
new BreakIteratorProviderImpl(
149
getAdapterType(),
150
getLanguageTagSet("FormatData")));
151
152
synchronized (this) {
153
if (breakIteratorProvider == null) {
154
breakIteratorProvider = provider;
155
}
156
}
157
}
158
return breakIteratorProvider;
159
}
160
161
@Override
162
public CollatorProvider getCollatorProvider() {
163
if (collatorProvider == null) {
164
@SuppressWarnings("removal")
165
CollatorProvider provider = AccessController.doPrivileged(
166
(PrivilegedAction<CollatorProvider>) () ->
167
new CollatorProviderImpl(
168
getAdapterType(),
169
getLanguageTagSet("CollationData")));
170
171
synchronized (this) {
172
if (collatorProvider == null) {
173
collatorProvider = provider;
174
}
175
}
176
}
177
return collatorProvider;
178
}
179
180
@Override
181
public DateFormatProvider getDateFormatProvider() {
182
if (dateFormatProvider == null) {
183
@SuppressWarnings("removal")
184
DateFormatProvider provider = AccessController.doPrivileged(
185
(PrivilegedAction<DateFormatProvider>) () ->
186
new DateFormatProviderImpl(
187
getAdapterType(),
188
getLanguageTagSet("FormatData")));
189
190
synchronized (this) {
191
if (dateFormatProvider == null) {
192
dateFormatProvider = provider;
193
}
194
}
195
}
196
return dateFormatProvider;
197
}
198
199
@Override
200
public DateFormatSymbolsProvider getDateFormatSymbolsProvider() {
201
if (dateFormatSymbolsProvider == null) {
202
@SuppressWarnings("removal")
203
DateFormatSymbolsProvider provider = AccessController.doPrivileged(
204
(PrivilegedAction<DateFormatSymbolsProvider>) () ->
205
new DateFormatSymbolsProviderImpl(
206
getAdapterType(),
207
getLanguageTagSet("FormatData")));
208
209
synchronized (this) {
210
if (dateFormatSymbolsProvider == null) {
211
dateFormatSymbolsProvider = provider;
212
}
213
}
214
}
215
return dateFormatSymbolsProvider;
216
}
217
218
@Override
219
public DecimalFormatSymbolsProvider getDecimalFormatSymbolsProvider() {
220
if (decimalFormatSymbolsProvider == null) {
221
@SuppressWarnings("removal")
222
DecimalFormatSymbolsProvider provider = AccessController.doPrivileged(
223
(PrivilegedAction<DecimalFormatSymbolsProvider>) () ->
224
new DecimalFormatSymbolsProviderImpl(
225
getAdapterType(),
226
getLanguageTagSet("FormatData")));
227
228
synchronized (this) {
229
if (decimalFormatSymbolsProvider == null) {
230
decimalFormatSymbolsProvider = provider;
231
}
232
}
233
}
234
return decimalFormatSymbolsProvider;
235
}
236
237
@Override
238
public NumberFormatProvider getNumberFormatProvider() {
239
if (numberFormatProvider == null) {
240
@SuppressWarnings("removal")
241
NumberFormatProvider provider = AccessController.doPrivileged(
242
(PrivilegedAction<NumberFormatProvider>) () ->
243
new NumberFormatProviderImpl(
244
getAdapterType(),
245
getLanguageTagSet("FormatData")));
246
247
synchronized (this) {
248
if (numberFormatProvider == null) {
249
numberFormatProvider = provider;
250
}
251
}
252
}
253
return numberFormatProvider;
254
}
255
256
/**
257
* Getter methods for java.util.spi.* providers
258
*/
259
@Override
260
public CurrencyNameProvider getCurrencyNameProvider() {
261
if (currencyNameProvider == null) {
262
@SuppressWarnings("removal")
263
CurrencyNameProvider provider = AccessController.doPrivileged(
264
(PrivilegedAction<CurrencyNameProvider>) () ->
265
new CurrencyNameProviderImpl(
266
getAdapterType(),
267
getLanguageTagSet("CurrencyNames")));
268
269
synchronized (this) {
270
if (currencyNameProvider == null) {
271
currencyNameProvider = provider;
272
}
273
}
274
}
275
return currencyNameProvider;
276
}
277
278
@Override
279
public LocaleNameProvider getLocaleNameProvider() {
280
if (localeNameProvider == null) {
281
@SuppressWarnings("removal")
282
LocaleNameProvider provider = AccessController.doPrivileged(
283
(PrivilegedAction<LocaleNameProvider>) () ->
284
new LocaleNameProviderImpl(
285
getAdapterType(),
286
getLanguageTagSet("LocaleNames")));
287
288
synchronized (this) {
289
if (localeNameProvider == null) {
290
localeNameProvider = provider;
291
}
292
}
293
}
294
return localeNameProvider;
295
}
296
297
@Override
298
public TimeZoneNameProvider getTimeZoneNameProvider() {
299
if (timeZoneNameProvider == null) {
300
@SuppressWarnings("removal")
301
TimeZoneNameProvider provider = AccessController.doPrivileged(
302
(PrivilegedAction<TimeZoneNameProvider>) () ->
303
new TimeZoneNameProviderImpl(
304
getAdapterType(),
305
getLanguageTagSet("TimeZoneNames")));
306
307
synchronized (this) {
308
if (timeZoneNameProvider == null) {
309
timeZoneNameProvider = provider;
310
}
311
}
312
}
313
return timeZoneNameProvider;
314
}
315
316
@Override
317
public CalendarDataProvider getCalendarDataProvider() {
318
if (calendarDataProvider == null) {
319
@SuppressWarnings("removal")
320
CalendarDataProvider provider = AccessController.doPrivileged(
321
(PrivilegedAction<CalendarDataProvider>) () ->
322
new CalendarDataProviderImpl(
323
getAdapterType(),
324
getLanguageTagSet("CalendarData")));
325
326
synchronized (this) {
327
if (calendarDataProvider == null) {
328
calendarDataProvider = provider;
329
}
330
}
331
}
332
return calendarDataProvider;
333
}
334
335
@Override
336
public CalendarNameProvider getCalendarNameProvider() {
337
if (calendarNameProvider == null) {
338
@SuppressWarnings("removal")
339
CalendarNameProvider provider = AccessController.doPrivileged(
340
(PrivilegedAction<CalendarNameProvider>) () ->
341
new CalendarNameProviderImpl(
342
getAdapterType(),
343
getLanguageTagSet("FormatData")));
344
345
synchronized (this) {
346
if (calendarNameProvider == null) {
347
calendarNameProvider = provider;
348
}
349
}
350
}
351
return calendarNameProvider;
352
}
353
354
/**
355
* Getter methods for sun.util.spi.* providers
356
*/
357
@Override
358
public CalendarProvider getCalendarProvider() {
359
if (calendarProvider == null) {
360
@SuppressWarnings("removal")
361
CalendarProvider provider = AccessController.doPrivileged(
362
(PrivilegedAction<CalendarProvider>) () ->
363
new CalendarProviderImpl(
364
getAdapterType(),
365
getLanguageTagSet("CalendarData")));
366
367
synchronized (this) {
368
if (calendarProvider == null) {
369
calendarProvider = provider;
370
}
371
}
372
}
373
return calendarProvider;
374
}
375
376
/**
377
* Getter methods for sun.text.spi.JavaTimeDateTimePatternProvider provider
378
*/
379
@Override
380
public JavaTimeDateTimePatternProvider getJavaTimeDateTimePatternProvider() {
381
if (javaTimeDateTimePatternProvider == null) {
382
@SuppressWarnings("removal")
383
JavaTimeDateTimePatternProvider provider = AccessController.doPrivileged(
384
(PrivilegedAction<JavaTimeDateTimePatternProvider>) ()
385
-> new JavaTimeDateTimePatternImpl(
386
getAdapterType(),
387
getLanguageTagSet("FormatData")));
388
389
synchronized (this) {
390
if (javaTimeDateTimePatternProvider == null) {
391
javaTimeDateTimePatternProvider = provider;
392
}
393
}
394
}
395
return javaTimeDateTimePatternProvider;
396
}
397
398
@Override
399
public LocaleResources getLocaleResources(Locale locale) {
400
LocaleResources lr = localeResourcesMap.get(locale);
401
if (lr == null) {
402
lr = new LocaleResources(this, locale);
403
LocaleResources lrc = localeResourcesMap.putIfAbsent(locale, lr);
404
if (lrc != null) {
405
lr = lrc;
406
}
407
}
408
return lr;
409
}
410
411
// ResourceBundleBasedAdapter method implementation
412
413
@Override
414
public LocaleData getLocaleData() {
415
if (localeData == null) {
416
synchronized (this) {
417
if (localeData == null) {
418
localeData = new LocaleData(getAdapterType());
419
}
420
}
421
}
422
return localeData;
423
}
424
425
@Override
426
public List<Locale> getCandidateLocales(String baseName, Locale locale) {
427
return ResourceBundle.Control
428
.getNoFallbackControl(ResourceBundle.Control.FORMAT_DEFAULT)
429
.getCandidateLocales(baseName, locale);
430
}
431
432
/**
433
* Returns a list of the installed locales. Currently, this simply returns
434
* the list of locales for which a sun.text.resources.FormatData bundle
435
* exists. This bundle family happens to be the one with the broadest
436
* locale coverage in the JRE.
437
*/
438
@Override
439
public Locale[] getAvailableLocales() {
440
return AvailableJRELocales.localeList.clone();
441
}
442
443
public Set<String> getLanguageTagSet(String category) {
444
Set<String> tagset = langtagSets.get(category);
445
if (tagset == null) {
446
tagset = createLanguageTagSet(category);
447
Set<String> ts = langtagSets.putIfAbsent(category, tagset);
448
if (ts != null) {
449
tagset = ts;
450
}
451
}
452
return tagset;
453
}
454
455
protected Set<String> createLanguageTagSet(String category) {
456
String supportedLocaleString = createSupportedLocaleString(category);
457
if (supportedLocaleString == null) {
458
return Collections.emptySet();
459
}
460
StringTokenizer tokens = new StringTokenizer(supportedLocaleString);
461
Set<String> tagset = new HashSet<>((tokens.countTokens() * 4 + 2) / 3);
462
while (tokens.hasMoreTokens()) {
463
tagset.add(tokens.nextToken());
464
}
465
466
return tagset;
467
}
468
469
private static String createSupportedLocaleString(String category) {
470
// Directly call Base tags, as we know it's in the base module.
471
String supportedLocaleString = BaseLocaleDataMetaInfo.getSupportedLocaleString(category);
472
473
// Use ServiceLoader to dynamically acquire installed locales' tags.
474
try {
475
@SuppressWarnings("removal")
476
String nonBaseTags = AccessController.doPrivileged((PrivilegedExceptionAction<String>) () -> {
477
StringBuilder tags = new StringBuilder();
478
for (LocaleDataMetaInfo ldmi :
479
ServiceLoader.loadInstalled(LocaleDataMetaInfo.class)) {
480
if (ldmi.getType() == LocaleProviderAdapter.Type.JRE) {
481
String t = ldmi.availableLanguageTags(category);
482
if (t != null) {
483
if (tags.length() > 0) {
484
tags.append(' ');
485
}
486
tags.append(t);
487
}
488
}
489
}
490
return tags.toString();
491
});
492
493
if (nonBaseTags != null) {
494
supportedLocaleString += " " + nonBaseTags;
495
}
496
} catch (PrivilegedActionException pae) {
497
throw new InternalError(pae.getCause());
498
}
499
500
return supportedLocaleString;
501
}
502
503
/**
504
* Lazy load available locales.
505
*/
506
private static class AvailableJRELocales {
507
private static final Locale[] localeList = createAvailableLocales();
508
private AvailableJRELocales() {}
509
}
510
511
private static Locale[] createAvailableLocales() {
512
/*
513
* Gets the locale string list from LocaleDataMetaInfo classes and then
514
* contructs the Locale array and a set of language tags based on the
515
* locale string returned above.
516
*/
517
String supportedLocaleString = createSupportedLocaleString("AvailableLocales");
518
519
if (supportedLocaleString.isEmpty()) {
520
throw new InternalError("No available locales for JRE");
521
}
522
523
StringTokenizer localeStringTokenizer = new StringTokenizer(supportedLocaleString);
524
525
int length = localeStringTokenizer.countTokens();
526
Locale[] locales = new Locale[length + 1];
527
locales[0] = Locale.ROOT;
528
for (int i = 1; i <= length; i++) {
529
String currentToken = localeStringTokenizer.nextToken();
530
switch (currentToken) {
531
case "ja-JP-JP":
532
locales[i] = JRELocaleConstants.JA_JP_JP;
533
break;
534
case "no-NO-NY":
535
locales[i] = JRELocaleConstants.NO_NO_NY;
536
break;
537
case "th-TH-TH":
538
locales[i] = JRELocaleConstants.TH_TH_TH;
539
break;
540
default:
541
locales[i] = Locale.forLanguageTag(currentToken);
542
}
543
}
544
return locales;
545
}
546
547
@Override
548
public boolean isSupportedProviderLocale(Locale locale, Set<String> langtags) {
549
if (Locale.ROOT.equals(locale)) {
550
return true;
551
}
552
553
locale = locale.stripExtensions();
554
if (langtags.contains(locale.toLanguageTag())) {
555
return true;
556
}
557
558
String oldname = locale.toString().replace('_', '-');
559
return langtags.contains(oldname) ||
560
"ja-JP-JP".equals(oldname) ||
561
"th-TH-TH".equals(oldname) ||
562
"no-NO-NY".equals(oldname);
563
}
564
}
565
566