diff --git a/classpath/java/lang/Character.java b/classpath/java/lang/Character.java index 859600ca2f..dd7658d52b 100644 --- a/classpath/java/lang/Character.java +++ b/classpath/java/lang/Character.java @@ -70,7 +70,7 @@ public final class Character { } public static boolean isWhitespace(char c) { - return c == ' ' || c == '\t' || c == '\n'; + return c == ' ' || c == '\t' || c == '\n' || c == '\r'; } public static boolean isSpaceChar(char c) { diff --git a/classpath/java/lang/Throwable.java b/classpath/java/lang/Throwable.java index 1c77a7566a..85cefd8305 100644 --- a/classpath/java/lang/Throwable.java +++ b/classpath/java/lang/Throwable.java @@ -31,6 +31,14 @@ public class Throwable { return cause; } + public void initCause(Throwable e) { + if (cause == null) { + cause = e; + } else { + throw new IllegalStateException(); + } + } + public String getMessage() { return message; } diff --git a/classpath/java/util/ResourceBundle.java b/classpath/java/util/ResourceBundle.java index 6a20ee9446..6df7e4d3a0 100644 --- a/classpath/java/util/ResourceBundle.java +++ b/classpath/java/util/ResourceBundle.java @@ -1,5 +1,211 @@ package java.util; -public abstract class ResourceBundle { +import java.lang.reflect.Method; +import java.io.InputStream; +import java.io.IOException; +public abstract class ResourceBundle { + protected ResourceBundle parent; + + private static String replace(char a, char b, String s) { + char[] array = new char[s.length()]; + for (int i = 0; i < array.length; ++i) { + char c = s.charAt(i); + array[i] = (c == a ? b : c); + } + return new String(array, 0, array.length, false); + } + + private static ResourceBundle findProperties(String name, ClassLoader loader, + ResourceBundle parent) + throws IOException + { + InputStream in = loader.getResourceAsStream + (replace('.', '/', name) + ".properties"); + if (in != null) { + try { + return new MapResourceBundle(new Parser().parse(in), parent); + } finally { + in.close(); + } + } else { + return null; + } + } + + private static ResourceBundle find(String name, ClassLoader loader, + ResourceBundle parent) + throws Exception + { + try { + Class c = Class.forName(name, true, loader); + if (c.isAssignableFrom(ResourceBundle.class)) { + return (ResourceBundle) c.getConstructor().newInstance(); + } + } catch (ClassNotFoundException ok) { + } catch (NoSuchMethodException ok) { } + + return findProperties(name, loader, parent); + } + + public static ResourceBundle getBundle(String name, Locale locale, + ClassLoader loader) + { + try { + ResourceBundle b = find(name, loader, null); + if (locale.getLanguage() != null) { + name = name + "_" + locale.getLanguage(); + b = find(name, loader, b); + if (locale.getCountry() != null) { + name = name + "_" + locale.getCountry(); + b = find(name, loader, b); + if (locale.getVariant() != null) { + name = name + "_" + locale.getVariant(); + b = find(name, loader, b); + } + } + } + return b; + } catch (Exception e) { + RuntimeException re = new MissingResourceException(name, name, null); + re.initCause(e); + throw re; + } + } + + public static ResourceBundle getBundle(String name, Locale locale) { + return getBundle(name, locale, + Method.getCaller().getDeclaringClass().getClassLoader()); + } + + public static ResourceBundle getBundle(String name) { + return getBundle(name, Locale.getDefault(), + Method.getCaller().getDeclaringClass().getClassLoader()); + } + + public Object getObject(String key) { + for (ResourceBundle b = this; b != null; b = b.parent) { + Object value = b.handleGetObject(key); + if (value != null) { + return value; + } + } + return null; + } + + public String getString(String key) { + return (String) getObject(key); + } + + protected abstract Object handleGetObject(String key); + + private static class MapResourceBundle extends ResourceBundle { + private final Map map; + + public MapResourceBundle(Map map, ResourceBundle parent) { + this.parent = parent; + this.map = map; + } + + protected Object handleGetObject(String key) { + return map.get(key); + } + } + + private static class Parser { + private StringBuilder key = null; + private StringBuilder value = null; + private StringBuilder current = null; + + private void append(int c) { + if (current == null) { + if (key == null) { + current = key = new StringBuilder(); + } else { + current = value = new StringBuilder(); + } + } + + current.append((char) c); + } + + private void finishLine(Map map) { + if (key != null) { + map.put(key.toString(), + (value == null ? "" : value.toString().trim())); + } + + key = value = current = null; + } + + private Map parse(InputStream in) + throws IOException + { + Map map = new HashMap(); + boolean escaped = false; + + int c; + while ((c = in.read()) != -1) { + if (c == '\\') { + if (escaped) { + escaped = false; + append(c); + } else { + escaped = true; + } + } else { + switch (c) { + case '#': + case '!': + if (key == null) { + while ((c = in.read()) != -1 && c != '\n'); + } else { + append(c); + } + break; + + case ' ': + case '\r': + case '\t': + if (escaped || key != current) { + append(c); + } else { + current = null; + } + break; + + case ':': + case '=': + if (escaped || key != current) { + append(c); + } else { + if (key == null) { + key = new StringBuilder(); + } + current = null; + } + break; + + case '\n': + if (escaped) { + append(c); + } else { + finishLine(map); + } + break; + + default: + append(c); + break; + } + + escaped = false; + } + } + + finishLine(map); + + return map; + } + } }