/*
*
* @(#)LocaleData.java 1.36 06/10/10
*
* Portions Copyright 2000-2008 Sun Microsystems, Inc. All Rights
* Reserved. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version
* 2 only, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License version 2 for more details (a copy is
* included at /legal/license.txt).
*
* You should have received a copy of the GNU General Public License
* version 2 along with this work; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
* Clara, CA 95054 or visit www.sun.com if you need additional
* information or have any questions.
*/
/*
* (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved
* (C) Copyright IBM Corp. 1996 - 1998 - All Rights Reserved
*
* The original version of this source code and documentation
* is copyrighted and owned by Taligent, Inc., a wholly-owned
* subsidiary of IBM. These materials are provided under terms
* of a License Agreement between Taligent and Sun. This technology
* is protected by multiple US and International patents.
*
* This notice and attribution to Taligent may not be removed.
* Taligent is a registered trademark of Taligent, Inc.
*
*/
package sun.text.resources;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.URL;
import java.net.URLClassLoader;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Locale;
import java.util.ResourceBundle;
import java.util.Hashtable;
import java.util.Vector;
import java.util.zip.ZipEntry;
import java.io.File;
import java.util.zip.ZipInputStream;
import sun.misc.Launcher;
/**
* Provides information about and access to resource bundles in the
* sun.text.resources package.
* This class now exists only to allow a way to get the list of available resources. Even
* this will be changing in the future.
*
* @author Asmus Freytag
* @author Mark Davis
* @version 1.34 01/23/03
*/
public class LocaleData {
/**
* Returns a list of the installed locales.
* @param key A resource tag. Currently, this parameter is ignored. The obvious
* intent, however, is for getAvailableLocales() to return a list of only those
* locales that contain a resource with the specified resource tag.
*
* <p>Before we implement this function this way, however, some thought should be
* given to whether this is really the right thing to do. Because of the lookup
* algorithm, a NumberFormat, for example, is "installed" for all locales. But if
* we're trying to put up a list of NumberFormats to choose from, we may want to see
* only a list of those locales that uniquely define a NumberFormat rather than
* inheriting one from another locale. Thus, if fr and fr_CA uniquely define
* NumberFormat data, but fr_BE doesn't, the user wouldn't see "French (Belgium)" in
* the list and would go for "French (default)" instead. Of course, this means
* "English (United States)" would not be in the list, since it is the default locale.
* This might be okay, but might be confusing to some users.
*
* <p>In addition, the other functions that call getAvailableLocales() don't currently
* all pass the right thing for "key," meaning that all of these functions should be
* looked at before anything is done to this function.
*
* <p>We recommend that someone take some careful consideration of these issues before
* modifying this function to pay attention to the "key" parameter. --rtg 1/26/98
*/
public static Locale[] getAvailableLocales(String key) {
// creating the locale list is expensive, so be careful to do it
// only once
if (localeList == null) {
synchronized(LocaleData.class) {
if (localeList == null) {
localeList = createLocaleList();
}
}
}
Locale[] temp = new Locale[localeList.length];
System.arraycopy(localeList, 0, temp, 0, localeList.length);
return temp;
}
/**
* Gets a sun.text.resources.LocaleElements resource bundle, using privileges
* to allow accessing a sun.* package.
*/
public static ResourceBundle getLocaleElements(Locale locale) {
return getBundle("sun.text.resources.LocaleElements", locale);
}
/**
* Gets a sun.text.resources.DateFormatZoneData resource bundle, using privileges
* to allow accessing a sun.* package.
*/
public static ResourceBundle getDateFormatZoneData(Locale locale) {
return getBundle("sun.text.resources.DateFormatZoneData", locale);
}
private static ResourceBundle getBundle(final String baseName, final Locale locale) {
return (ResourceBundle) AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
return ResourceBundle.getBundle(baseName, locale);
}
});
}
// ========== privates ==========
private static Vector classPathSegments = new Vector();
private static Locale[] localeList;
private static final String PACKAGE = "sun.text.resources";
private static final String PREFIX = "LocaleElements_";
private static final char ZIPSEPARATOR = '/';
private static Locale[] createLocaleList() {
Locale[] locales;
String classPath =
(String) java.security.AccessController.doPrivileged(
new sun.security.action.GetPropertyAction("sun.boot.class.path"));
String s =
(String) java.security.AccessController.doPrivileged(
new sun.security.action.GetPropertyAction("java.class.path"));
// Search combined system and application class path
if (s != null && s.length() != 0) {
if (classPath == null) {
classPath = s;
} else {
classPath += File.pathSeparator + s;
}
}
while (classPath != null && classPath.length() != 0) {
int i = classPath.lastIndexOf(java.io.File.pathSeparatorChar);
String dir = classPath.substring(i + 1);
if (i == -1) {
classPath = null;
} else {
classPath = classPath.substring(0, i);
}
classPathSegments.insertElementAt(dir, 0);
}
// add extensions from the extension class loader
ClassLoader appLoader = Launcher.getLauncher().getClassLoader();
URLClassLoader extLoader = (URLClassLoader) appLoader.getParent();
if (extLoader != null) {
URL[] urls = extLoader.getURLs();
for (int i = 0; i < urls.length; i++) {
classPathSegments.insertElementAt(urls[i].getPath(), 0);
}
}
String[] classList = (String[])
java.security.AccessController.doPrivileged(
new java.security.PrivilegedAction() {
public Object run() {
return getClassList(PACKAGE, PREFIX);
}
});
/*
* When all library classes are romized, no cdc.jar or foundation.jar
* exists, so we would fail to create the correct locale data by just
* searching through sun.boot.class.path and java.class.path.
* To solve the problem, we use a generated java class,
* sun.misc.DefaultLocaleList. This class is generated at build time.
* The generated class contains a list of default locale information
* gathered by parsing build-time class (romized classes) list.
*/
int plen = PREFIX.length();
localeList = new Locale[classList.length +
sun.misc.DefaultLocaleList.list.length];
/* 1. search sun.boot.class.path and java.class.path. */
for (int i = 0; i < classList.length; i++) {
localeList[i] = getLocale(classList[i].substring(plen));
}
/* 2. add locale information generated from romized classes if
* there is any
*/
for (int j = 0; j < sun.misc.DefaultLocaleList.list.length; j++) {
localeList[classList.length + j] =
getLocale(sun.misc.DefaultLocaleList.list[j]);
}
return (localeList);
}
private static Locale getLocale(String s) {
String lang = "";
String region = "";
String var = "";
int p1 = s.indexOf('_');
int p2 = 0;
if (p1 == -1) {
lang = s;
} else {
lang = s.substring(0, p1);
p2 = s.indexOf('_', p1 + 1);
if (p2 == -1) {
region = s.substring(p1 + 1);
} else {
region = s.substring(p1 + 1, p2);
if (p2 < s.length()) {
var = s.substring(p2 + 1);
}
}
}
return new Locale(lang, region, var);
}
/**
* Walk through CLASSPATH and find class list from a package.
* The class names start with prefix string
* @param package name, class name prefix
* @return class list in an array of String
*/
private static String[] getClassList(String pkgName, String prefix) {
Vector listBuffer = new Vector();
String packagePath = pkgName.replace('.', File.separatorChar)
+ File.separatorChar;
String zipPackagePath = pkgName.replace('.', ZIPSEPARATOR)
+ ZIPSEPARATOR;
for (int i = 0; i < classPathSegments.size(); i++){
String onePath = (String) classPathSegments.elementAt(i);
File f = new File(onePath);
if (!f.exists())
continue;
if (f.isFile())
scanFile(f, zipPackagePath, listBuffer, prefix);
else if (f.isDirectory()) {
String fullPath;
if (onePath.endsWith(File.separator))
fullPath = onePath + packagePath;
else
fullPath = onePath + File.separatorChar + packagePath;
File dir = new File(fullPath);
if (dir.exists() && dir.isDirectory())
scanDir(dir, listBuffer, prefix);
}
}
String[] classNames = new String[listBuffer.size()];
listBuffer.copyInto(classNames);
return classNames;
}
private static void addClass (String className, Vector listBuffer, String prefix) {
if (className != null && className.startsWith(prefix)
&& !listBuffer.contains(className))
listBuffer.addElement(className);
}
private static String midString(String str, String pre, String suf) {
String midStr;
if (str.startsWith(pre) && str.endsWith(suf))
midStr = str.substring(pre.length(), str.length() - suf.length());
else
midStr = null;
return midStr;
}
private static void scanDir(File dir, Vector listBuffer, String prefix) {
String[] fileList = dir.list();
for (int i = 0; i < fileList.length; i++) {
addClass(midString(fileList[i], "", ".class"), listBuffer, prefix);
}
}
private static void scanFile(File f, String packagePath, Vector listBuffer,
String prefix) {
try {
ZipInputStream zipFile = new ZipInputStream(new FileInputStream(f));
boolean gotThere = false;
ZipEntry entry;
while ((entry = zipFile.getNextEntry()) != null) {
String eName = entry.getName();
if (eName.startsWith(packagePath)) {
gotThere = true;
if (eName.endsWith(".class")) {
addClass(midString(eName, packagePath, ".class"),
listBuffer, prefix);
}
} else {
if (gotThere) // Found the package, now we are leaving
break;
}
}
} catch (FileNotFoundException e) {
System.out.println("file not found:" + e);
} catch (IOException e) {
System.out.println("file IO Exception:" + e);
} catch (Exception e) {
System.out.println("Exception:" + e);
}
}
}