Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/sun/util/locale/provider/LocaleProviderAdapter.java
38918 views
1
/*
2
* Copyright (c) 2012, 2015, 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.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.ResourceBundle;
40
import java.util.Set;
41
import java.util.concurrent.ConcurrentHashMap;
42
import java.util.concurrent.ConcurrentMap;
43
import java.util.spi.CalendarDataProvider;
44
import java.util.spi.CalendarNameProvider;
45
import java.util.spi.CurrencyNameProvider;
46
import java.util.spi.LocaleNameProvider;
47
import java.util.spi.LocaleServiceProvider;
48
import java.util.spi.TimeZoneNameProvider;
49
import sun.util.cldr.CLDRLocaleProviderAdapter;
50
import sun.util.spi.CalendarProvider;
51
52
/**
53
* The LocaleProviderAdapter abstract class.
54
*
55
* @author Naoto Sato
56
* @author Masayoshi Okutsu
57
*/
58
public abstract class LocaleProviderAdapter {
59
/**
60
* Adapter type.
61
*/
62
public static enum Type {
63
JRE("sun.util.resources", "sun.text.resources"),
64
CLDR("sun.util.resources.cldr", "sun.text.resources.cldr"),
65
SPI,
66
HOST,
67
FALLBACK("sun.util.resources", "sun.text.resources");
68
69
private final String UTIL_RESOURCES_PACKAGE;
70
private final String TEXT_RESOURCES_PACKAGE;
71
72
private Type() {
73
this(null, null);
74
}
75
76
private Type(String util, String text) {
77
UTIL_RESOURCES_PACKAGE = util;
78
TEXT_RESOURCES_PACKAGE = text;
79
}
80
81
public String getUtilResourcesPackage() {
82
return UTIL_RESOURCES_PACKAGE;
83
}
84
85
public String getTextResourcesPackage() {
86
return TEXT_RESOURCES_PACKAGE;
87
}
88
}
89
90
/**
91
* LocaleProviderAdapter preference list. The default list is intended
92
* to behave the same manner in JDK7.
93
*/
94
private static final List<Type> adapterPreference;
95
96
/**
97
* JRE Locale Data Adapter instance
98
*/
99
private static LocaleProviderAdapter jreLocaleProviderAdapter = new JRELocaleProviderAdapter();
100
101
/**
102
* SPI Locale Data Adapter instance
103
*/
104
private static LocaleProviderAdapter spiLocaleProviderAdapter = new SPILocaleProviderAdapter();
105
106
/**
107
* CLDR Locale Data Adapter instance, if any.
108
*/
109
private static LocaleProviderAdapter cldrLocaleProviderAdapter = null;
110
111
/**
112
* HOST Locale Data Adapter instance, if any.
113
*/
114
private static LocaleProviderAdapter hostLocaleProviderAdapter = null;
115
116
/**
117
* FALLBACK Locale Data Adapter instance. It's basically the same with JRE, but only kicks
118
* in for the root locale.
119
*/
120
private static LocaleProviderAdapter fallbackLocaleProviderAdapter = null;
121
122
/**
123
* Default fallback adapter type, which should return something meaningful in any case.
124
* This is either JRE or FALLBACK.
125
*/
126
static LocaleProviderAdapter.Type defaultLocaleProviderAdapter = null;
127
128
/**
129
* Adapter lookup cache.
130
*/
131
private static ConcurrentMap<Class<? extends LocaleServiceProvider>, ConcurrentMap<Locale, LocaleProviderAdapter>>
132
adapterCache = new ConcurrentHashMap<>();
133
134
static {
135
String order = AccessController.doPrivileged(
136
new sun.security.action.GetPropertyAction("java.locale.providers"));
137
List<Type> typeList = new ArrayList<>();
138
139
// Check user specified adapter preference
140
if (order != null && order.length() != 0) {
141
String[] types = order.split(",");
142
for (String type : types) {
143
try {
144
Type aType = Type.valueOf(type.trim().toUpperCase(Locale.ROOT));
145
146
// load adapter if necessary
147
switch (aType) {
148
case CLDR:
149
if (cldrLocaleProviderAdapter == null) {
150
cldrLocaleProviderAdapter = new CLDRLocaleProviderAdapter();
151
}
152
break;
153
case HOST:
154
if (hostLocaleProviderAdapter == null) {
155
hostLocaleProviderAdapter = new HostLocaleProviderAdapter();
156
}
157
break;
158
}
159
if (!typeList.contains(aType)) {
160
typeList.add(aType);
161
}
162
} catch (IllegalArgumentException | UnsupportedOperationException e) {
163
// could be caused by the user specifying wrong
164
// provider name or format in the system property
165
LocaleServiceProviderPool.config(LocaleProviderAdapter.class, e.toString());
166
}
167
}
168
}
169
170
if (!typeList.isEmpty()) {
171
if (!typeList.contains(Type.JRE)) {
172
// Append FALLBACK as the last resort.
173
fallbackLocaleProviderAdapter = new FallbackLocaleProviderAdapter();
174
typeList.add(Type.FALLBACK);
175
defaultLocaleProviderAdapter = Type.FALLBACK;
176
} else {
177
defaultLocaleProviderAdapter = Type.JRE;
178
}
179
} else {
180
// Default preference list
181
typeList.add(Type.JRE);
182
typeList.add(Type.SPI);
183
defaultLocaleProviderAdapter = Type.JRE;
184
}
185
186
adapterPreference = Collections.unmodifiableList(typeList);
187
}
188
189
/**
190
* Returns the singleton instance for each adapter type
191
*/
192
public static LocaleProviderAdapter forType(Type type) {
193
switch (type) {
194
case JRE:
195
return jreLocaleProviderAdapter;
196
case CLDR:
197
return cldrLocaleProviderAdapter;
198
case SPI:
199
return spiLocaleProviderAdapter;
200
case HOST:
201
return hostLocaleProviderAdapter;
202
case FALLBACK:
203
return fallbackLocaleProviderAdapter;
204
default:
205
throw new InternalError("unknown locale data adapter type");
206
}
207
}
208
209
public static LocaleProviderAdapter forJRE() {
210
return jreLocaleProviderAdapter;
211
}
212
213
public static LocaleProviderAdapter getResourceBundleBased() {
214
for (Type type : getAdapterPreference()) {
215
if (type == Type.JRE || type == Type.CLDR || type == Type.FALLBACK) {
216
return forType(type);
217
}
218
}
219
// Shouldn't happen.
220
throw new InternalError();
221
}
222
/**
223
* Returns the preference order of LocaleProviderAdapter.Type
224
*/
225
public static List<Type> getAdapterPreference() {
226
return adapterPreference;
227
}
228
229
/**
230
* Returns a LocaleProviderAdapter for the given locale service provider that
231
* best matches the given locale. This method returns the LocaleProviderAdapter
232
* for JRE if none is found for the given locale.
233
*
234
* @param providerClass the class for the locale service provider
235
* @param locale the desired locale.
236
* @return a LocaleProviderAdapter
237
*/
238
public static LocaleProviderAdapter getAdapter(Class<? extends LocaleServiceProvider> providerClass,
239
Locale locale) {
240
LocaleProviderAdapter adapter;
241
242
// cache lookup
243
ConcurrentMap<Locale, LocaleProviderAdapter> adapterMap = adapterCache.get(providerClass);
244
if (adapterMap != null) {
245
if ((adapter = adapterMap.get(locale)) != null) {
246
return adapter;
247
}
248
} else {
249
adapterMap = new ConcurrentHashMap<>();
250
adapterCache.putIfAbsent(providerClass, adapterMap);
251
}
252
253
// Fast look-up for the given locale
254
adapter = findAdapter(providerClass, locale);
255
if (adapter != null) {
256
adapterMap.putIfAbsent(locale, adapter);
257
return adapter;
258
}
259
260
// Try finding an adapter in the normal candidate locales path of the given locale.
261
List<Locale> lookupLocales = ResourceBundle.Control.getControl(ResourceBundle.Control.FORMAT_DEFAULT)
262
.getCandidateLocales("", locale);
263
for (Locale loc : lookupLocales) {
264
if (loc.equals(locale)) {
265
// We've already done with this loc.
266
continue;
267
}
268
adapter = findAdapter(providerClass, loc);
269
if (adapter != null) {
270
adapterMap.putIfAbsent(locale, adapter);
271
return adapter;
272
}
273
}
274
275
// returns the adapter for FALLBACK as the last resort
276
adapterMap.putIfAbsent(locale, fallbackLocaleProviderAdapter);
277
return fallbackLocaleProviderAdapter;
278
}
279
280
private static LocaleProviderAdapter findAdapter(Class<? extends LocaleServiceProvider> providerClass,
281
Locale locale) {
282
for (Type type : getAdapterPreference()) {
283
LocaleProviderAdapter adapter = forType(type);
284
LocaleServiceProvider provider = adapter.getLocaleServiceProvider(providerClass);
285
if (provider != null) {
286
if (provider.isSupportedLocale(locale)) {
287
return adapter;
288
}
289
}
290
}
291
return null;
292
}
293
294
/**
295
* A utility method for implementing the default LocaleServiceProvider.isSupportedLocale
296
* for the JRE, CLDR, and FALLBACK adapters.
297
*/
298
public static boolean isSupportedLocale(Locale locale, LocaleProviderAdapter.Type type, Set<String> langtags) {
299
assert type == Type.JRE || type == Type.CLDR || type == Type.FALLBACK;
300
if (Locale.ROOT.equals(locale)) {
301
return true;
302
}
303
304
if (type == Type.FALLBACK) {
305
// no other locales except ROOT are supported for FALLBACK
306
return false;
307
}
308
309
locale = locale.stripExtensions();
310
if (langtags.contains(locale.toLanguageTag())) {
311
return true;
312
}
313
if (type == Type.JRE) {
314
String oldname = locale.toString().replace('_', '-');
315
return langtags.contains(oldname) ||
316
"ja-JP-JP".equals(oldname) ||
317
"th-TH-TH".equals(oldname) ||
318
"no-NO-NY".equals(oldname);
319
}
320
return false;
321
}
322
323
public static Locale[] toLocaleArray(Set<String> tags) {
324
Locale[] locs = new Locale[tags.size() + 1];
325
int index = 0;
326
locs[index++] = Locale.ROOT;
327
for (String tag : tags) {
328
switch (tag) {
329
case "ja-JP-JP":
330
locs[index++] = JRELocaleConstants.JA_JP_JP;
331
break;
332
case "th-TH-TH":
333
locs[index++] = JRELocaleConstants.TH_TH_TH;
334
break;
335
default:
336
locs[index++] = Locale.forLanguageTag(tag);
337
break;
338
}
339
}
340
return locs;
341
}
342
343
/**
344
* Returns the type of this LocaleProviderAdapter
345
*/
346
public abstract LocaleProviderAdapter.Type getAdapterType();
347
348
/**
349
* Getter method for Locale Service Providers.
350
*/
351
public abstract <P extends LocaleServiceProvider> P getLocaleServiceProvider(Class<P> c);
352
353
/**
354
* Returns a BreakIteratorProvider for this LocaleProviderAdapter, or null if no
355
* BreakIteratorProvider is available.
356
*
357
* @return a BreakIteratorProvider
358
*/
359
public abstract BreakIteratorProvider getBreakIteratorProvider();
360
361
/**
362
* Returns a ollatorProvider for this LocaleProviderAdapter, or null if no
363
* ollatorProvider is available.
364
*
365
* @return a ollatorProvider
366
*/
367
public abstract CollatorProvider getCollatorProvider();
368
369
/**
370
* Returns a DateFormatProvider for this LocaleProviderAdapter, or null if no
371
* DateFormatProvider is available.
372
*
373
* @return a DateFormatProvider
374
*/
375
public abstract DateFormatProvider getDateFormatProvider();
376
377
/**
378
* Returns a DateFormatSymbolsProvider for this LocaleProviderAdapter, or null if no
379
* DateFormatSymbolsProvider is available.
380
*
381
* @return a DateFormatSymbolsProvider
382
*/
383
public abstract DateFormatSymbolsProvider getDateFormatSymbolsProvider();
384
385
/**
386
* Returns a DecimalFormatSymbolsProvider for this LocaleProviderAdapter, or null if no
387
* DecimalFormatSymbolsProvider is available.
388
*
389
* @return a DecimalFormatSymbolsProvider
390
*/
391
public abstract DecimalFormatSymbolsProvider getDecimalFormatSymbolsProvider();
392
393
/**
394
* Returns a NumberFormatProvider for this LocaleProviderAdapter, or null if no
395
* NumberFormatProvider is available.
396
*
397
* @return a NumberFormatProvider
398
*/
399
public abstract NumberFormatProvider getNumberFormatProvider();
400
401
/*
402
* Getter methods for java.util.spi.* providers
403
*/
404
405
/**
406
* Returns a CurrencyNameProvider for this LocaleProviderAdapter, or null if no
407
* CurrencyNameProvider is available.
408
*
409
* @return a CurrencyNameProvider
410
*/
411
public abstract CurrencyNameProvider getCurrencyNameProvider();
412
413
/**
414
* Returns a LocaleNameProvider for this LocaleProviderAdapter, or null if no
415
* LocaleNameProvider is available.
416
*
417
* @return a LocaleNameProvider
418
*/
419
public abstract LocaleNameProvider getLocaleNameProvider();
420
421
/**
422
* Returns a TimeZoneNameProvider for this LocaleProviderAdapter, or null if no
423
* TimeZoneNameProvider is available.
424
*
425
* @return a TimeZoneNameProvider
426
*/
427
public abstract TimeZoneNameProvider getTimeZoneNameProvider();
428
429
/**
430
* Returns a CalendarDataProvider for this LocaleProviderAdapter, or null if no
431
* CalendarDataProvider is available.
432
*
433
* @return a CalendarDataProvider
434
*/
435
public abstract CalendarDataProvider getCalendarDataProvider();
436
437
/**
438
* Returns a CalendarNameProvider for this LocaleProviderAdapter, or null if no
439
* CalendarNameProvider is available.
440
*
441
* @return a CalendarNameProvider
442
*/
443
public abstract CalendarNameProvider getCalendarNameProvider();
444
445
/**
446
* Returns a CalendarProvider for this LocaleProviderAdapter, or null if no
447
* CalendarProvider is available.
448
*
449
* @return a CalendarProvider
450
*/
451
public abstract CalendarProvider getCalendarProvider();
452
453
public abstract LocaleResources getLocaleResources(Locale locale);
454
455
public abstract Locale[] getAvailableLocales();
456
}
457
458