/*
Javier Kohen's Java Framework Classes.
Copyright (C) 2000-2001 Javier Kohen <jkohen at tough.com>
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 ar.com.jkohen.util;
import java.applet.Applet;
import java.applet.AudioClip;
import java.awt.*;
import java.net.*;
import java.util.*;
import java.io.*;
import ar.com.jkohen.irc.MircMessage;
public class Resources extends Observable implements Runnable
{
private static Object obj;
private static Class cls;
private static ClassLoader clsld;
private static MediaTracker tracker;
private static Thread loader;
private static String path;
private static Vector files;
public static Properties lang_resource;
public static Properties img_resource;
public static String help_resource;
// Events sounds.
public static final int SND_ON = 0;
public static final int SND_OFFAWAY = 1;
public static final int SND_OFF = 2;
public final static int EVENT_JOIN = 0;
public final static int EVENT_PART = 1;
public final static int EVENT_OP = 2;
public final static int EVENT_DEOP = 3;
public final static int EVENT_KICK = 4;
public final static int EVENT_BAN = 5;
public final static int EVENT_QUIT = 6;
public final static int EVENT_PRVMSG = 7;
public final static int EVENT_MSG = 8;
public final static int EVENTS = 9;
public static Hashtable SOUNDS = new Hashtable();
// Images buttons.
public static Image LARGE_NORMAL;
public static Image LARGE_PRESSED;
public static Image LARGE_DISABLED;
public static Image LARGE_ALERT;
public static Image LARGE_WAIT;
public static Image SMALL_NORMAL;
public static Image SMALL_PRESSED;
public static Image SMALL_DISABLED;
public Resources(Object target, String pref_lang)
{
this.obj = target;
try
{
/* Mixing Signed and Unsigned Code
** http://docs.oracle.com/javase/6/docs/technotes/guides/jweb/mixed_code.html
**
** ClassLoader clsld = Thread.currentThread().getContextClassLoader();
*/
Thread th = Thread.currentThread();
java.lang.reflect.Method getloader = Thread.class.getMethod("getContextClassLoader", new Class[] {});
Object obj = getloader.invoke(th, new Object[] {});
clsld = (ClassLoader)obj;
}
catch (Exception ex)
{
cls = (target instanceof Class) ? (Class)target : target.getClass();
}
this.tracker = new MediaTracker((Component)target);
/*
** By default, this will load the English language files
** Then, this will try to load JVM's default locale ones.
** So, you should always include *_en.properties files.
*/
try
{
Locale en_locale = new Locale("en", "");
Properties en_lang_resource = null;
Properties en_img_resource = null;
String en_help_resource = null;
try
{
en_lang_resource = readProperties("eirc", en_locale, null);
en_img_resource = readProperties("images", en_locale, null);
en_help_resource = readText("help", en_locale, null);
}
catch (MissingResourceException ex) { System.err.println("Cannot load " + ex.getKey()); }
Locale locale = null;
if (pref_lang != null && pref_lang.length() >= 2)
locale = new Locale(pref_lang, "");
else
locale = Locale.getDefault();
lang_resource = readProperties("eirc", locale, en_lang_resource);
img_resource = readProperties("images", locale, en_img_resource);
help_resource = readText("help", locale, en_help_resource);
}
catch (MissingResourceException ex) { System.err.println("Cannot load " + ex.getKey()); }
cacheImages();
}
public static URL getResource(String resource_name)
{
URL u = (clsld != null ? clsld.getResource(resource_name) : cls.getResource(resource_name));
return (u);
}
public static InputStream getResourceAsStream(String resource_name)
{
InputStream is = (clsld != null ? clsld.getResourceAsStream(resource_name) : cls.getResourceAsStream(resource_name));
return (is);
}
private static void cacheImages()
{
LARGE_NORMAL = getImage("button.large.normal");
LARGE_PRESSED = getImage("button.large.pressed");
LARGE_DISABLED = getImage("button.large.disabled");
LARGE_ALERT = getImage("button.large.alert");
LARGE_WAIT = getImage("button.large.wait");
SMALL_NORMAL = getImage("button.small.normal");
SMALL_PRESSED = getImage("button.small.pressed");
SMALL_DISABLED = getImage("button.small.disabled");
}
public void cacheSounds(Vector files, String path)
{
this.files = files;
this.path = path;
loader = new Thread(this, "sound_loader");
loader.start();
}
public void run()
{
int i = 1;
Enumeration e = files.elements();
while (e.hasMoreElements() && loader == Thread.currentThread())
{
String key = (String)e.nextElement();
AudioClip au = createSound(path + "/" + key);
if (au != null)
{
SOUNDS.put(key, au);
setChanged();
notifyObservers(key);
}
}
}
public static Image getImage(String key)
{
String name = getLabel(key);
if (name != null && !name.equals(""))
{
try
{
Image img = createImage(name);
tracker.addImage(img, 0);
tracker.waitForID(0, 1000);
return(img);
} catch (InterruptedException e) {}
}
return(null);
}
public static String getLabel(String key)
{
String value = img_resource.getProperty(key);
if (value == null)
System.err.println("Missing key : " + key);
return(value);
}
public static String getString(String key)
{
String value = lang_resource.getProperty(key);
if (value == null)
System.err.println("Missing key : " + key);
return(value);
}
public static String getHelp()
{
return(help_resource);
}
private Properties readProperties(String name, Locale loc, Properties defaults) throws MissingResourceException
{
Properties pr = null;
if (defaults != null)
pr = new Properties(defaults);
else
pr = new Properties();
String resource_name = name + "_" + loc.getLanguage() + ".properties";
try
{
InputStream in = getResourceAsStream(resource_name);
if (in != null)
{
pr.load(in);
in.close();
}
if (pr == null)
{
throw new MissingResourceException("Cannot load properties file" , "Resource", resource_name);
}
else
{
for (Enumeration e = pr.propertyNames(); e.hasMoreElements(); )
{
String key = (String)e.nextElement();
String value = pr.getProperty(key);
if (value != null && value.length() > 0)
pr.put(key, MircMessage.attrDecode(value));
}
}
}
catch (IOException e)
{
throw new MissingResourceException("Cannot load properties file" , "Resource", resource_name);
}
return(pr);
}
private String readText(String name, Locale loc, String defaults) throws MissingResourceException
{
String txt = null;
if (defaults != null)
txt = defaults;
String resource_name = name + "_" + loc.getLanguage() + ".txt";
try
{
InputStream in = getResourceAsStream(resource_name);
if (in != null)
{
txt = new String();
BufferedReader br = new BufferedReader(new InputStreamReader(in, "UTF8"));
String s;
while((s = br.readLine()) != null)
{
if (s.equals(""))
s = "\r";
txt += s + "\n";
}
br.close();
txt = MircMessage.attrDecode(txt);
}
}
catch (IOException e)
{
throw new MissingResourceException("Cannot load text file" , "Resource", resource_name);
}
return(txt);
}
/**
* BUGS:
* * Netscape Navigator (tested with 4.7x) won't load files from outside a JAR.
* * Life would be easier if Netscape Navigator supported Class.getResource().
* * Their not supporting it is actually documented on Netscape's Developers website.
*/
/*
public static byte [] getResource(String name, Object target) throws IOException
{
// Resolve object to a Class, if needed.
Class cl = (target instanceof Class) ? (Class)target : target.getClass();
InputStream is = cl.getResourceAsStream(name);
BufferedInputStream bis = new BufferedInputStream(is);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try
{
int pos = 0;
int readed;
final int chunk_size = 4096;
byte [] buf = new byte [chunk_size];
while ((readed = bis.read(buf, 0, chunk_size)) != -1)
{
baos.write(buf, pos, readed);
pos += readed;
}
return baos.toByteArray();
}
catch (Exception e)
{
throw new IOException("Cannot open image file " + name);
}
}
*/
private static Image createImage(String resource_name)
{
/*
try
{
byte [] image = getResource(resource_name, target);
return (Toolkit.getDefaultToolkit().createImage(image));
}
catch (IOException e) { System.err.println(e); }
return(null);
*/
try
{
URL url = getResource(resource_name);
Image image = ((Applet)obj).getImage(url);
return(image);
}
catch (Exception e) {}
System.err.println("Cannot open image file : " + resource_name);
return(null);
}
private static AudioClip createSound(String resource_name)
{
// URL url = new URL(((Applet)obj).getCodeBase() + resource_name);
URL url = getResource(resource_name);
AudioClip clip = ((Applet)obj).getAudioClip(url);
if (clip != null)
return(clip);
else
System.err.println("Cannot open sound file : " + resource_name);
return(null);
}
}