1 /* 2 * Copyright (c) 1996, 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 /* 27 * (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved 28 * (C) Copyright IBM Corp. 1996 - 1998 - All Rights Reserved 29 * 30 * The original version of this source code and documentation 31 * is copyrighted and owned by Taligent, Inc., a wholly-owned 32 * subsidiary of IBM. These materials are provided under terms 33 * of a License Agreement between Taligent and Sun. This technology 34 * is protected by multiple US and International patents. 35 * 36 * This notice and attribution to Taligent may not be removed. 37 * Taligent is a registered trademark of Taligent, Inc. 38 * 39 */ 40 41 package sun.util.resources; 42 43 import java.security.AccessController; 44 import java.security.PrivilegedAction; 45 import java.util.Iterator; 46 import java.util.List; 47 import java.util.Locale; 48 import java.util.ResourceBundle; 49 import sun.util.locale.provider.LocaleDataMetaInfo; 50 import sun.util.locale.provider.LocaleProviderAdapter; 51 import static sun.util.locale.provider.LocaleProviderAdapter.Type.JRE; 52 53 /** 54 * Provides information about and access to resource bundles in the 55 * sun.text.resources and sun.util.resources packages or in their corresponding 56 * packages for CLDR. 57 * 58 * @author Asmus Freytag 59 * @author Mark Davis 60 */ 61 62 public class LocaleData { 63 private final LocaleProviderAdapter.Type type; 64 65 public LocaleData(LocaleProviderAdapter.Type type) { 66 this.type = type; 67 } 68 69 /** 70 * Gets a calendar data resource bundle, using privileges 71 * to allow accessing a sun.* package. 72 */ 73 public ResourceBundle getCalendarData(Locale locale) { 74 return getBundle(type.getUtilResourcesPackage() + ".CalendarData", locale); 75 } 76 77 /** 78 * Gets a currency names resource bundle, using privileges 79 * to allow accessing a sun.* package. 80 */ 81 public OpenListResourceBundle getCurrencyNames(Locale locale) { 82 return (OpenListResourceBundle) getBundle(type.getUtilResourcesPackage() + ".CurrencyNames", locale); 83 } 84 85 /** 86 * Gets a locale names resource bundle, using privileges 87 * to allow accessing a sun.* package. 88 */ 89 public OpenListResourceBundle getLocaleNames(Locale locale) { 90 return (OpenListResourceBundle) getBundle(type.getUtilResourcesPackage() + ".LocaleNames", locale); 91 } 92 93 /** 94 * Gets a time zone names resource bundle, using privileges 95 * to allow accessing a sun.* package. 96 */ 97 public TimeZoneNamesBundle getTimeZoneNames(Locale locale) { 98 return (TimeZoneNamesBundle) getBundle(type.getUtilResourcesPackage() + ".TimeZoneNames", locale); 99 } 100 101 /** 102 * Gets a break iterator info resource bundle, using privileges 103 * to allow accessing a sun.* package. 104 */ 105 public ResourceBundle getBreakIteratorInfo(Locale locale) { 106 return getBundle(type.getTextResourcesPackage() + ".BreakIteratorInfo", locale); 107 } 108 109 /** 110 * Gets a collation data resource bundle, using privileges 111 * to allow accessing a sun.* package. 112 */ 113 public ResourceBundle getCollationData(Locale locale) { 114 return getBundle(type.getTextResourcesPackage() + ".CollationData", locale); 115 } 116 117 /** 118 * Gets a date format data resource bundle, using privileges 119 * to allow accessing a sun.* package. 120 */ 121 public ResourceBundle getDateFormatData(Locale locale) { 122 return getBundle(type.getTextResourcesPackage() + ".FormatData", locale); 123 } 124 125 /** 126 * Gets a number format data resource bundle, using privileges 127 * to allow accessing a sun.* package. 128 */ 129 public ResourceBundle getNumberFormatData(Locale locale) { 130 return getBundle(type.getTextResourcesPackage() + ".FormatData", locale); 131 } 132 133 public static ResourceBundle getBundle(final String baseName, final Locale locale) { 134 return AccessController.doPrivileged(new PrivilegedAction<ResourceBundle>() { 135 @Override 136 public ResourceBundle run() { 137 return ResourceBundle. 138 getBundle(baseName, locale, 139 LocaleDataResourceBundleControl.getRBControlInstance()); 140 } 141 }); 142 } 143 144 private static class LocaleDataResourceBundleControl extends ResourceBundle.Control { 145 /* Singlton instance of ResourceBundle.Control. */ 146 private static LocaleDataResourceBundleControl rbControlInstance = 147 new LocaleDataResourceBundleControl(); 148 149 public static LocaleDataResourceBundleControl getRBControlInstance() { 150 return rbControlInstance; 151 } 152 153 /* 154 * This method overrides the default implementation to search 155 * from a prebaked locale string list to determin the candidate 156 * locale list. 157 * 158 * @param baseName the resource bundle base name. 159 * locale the requested locale for the resource bundle. 160 * @returns a list of candidate locales to search from. 161 * @exception NullPointerException if baseName or locale is null. 162 */ 163 @Override 164 public List<Locale> getCandidateLocales(String baseName, Locale locale) { 165 List<Locale> candidates = super.getCandidateLocales(baseName, locale); 166 /* Get the locale string list from LocaleDataMetaInfo class. */ 167 String localeString = LocaleDataMetaInfo.getSupportedLocaleString(baseName); 168 169 if (localeString != null && localeString.length() != 0) { 170 for (Iterator<Locale> l = candidates.iterator(); l.hasNext();) { 171 Locale loc = l.next(); 172 String lstr; 173 if (loc.getScript().length() > 0) { 174 lstr = loc.toLanguageTag().replace('-', '_'); 175 } else { 176 lstr = loc.toString(); 177 int idx = lstr.indexOf("_#"); 178 if (idx >= 0) { 179 lstr = lstr.substring(0, idx); 180 } 181 } 182 /* Every locale string in the locale string list returned from 183 the above getSupportedLocaleString is enclosed 184 within two white spaces so that we could check some locale 185 such as "en". 186 */ 187 if (lstr.length() != 0 && localeString.indexOf(" " + lstr + " ") == -1) { 188 l.remove(); 189 } 190 } 191 } 192 // Force fallback to Locale.ENGLISH for CLDR time zone names support 193 if (locale.getLanguage() != "en" 194 && baseName.contains(CLDR) && baseName.endsWith("TimeZoneNames")) { 195 candidates.add(candidates.size() - 1, Locale.ENGLISH); 196 } 197 return candidates; 198 } 199 200 /* 201 * Overrides "getFallbackLocale" to return null so 202 * that the fallback locale will be null. 203 * @param baseName the resource bundle base name. 204 * locale the requested locale for the resource bundle. 205 * @return null for the fallback locale. 206 * @exception NullPointerException if baseName or locale is null. 207 */ 208 @Override 209 public Locale getFallbackLocale(String baseName, Locale locale) { 210 if (baseName == null || locale == null) { 211 throw new NullPointerException(); 212 } 213 return null; 214 } 215 216 private static final String CLDR = ".cldr"; 217 218 /** 219 * Changes baseName to its per-language package name and 220 * calls the super class implementation. For example, 221 * if the baseName is "sun.text.resources.FormatData" and locale is ja_JP, 222 * the baseName is changed to "sun.text.resources.ja.FormatData". If 223 * baseName contains "cldr", such as "sun.text.resources.cldr.FormatData", 224 * the name is changed to "sun.text.resources.cldr.jp.FormatData". 225 */ 226 @Override 227 public String toBundleName(String baseName, Locale locale) { 228 String newBaseName = baseName; 229 String lang = locale.getLanguage(); 230 if (lang.length() > 0) { 231 if (baseName.startsWith(JRE.getUtilResourcesPackage()) 232 || baseName.startsWith(JRE.getTextResourcesPackage())) { 233 // Assume the lengths are the same. 234 assert JRE.getUtilResourcesPackage().length() 235 == JRE.getTextResourcesPackage().length(); 236 int index = JRE.getUtilResourcesPackage().length(); 237 if (baseName.indexOf(CLDR, index) > 0) { 238 index += CLDR.length(); 239 } 240 newBaseName = baseName.substring(0, index + 1) + lang 241 + baseName.substring(index); 242 } 243 } 244 return super.toBundleName(newBaseName, locale); 245 } 246 247 } 248 }