package org.safermobile.clear.micro; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.Reader; import java.util.Hashtable; public class L10nResources { // Constants ----------------------------------------------------- private static final String PROPERTIES_PCKG = ""; private static final String PROPERTIES_PRFX = "messages"; private static final String DEFAULT_LOCALE = "en-US"; private static final String UNSET_LOCALE_MESSAGE = "Set locale before retrieving resources."; private static final String INVALID_STRING_FORMAT = "The String format is invalid."; private static final String LOCALE_NOT_FOUND = "No resource found for locale"; private static final String INVALID_RESOURCE_FORMAT = "The resource file format is invalid."; private static final String ERROR_LOADING_RESOURCES = "Error loading resources."; private static final String UNABLE_TO_FIND_BINARY_RESOURCE = "Unable to find binary resource."; // Attributes ---------------------------------------------------- private Hashtable values; private String _locale; // Static -------------------------------------------------------- /** * Gets an instance of L10nResources to access resources with * the specified locale. * * @param locale name of locale. * @return L10nResources instance. */ public static L10nResources getL10nResources(String locale) { return new L10nResources(locale); } // Constructors -------------------------------------------------- /** * Creates an instance of L10nResources to access resources * with the specified locale. * * @param locale name of locale. * @return L10nResources instance. */ private L10nResources(String locale) { this.values = new Hashtable(); //this.setLocale(locale); this.setLocale("en-US"); } // Public -------------------------------------------------------- /** * Sets the locale of the L10nResources instance. * * @param locale name of the locale. */ public void setLocale(String locale) { if (locale == null || locale.length() == 0x00) { _locale = System.getProperty("microedition.locale"); System.out.println("LOCALE: " + _locale); if (_locale == null || _locale.length() == 0) { _locale = L10nResources.DEFAULT_LOCALE; } } else { _locale = locale; } try { this.loadResources(_locale); } catch (Exception exc) { exc.printStackTrace(); } } /** * Gets the value for the specified key. For every parameter * on the params argument there must be an entry in the key * value in the format {x} where x is the index of the value * to be replaced on the formated string. * * @param key resource key. * @param params parameters to be formated. * @return the formated value. */ public String getString(String key, String[] params) { String result = null; if (this.values == null) { throw new IllegalStateException(UNSET_LOCALE_MESSAGE); } result = (String) this.values.get(key); if (result == null){ result = "!!" + key + "!!"; } else { StringBuffer buffer = new StringBuffer(result); for (int i = 0; i < params.length; i++) { int index = result.indexOf("{" + i + "}"); if (index == -1) { throw new IllegalArgumentException(INVALID_STRING_FORMAT); } buffer.delete(index, index + String.valueOf(i).length() + 2); buffer.insert(index, params[i]); result = buffer.toString(); buffer.delete(0x00, buffer.length()); buffer.append(result); } } return result; } /** * Gets the value for the specified key. * * @param key resource key. * @return String values associated to the * key. */ public String getString(String key) { if (this.values == null) { throw new IllegalStateException(UNSET_LOCALE_MESSAGE); } String result = (String) this.values.get(key); if (result == null) { result = "!!" + key + "!!"; } return result; } /** * Gets the binary data associated to the path * set as value of the specified key. * * @param key resource key. * @return the bytes of the binary data or null * if key has no associated value. * @throws IOException - If any error occurs. */ public byte[] getData(String key) throws IOException { byte[] result = null; String value = getString(key); if (value != null) { InputStream stream = this.getClass().getResourceAsStream(value); if (stream == null) { throw new IOException(UNABLE_TO_FIND_BINARY_RESOURCE); } ByteArrayOutputStream buffer = new ByteArrayOutputStream(); try { byte[] chunk = new byte[100]; int read = -1; do { read = stream.read(chunk); if (read > 0x00) { buffer.write(chunk, 0x00, read); } } while (read != -1); } finally { stream.close(); } result = buffer.toByteArray(); } return result; } // Package protected --------------------------------------------- // Protected ----------------------------------------------------- // Private ------------------------------------------------------- private void loadResources(String locale) throws IOException { Reader reader = null; this.values.clear(); try { reader = getResourceReader(locale); if (reader != null) { values = readResources(reader); } } finally { if (reader != null) reader.close(); } } private Reader getResourceReader(String locale) throws IOException { Reader reader = null; String resourePath = getResourcePath(locale); InputStream stream = this.getClass().getResourceAsStream(resourePath); if (stream == null) { throw new IOException(LOCALE_NOT_FOUND + " " + _locale + "."); } else { reader = new InputStreamReader(stream); } return reader; } private Hashtable readResources(Reader reader) throws IOException { Hashtable values = new Hashtable(); StringBuffer buffer = new StringBuffer(); try { int letter = -1; while ((letter = reader.read()) != -1) { switch (letter) { case '\r': case '\n': break; default: buffer.append((char)letter); break; } if (letter == '\n') { String line = buffer.toString(); int separator = line.indexOf("="); if (separator < 0) { throw new IOException(INVALID_RESOURCE_FORMAT); } String key = line.substring(0x00, separator); String value = line.substring(++separator, line.length()); values.put(key, value); buffer.delete(0x00, buffer.length()); } } } catch (Exception e) { throw new IOException(ERROR_LOADING_RESOURCES); } return values; } private String getResourcePath(String locale) { StringBuffer buffer = new StringBuffer(); buffer.append("/"); if ( PROPERTIES_PCKG.length() > 0 ) { buffer.append(PROPERTIES_PCKG); buffer.append("/"); } buffer.append(PROPERTIES_PRFX); if (locale.length() > 0) { buffer.append("_"); } buffer.append(locale); buffer.append(".properties"); return buffer.toString(); } }