1. /*
  2. * @(#)LocaleData.java 1.26 01/11/29
  3. *
  4. * Copyright 2002 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. /*
  8. * @(#)LocaleData.java 1.26 01/11/29
  9. *
  10. * (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved
  11. * (C) Copyright IBM Corp. 1996 - 1998 - All Rights Reserved
  12. *
  13. * Portions copyright (c) 1996-1998 Sun Microsystems, Inc.
  14. * All Rights Reserved.
  15. *
  16. * The original version of this source code and documentation
  17. * is copyrighted and owned by Taligent, Inc., a wholly-owned
  18. * subsidiary of IBM. These materials are provided under terms
  19. * of a License Agreement between Taligent and Sun. This technology
  20. * is protected by multiple US and International patents.
  21. *
  22. * This notice and attribution to Taligent may not be removed.
  23. * Taligent is a registered trademark of Taligent, Inc.
  24. *
  25. * Permission to use, copy, modify, and distribute this software
  26. * and its documentation for NON-COMMERCIAL purposes and without
  27. * fee is hereby granted provided that this copyright notice
  28. * appears in all copies. Please refer to the file "copyright.html"
  29. * for further important copyright and licensing information.
  30. *
  31. * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
  32. * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
  33. * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
  34. * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR
  35. * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
  36. * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
  37. *
  38. */
  39. package java.text.resources;
  40. import java.util.Locale;
  41. import java.util.ResourceBundle;
  42. import java.util.Hashtable;
  43. import java.util.Enumeration;
  44. import java.util.Vector;
  45. import java.io.File;
  46. import java.io.FileInputStream;
  47. import java.io.IOException;
  48. import java.io.FileNotFoundException;
  49. import java.util.zip.ZipInputStream;
  50. import java.util.zip.ZipEntry;
  51. /**
  52. * This class used to be the base class for all of the LocaleElements classes. This has
  53. * been changed so that all of the LocaleElements classes descend from ListResourceBundle.
  54. * This class now exists only to allow a way to get the list of available resources. Even
  55. * this will be changing in the future.
  56. *
  57. * @author Asmus Freytag
  58. * @author Mark Davis
  59. * @version 1.26 11/29/01
  60. */
  61. public class LocaleData {
  62. /**
  63. * Returns a list of the installed locales.
  64. * @param key A resource tag. Currently, this parameter is ignored. The obvious
  65. * intent, however, is for getAvailableLocales() to return a list of only those
  66. * locales that contain a resource with the specified resource tag.
  67. *
  68. * <p>Before we implement this function this way, however, some thought should be
  69. * given to whether this is really the right thing to do. Because of the lookup
  70. * algorithm, a NumberFormat, for example, is "installed" for all locales. But if
  71. * we're trying to put up a list of NumberFormats to choose from, we may want to see
  72. * only a list of those locales that uniquely define a NumberFormat rather than
  73. * inheriting one from another locale. Thus, if fr and fr_CA uniquely define
  74. * NumberFormat data, but fr_BE doesn't, the user wouldn't see "French (Belgium)" in
  75. * the list and would go for "French (default)" instead. Of course, this means
  76. * "English (United States)" would not be in the list, since it is the default locale.
  77. * This might be okay, but might be confusing to some users.
  78. *
  79. * <p>In addition, the other functions that call getAvailableLocales() don't currently
  80. * all pass the right thing for "key," meaning that all of these functions should be
  81. * looked at before anything is done to this function.
  82. *
  83. * <p>We recommend that someone take some careful consideration of these issues before
  84. * modifying this function to pay attention to the "key" parameter. --rtg 1/26/98
  85. */
  86. public static Locale[] getAvailableLocales(String key)
  87. {
  88. Locale[] temp = new Locale[localeList.length];
  89. System.arraycopy(localeList, 0, temp, 0, localeList.length);
  90. return temp;
  91. }
  92. // ========== privates ==========
  93. private static Vector classPathSegments = new Vector();
  94. private static Locale[] localeList;
  95. private static final String PACKAGE = "java.text.resources";
  96. private static final String PREFIX = "LocaleElements_";
  97. private static final char ZIPSEPARATOR = '/';
  98. static {
  99. String classPath =
  100. (String) java.security.AccessController.doPrivileged(
  101. new sun.security.action.GetPropertyAction("sun.boot.class.path"));
  102. String s =
  103. (String) java.security.AccessController.doPrivileged(
  104. new sun.security.action.GetPropertyAction("java.class.path"));
  105. // Search combined system and application class path
  106. if (s != null && s.length() != 0) {
  107. classPath += File.pathSeparator + s;
  108. }
  109. while (classPath != null && classPath.length() != 0) {
  110. int i = classPath.lastIndexOf(java.io.File.pathSeparatorChar);
  111. String dir = classPath.substring(i + 1);
  112. if (i == -1) {
  113. classPath = null;
  114. } else {
  115. classPath = classPath.substring(0, i);
  116. }
  117. classPathSegments.insertElementAt(dir, 0);
  118. }
  119. String[] classList = (String[])
  120. java.security.AccessController.doPrivileged(
  121. new java.security.PrivilegedAction() {
  122. public Object run() {
  123. return getClassList(PACKAGE, PREFIX);
  124. }
  125. });
  126. int plen = PREFIX.length();
  127. localeList = new Locale[classList.length];
  128. for (int i = 0; i < classList.length; i++) {
  129. int p2 = 0;
  130. int p1 = classList[i].indexOf('_', plen);
  131. String lang = "";
  132. String region = "";
  133. String var = "";
  134. if (p1 == -1) {
  135. lang = classList[i].substring(plen);
  136. } else {
  137. lang = classList[i].substring(plen, p1);
  138. p2 = classList[i].indexOf('_', p1 + 1);
  139. if (p2 == -1) {
  140. region = classList[i].substring(p1 + 1);
  141. } else {
  142. region = classList[i].substring(p1 + 1, p2);
  143. if (p2 < classList[i].length())
  144. var = classList[i].substring(p2 + 1);
  145. }
  146. }
  147. localeList[i] = new Locale(lang, region, var);
  148. }
  149. }
  150. /**
  151. * Walk through CLASSPATH and find class list from a package.
  152. * The class names start with prefix string
  153. * @param package name, class name prefix
  154. * @return class list in an array of String
  155. */
  156. private static String[] getClassList(String pkgName, String prefix) {
  157. Vector listBuffer = new Vector();
  158. String packagePath = pkgName.replace('.', File.separatorChar)
  159. + File.separatorChar;
  160. String zipPackagePath = pkgName.replace('.', ZIPSEPARATOR)
  161. + ZIPSEPARATOR;
  162. for (int i = 0; i < classPathSegments.size(); i++){
  163. String onePath = (String) classPathSegments.elementAt(i);
  164. File f = new File(onePath);
  165. if (!f.exists())
  166. continue;
  167. if (f.isFile())
  168. scanFile(f, zipPackagePath, listBuffer, prefix);
  169. else if (f.isDirectory()) {
  170. String fullPath;
  171. if (onePath.endsWith(File.separator))
  172. fullPath = onePath + packagePath;
  173. else
  174. fullPath = onePath + File.separatorChar + packagePath;
  175. File dir = new File(fullPath);
  176. if (dir.exists() && dir.isDirectory())
  177. scanDir(dir, listBuffer, prefix);
  178. }
  179. }
  180. String[] classNames = new String[listBuffer.size()];
  181. listBuffer.copyInto(classNames);
  182. return classNames;
  183. }
  184. private static void addClass (String className, Vector listBuffer, String prefix) {
  185. if (className != null && className.startsWith(prefix)
  186. && !listBuffer.contains(className))
  187. listBuffer.addElement(className);
  188. }
  189. private static String midString(String str, String pre, String suf) {
  190. String midStr;
  191. if (str.startsWith(pre) && str.endsWith(suf))
  192. midStr = str.substring(pre.length(), str.length() - suf.length());
  193. else
  194. midStr = null;
  195. return midStr;
  196. }
  197. private static void scanDir(File dir, Vector listBuffer, String prefix) {
  198. String[] fileList = dir.list();
  199. for (int i = 0; i < fileList.length; i++) {
  200. addClass(midString(fileList[i], "", ".class"), listBuffer, prefix);
  201. }
  202. }
  203. private static void scanFile(File f, String packagePath, Vector listBuffer,
  204. String prefix) {
  205. try {
  206. ZipInputStream zipFile = new ZipInputStream(new FileInputStream(f));
  207. boolean gotThere = false;
  208. ZipEntry entry;
  209. while ((entry = zipFile.getNextEntry()) != null) {
  210. String eName = entry.getName();
  211. if (eName.startsWith(packagePath)) {
  212. gotThere = true;
  213. if (eName.endsWith(".class")) {
  214. addClass(midString(eName, packagePath, ".class"),
  215. listBuffer, prefix);
  216. }
  217. } else {
  218. if (gotThere) // Found the package, now we are leaving
  219. break;
  220. }
  221. }
  222. } catch (FileNotFoundException e) {
  223. System.out.println("file not found:" + e);
  224. } catch (IOException e) {
  225. System.out.println("file IO Exception:" + e);
  226. } catch (Exception e) {
  227. System.out.println("Exception:" + e);
  228. }
  229. }
  230. }