/*
* @(#)Resource.java - resource and i18n
*
* Copyright (c) 2004-2005 by pstorch, All rights reserved.
*
* This file is part of ProjectX, a free Java based demux utility.
* By the authors, ProjectX is intended for educational purposes only,
* as a non-commercial test project.
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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 for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
package net.sourceforge.dvb.projectx.common;
//import java.awt.event.ActionEvent;
//import java.awt.event.ActionListener;
import java.io.File;
import java.io.FileInputStream;
import java.net.JarURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.MissingResourceException;
import java.util.PropertyResourceBundle;
import java.util.ResourceBundle;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.awt.Image;
import java.awt.Toolkit;
import net.sourceforge.dvb.projectx.common.Keys;
/**
* Project-X resource and localization handling.
*
* @author Peter Storch
*/
public class Resource extends Object {
/** the prefix of all pjx resource files */
private static final String PJX_RESOURCE_PREFIX = "pjxresources";
/** current working directory */
public static final String workdir = System.getProperty("user.dir");
/** os dependent file separator */
public static final String filesep = System.getProperty("file.separator");
/** the users locale */
private static Locale locale = null;
/** the default resource bundle */
private static ResourceBundle defaultResource = null;
/** the resource bundle for the current users locale or language setting */
private static ResourceBundle resource = null;
/**
* Loads a resource bundle for the given locale.
*
* @param locale
* @return ResourceBundle
*/
private static ResourceBundle loadResourceBundle(Locale locale) throws MissingResourceException
{
ResourceBundle newBundle = null;
String resourceName = PJX_RESOURCE_PREFIX + "_" + locale.getLanguage() + ".properties";
// first we try to find one in the current working directory
try
{
File file = new File(workdir + filesep + resourceName);
if (file.exists() && file.canRead())
{
newBundle = new PropertyResourceBundle(new FileInputStream(file));
return newBundle;
}
}
catch (Exception e)
{
// shit happens, go on and try to find one in our jar file
}
try
{
URL url = Resource.class.getClassLoader().getResource(resourceName);
newBundle = new PropertyResourceBundle(url.openStream());
}
catch (Exception e)
{
throw new MissingResourceException("couldn't find " + resourceName, Resource.class.getName(), resourceName);
}
return newBundle;
}
static{
// the default resource must be available
defaultResource = loadResourceBundle(Locale.ENGLISH);
try
{
// now try to load the resource bundle form the users locale
resource = loadResourceBundle(Locale.getDefault());
} catch (MissingResourceException e) {
// our fallback is english
resource = defaultResource;
}
}
/**
* Constructor of Resource.
*/
private Resource()
{
// singleton
}
/**
* Loads Language from ini file.
*
* @param filename Name of the inifile.
*/
public static void loadLang(String lang)
{
locale = new Locale(lang, "");
try {
resource = loadResourceBundle(locale);
} catch (MissingResourceException e) {
// our fallback is english
resource = defaultResource;
}
// initialize languages dependent keys
new Keys();
}
/**
*
*/
public static String getChosenLanguage()
{
if (locale == null)
return null;
return locale.getLanguage();
}
/**
*
*/
public static void setChosenLanguage(String str)
{
if (str == null)
locale = null;
else
locale = new Locale(str, "", "");
}
/**
* Gets a String from the Resource file. If the key is not found, the key
* itself is returned as text.
*
* @param key
* @return String
*/
public static String getString(String key)
{
String text = null;
try
{
text = resource.getString(key);
}
catch (MissingResourceException e)
{
try
{
// fallback to defaultResource
text = defaultResource.getString(key);
}
catch (MissingResourceException e2)
{
System.out.println("ResourceKey '" + key + "' not found in pjxresources");
}
}
// use key as text as fallback
if (text == null)
{
text = "?" + key + "?";
}
return text;
}
/**
* Returns a resource String as a String Array of lines.
*
* @return String[]
*/
public static String[] getStringByLines(String key)
{
List lines = new ArrayList();
StringTokenizer st = new StringTokenizer(getString(key), "\n");
while (st.hasMoreTokens())
{
lines.add(st.nextToken());
}
return (String[])lines.toArray(new String[0]);
}
/**
* Gets a String from the resource and inserts optional arguments.
*
* @param key
* @param args
* @return
*/
public static String getString(String key, Object args[])
{
return MessageFormat.format(getString(key), args);
}
/**
* Gets a String from the resource and inserts an optional argument.
*
* @param key
* @param args
* @return
*/
public static String getString(String key, Object arg)
{
return MessageFormat.format(getString(key), new Object[]{arg});
}
/**
* Gets a String from the resource and inserts two optional arguments.
*
* @param key
* @param arg1
* @param arg2
* @return
*/
public static String getString(String key, Object arg1, Object arg2)
{
return MessageFormat.format(getString(key), new Object[]{arg1, arg2});
}
/**
* Gets a String from the resource and inserts three optional arguments.
*
* @param key
* @param arg1
* @param arg2
* @param arg3
* @return
*/
public static String getString(String key, Object arg1, Object arg2, Object arg3)
{
return MessageFormat.format(getString(key), new Object[]{arg1, arg2, arg3});
}
/**
* Gets a String from the resource and inserts four optional arguments.
*
* @param key
* @param arg1
* @param arg2
* @param arg3
* @param arg4
* @return
*/
public static String getString(String key, Object arg1, Object arg2, Object arg3, Object arg4)
{
return MessageFormat.format(getString(key), new Object[]{arg1, arg2, arg3, arg4});
}
/**
* Gets a String from the resource and inserts five optional arguments.
*
* @param key
* @param arg1
* @param arg2
* @param arg3
* @param arg4
* @param arg5
* @return
*/
public static String getString(String key, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5)
{
return MessageFormat.format(getString(key), new Object[]{arg1, arg2, arg3, arg4, arg5});
}
/**
* Returns the available Locales for pjxresources.
*
* @return Locale[]
*/
public static Locale[] getAvailableLocales() {
Set locales = new HashSet();
String defLang = Locale.getDefault().getLanguage();
try {
// we know we have an english resource, so first find this one to find the location
URL url = ClassLoader.getSystemResource(PJX_RESOURCE_PREFIX + "_en.properties");
if (url != null) {
URLConnection urlc = null;
urlc = url.openConnection();
// If the resources are located in a JAR file, we need this
// version to get the available locales.
if (urlc != null && urlc instanceof JarURLConnection) {
JarURLConnection jurlc = (JarURLConnection) urlc;
addAvailableLocalesFromJar(locales, jurlc);
}
// .. else if the resources are in the file system, we use the
// default version to get the available locales.
else {
File enFile = new File(url.getFile());
File dir = enFile.getParentFile();
addAvailableLocalesFromFileSystem(locales, dir);
}
} else {
System.err.println("Couldn't find \"" + PJX_RESOURCE_PREFIX
+ "\"*.properties");
}
// also look into the current working directory for additional resource files
File workDirFile = new File(workdir);
addAvailableLocalesFromFileSystem(locales, workDirFile);
} catch (Exception e) {
System.out.println(e);
}
return (Locale[])locales.toArray(new Locale[0]);
}
/**
* Adds available Locales from the file system.
*
* @param locales
* @param dir
*/
private static void addAvailableLocalesFromFileSystem(Set locales, File dir) {
File[] files = dir.listFiles();
if (files != null) {
for (int i = 0; i < files.length; i++) {
File file = files[i];
if (file.isFile() && file.getName().startsWith(PJX_RESOURCE_PREFIX))
{
try {
String code = file.getName();
int pos = code.indexOf('_');
if (pos != -1) {
code = code.substring(pos + 1);
}
pos = code.indexOf('.');
if (pos != -1)
{
code = code.substring(0, pos);
}
Locale locale = new Locale(code, "");
locales.add(locale);
} catch (Exception e) {
System.out.println(e);
}
}
}
}
}
/**
* Adds available Locales from a Jar file location
*
* @param locales
* @param jurlc
*/
private static void addAvailableLocalesFromJar(Set locales, JarURLConnection jurlc) {
JarFile jarf = null;
try {
jarf = jurlc.getJarFile();
} catch (Exception e) {
System.out.println(e);
}
if (jarf != null) {
for (Enumeration en = jarf.entries(); en.hasMoreElements();) {
JarEntry jare = (JarEntry) en.nextElement();
String name = jare.getName();
if (name.startsWith(PJX_RESOURCE_PREFIX)) {
String code = name.substring(0,
name.length() - ".properties".length());
int pos = code.indexOf('_');
if (pos != -1) {
code = code.substring(pos + 1);
}
pos = code.indexOf('.');
if (pos != -1)
{
code = code.substring(0, pos);
}
Locale locale = new Locale(code, "");
locales.add(locale);
}
}
}
}
/**
* Returns a resource (e.g. from the jar file) as an URL.
*
* @param resource the name of the resource
* @return URL
*/
public static URL getResourceURL(String resource)
{
try
{
String filename = workdir + filesep + resource;
File file = new File(filename);
if (file.exists() && file.canRead())
{
return file.toURL();
}
}
catch(Exception e)
{
// ignore it, it was just a try to get this resource from the filesystem
}
// for the classloader we need to replace all backslashes to forward slashes.
// this is only necessary on windows systems and doesn't harm others
resource = resource.replace('\\', '/');
// ok, not founde in the filesystem, now try the classloader
return Resource.class.getClassLoader().getResource(resource);
}
/**
* Returns a resource (e.g. from the jar file) as an URL.
*
* @param resourceName the name of the resource
* @return URL
*/
public static URL getLocalizedResourceURL(String path, String resourceName)
{
Locale usedLocale = null;
if (locale != null)
{
usedLocale = locale;
}
else
{
usedLocale = Locale.getDefault();
}
String localizedResource = path + filesep + usedLocale.getLanguage() + filesep + resourceName;
URL url = getResourceURL(localizedResource);
if (url != null)
{
return url;
}
// there is no localized version of this file, try the default version
return getResourceURL(path + filesep + resourceName);
}
/**
*
*/
public static Image loadImage(String imageName)
{
try {
return Toolkit.getDefaultToolkit().createImage(getResourceURL(imageName));
} catch (Exception e) {
return null;
}
}
}