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