1 /*
2 * Copyright (c) 2005, 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;
27
28 import java.lang.ref.SoftReference;
29 import java.util.Enumeration;
30 import java.util.LinkedList;
31 import java.util.List;
32 import java.util.Locale;
33 import java.util.Map;
34 import java.util.MissingResourceException;
35 import java.util.Set;
36 import java.util.concurrent.ConcurrentHashMap;
37 import java.util.spi.TimeZoneNameProvider;
38 import sun.util.calendar.ZoneInfo;
39 import sun.util.resources.LocaleData;
40 import sun.util.resources.OpenListResourceBundle;
41
42 /**
43 * Utility class that deals with the localized time zone names
44 */
45 public final class TimeZoneNameUtility {
46
47 /**
48 * cache to hold time zone resource bundles. Keyed by Locale
49 */
50 private static ConcurrentHashMap<Locale, SoftReference<OpenListResourceBundle>> cachedBundles =
51 new ConcurrentHashMap<Locale, SoftReference<OpenListResourceBundle>>();
52
53 /**
54 * cache to hold time zone localized strings. Keyed by Locale
55 */
56 private static ConcurrentHashMap<Locale, SoftReference<String[][]>> cachedZoneData =
57 new ConcurrentHashMap<Locale, SoftReference<String[][]>>();
58
59 /**
60 * get time zone localized strings. Enumerate all keys.
61 */
62 public static final String[][] getZoneStrings(Locale locale) {
63 String[][] zones;
64 SoftReference<String[][]> data = cachedZoneData.get(locale);
65
66 if (data == null || ((zones = data.get()) == null)) {
67 zones = loadZoneStrings(locale);
68 data = new SoftReference<String[][]>(zones);
69 cachedZoneData.put(locale, data);
70 }
71
72 return zones;
73 }
74
75 private static final String[][] loadZoneStrings(Locale locale) {
76 List<String[]> zones = new LinkedList<String[]>();
77 OpenListResourceBundle rb = getBundle(locale);
78 Enumeration<String> keys = rb.getKeys();
79 String[] names = null;
80
81 while(keys.hasMoreElements()) {
82 String key = keys.nextElement();
83
84 names = retrieveDisplayNames(rb, key, locale);
85 if (names != null) {
86 zones.add(names);
87 }
88 }
89
90 String[][] zonesArray = new String[zones.size()][];
91 return zones.toArray(zonesArray);
92 }
93
94 /**
95 * Retrieve display names for a time zone ID.
96 */
97 public static final String[] retrieveDisplayNames(String id, Locale locale) {
98 OpenListResourceBundle rb = getBundle(locale);
99 return retrieveDisplayNames(rb, id, locale);
100 }
101
102 private static final String[] retrieveDisplayNames(OpenListResourceBundle rb,
103 String id, Locale locale) {
104 LocaleServiceProviderPool pool =
105 LocaleServiceProviderPool.getPool(TimeZoneNameProvider.class);
106 String[] names = null;
107
108 // Check whether a provider can provide an implementation that's closer
109 // to the requested locale than what the Java runtime itself can provide.
110 if (pool.hasProviders()) {
111 names = pool.getLocalizedObject(
112 TimeZoneNameGetter.INSTANCE,
113 locale, rb, id);
114 }
115
116 if (names == null) {
117 try {
118 names = rb.getStringArray(id);
119 } catch (MissingResourceException mre) {
120 // fall through
121 }
122 }
123
124 return names;
125 }
126
127 private static final OpenListResourceBundle getBundle(Locale locale) {
128 OpenListResourceBundle rb;
129 SoftReference<OpenListResourceBundle> data = cachedBundles.get(locale);
130
131 if (data == null || ((rb = data.get()) == null)) {
132 rb = LocaleData.getTimeZoneNames(locale);
133 data = new SoftReference<OpenListResourceBundle>(rb);
134 cachedBundles.put(locale, data);
135 }
136
137 return rb;
138 }
139
140 /**
141 * Obtains a localized time zone strings from a TimeZoneNameProvider
142 * implementation.
143 */
144 private static class TimeZoneNameGetter
145 implements LocaleServiceProviderPool.LocalizedObjectGetter<TimeZoneNameProvider,
146 String[]>{
147 private static final TimeZoneNameGetter INSTANCE =
148 new TimeZoneNameGetter();
149
150 public String[] getObject(TimeZoneNameProvider timeZoneNameProvider,
151 Locale locale,
152 String requestID,
153 Object... params) {
154 assert params.length == 0;
155 String[] names = null;
156 String queryID = requestID;
157
158 if (queryID.equals("GMT")) {
159 names = buildZoneStrings(timeZoneNameProvider, locale, queryID);
160 } else {
161 Map<String, String> aliases = ZoneInfo.getAliasTable();
162
163 if (aliases != null) {
164 // Check whether this id is an alias, if so,
165 // look for the standard id.
166 if (aliases.containsKey(queryID)) {
167 String prevID = queryID;
168 while ((queryID = aliases.get(queryID)) != null) {
169 prevID = queryID;
170 }
171 queryID = prevID;
172 }
173
174 names = buildZoneStrings(timeZoneNameProvider, locale, queryID);
175
176 if (names == null) {
177 // There may be a case that a standard id has become an
178 // alias. so, check the aliases backward.
179 names = examineAliases(timeZoneNameProvider, locale,
180 queryID, aliases, aliases.entrySet());
215
216 private static String[] buildZoneStrings(TimeZoneNameProvider tznp,
217 Locale locale, String id) {
218 String[] names = new String[5];
219
220 for (int i = 1; i <= 4; i ++) {
221 names[i] = tznp.getDisplayName(id, i>=3, i%2, locale);
222 if (i >= 3 && names[i] == null) {
223 names[i] = names[i-2];
224 }
225 }
226
227 if (names[1] == null) {
228 // this id seems not localized by this provider
229 names = null;
230 }
231
232 return names;
233 }
234 }
235 }
|
1 /*
2 * Copyright (c) 2005, 2012, 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.ref.SoftReference;
29 import java.util.Enumeration;
30 import java.util.LinkedList;
31 import java.util.List;
32 import java.util.Locale;
33 import java.util.Map;
34 import java.util.Set;
35 import java.util.concurrent.ConcurrentHashMap;
36 import java.util.spi.TimeZoneNameProvider;
37 import sun.util.calendar.ZoneInfo;
38 import sun.util.resources.OpenListResourceBundle;
39
40 /**
41 * Utility class that deals with the localized time zone names
42 *
43 * @author Naoto Sato
44 */
45 public final class TimeZoneNameUtility {
46
47 /**
48 * cache to hold time zone resource bundles. Keyed by Locale
49 */
50 private static ConcurrentHashMap<Locale, SoftReference<OpenListResourceBundle>> cachedBundles =
51 new ConcurrentHashMap<>();
52
53 /**
54 * cache to hold time zone localized strings. Keyed by Locale
55 */
56 private static ConcurrentHashMap<Locale, SoftReference<String[][]>> cachedZoneData =
57 new ConcurrentHashMap<>();
58
59 /**
60 * get time zone localized strings. Enumerate all keys.
61 */
62 public static String[][] getZoneStrings(Locale locale) {
63 String[][] zones;
64 SoftReference<String[][]> data = cachedZoneData.get(locale);
65
66 if (data == null || ((zones = data.get()) == null)) {
67 zones = loadZoneStrings(locale);
68 data = new SoftReference<>(zones);
69 cachedZoneData.put(locale, data);
70 }
71
72 return zones;
73 }
74
75 private static String[][] loadZoneStrings(Locale locale) {
76 List<String[]> zones = new LinkedList<>();
77 OpenListResourceBundle rb = getBundle(locale);
78 Enumeration<String> keys = rb.getKeys();
79 String[] names;
80
81 while(keys.hasMoreElements()) {
82 String key = keys.nextElement();
83
84 names = retrieveDisplayNames(rb, key, locale);
85 if (names != null) {
86 zones.add(names);
87 }
88 }
89
90 String[][] zonesArray = new String[zones.size()][];
91 return zones.toArray(zonesArray);
92 }
93
94 /**
95 * Retrieve display names for a time zone ID.
96 */
97 public static String[] retrieveDisplayNames(String id, Locale locale) {
98 OpenListResourceBundle rb = getBundle(locale);
99 return retrieveDisplayNames(rb, id, locale);
100 }
101
102 private static String[] retrieveDisplayNames(OpenListResourceBundle rb,
103 String id, Locale locale) {
104 if (id == null || locale == null) {
105 throw new NullPointerException();
106 }
107
108 LocaleServiceProviderPool pool =
109 LocaleServiceProviderPool.getPool(TimeZoneNameProvider.class);
110 return pool.getLocalizedObject(TimeZoneNameGetter.INSTANCE, locale, id);
111 }
112
113 private static OpenListResourceBundle getBundle(Locale locale) {
114 OpenListResourceBundle rb;
115 SoftReference<OpenListResourceBundle> data = cachedBundles.get(locale);
116
117 if (data == null || ((rb = data.get()) == null)) {
118 rb = LocaleProviderAdapter.forJRE().getLocaleData().getTimeZoneNames(locale);
119 data = new SoftReference<>(rb);
120 cachedBundles.put(locale, data);
121 }
122
123 return rb;
124 }
125
126 /**
127 * Obtains a localized time zone strings from a TimeZoneNameProvider
128 * implementation.
129 */
130 private static class TimeZoneNameGetter
131 implements LocaleServiceProviderPool.LocalizedObjectGetter<TimeZoneNameProvider,
132 String[]>{
133 private static final TimeZoneNameGetter INSTANCE =
134 new TimeZoneNameGetter();
135
136 @Override
137 public String[] getObject(TimeZoneNameProvider timeZoneNameProvider,
138 Locale locale,
139 String requestID,
140 Object... params) {
141 assert params.length == 0;
142 String queryID = requestID;
143
144 // First, try to get names with the request ID
145 String[] names = buildZoneStrings(timeZoneNameProvider, locale, requestID);
146
147 if (names == null) {
148 Map<String, String> aliases = ZoneInfo.getAliasTable();
149
150 if (aliases != null) {
151 // Check whether this id is an alias, if so,
152 // look for the standard id.
153 if (aliases.containsKey(queryID)) {
154 String prevID = queryID;
155 while ((queryID = aliases.get(queryID)) != null) {
156 prevID = queryID;
157 }
158 queryID = prevID;
159 }
160
161 names = buildZoneStrings(timeZoneNameProvider, locale, queryID);
162
163 if (names == null) {
164 // There may be a case that a standard id has become an
165 // alias. so, check the aliases backward.
166 names = examineAliases(timeZoneNameProvider, locale,
167 queryID, aliases, aliases.entrySet());
202
203 private static String[] buildZoneStrings(TimeZoneNameProvider tznp,
204 Locale locale, String id) {
205 String[] names = new String[5];
206
207 for (int i = 1; i <= 4; i ++) {
208 names[i] = tznp.getDisplayName(id, i>=3, i%2, locale);
209 if (i >= 3 && names[i] == null) {
210 names[i] = names[i-2];
211 }
212 }
213
214 if (names[1] == null) {
215 // this id seems not localized by this provider
216 names = null;
217 }
218
219 return names;
220 }
221 }
222
223 // No instantiation
224 private TimeZoneNameUtility() {
225 }
226 }
|