# HG changeset patch # User Jaroslav Tulach # Date 1380814604 -7200 # Node ID c794024954b592b5a85add404b27a1d3f13b2578 # Parent 804f6f982f4eb545238e9fe160d5aea662b96922 Implementation of few more JDK classes diff -r 804f6f982f4e -r c794024954b5 rt/emul/compact/src/main/java/java/io/BufferedInputStream.java --- a/rt/emul/compact/src/main/java/java/io/BufferedInputStream.java Thu Oct 03 15:51:55 2013 +0200 +++ b/rt/emul/compact/src/main/java/java/io/BufferedInputStream.java Thu Oct 03 17:36:44 2013 +0200 @@ -24,7 +24,6 @@ */ package java.io; -import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; /** * A BufferedInputStream adds @@ -59,16 +58,6 @@ */ protected volatile byte buf[]; - /** - * Atomic updater to provide compareAndSet for buf. This is - * necessary because closes can be asynchronous. We use nullness - * of buf[] as primary indicator that this stream is closed. (The - * "in" field is also nulled out on close.) - */ - private static final - AtomicReferenceFieldUpdater bufUpdater = - AtomicReferenceFieldUpdater.newUpdater - (BufferedInputStream.class, byte[].class, "buf"); /** * The index one greater than the index of the last valid byte in @@ -221,14 +210,6 @@ nsz = marklimit; byte nbuf[] = new byte[nsz]; System.arraycopy(buffer, 0, nbuf, 0, pos); - if (!bufUpdater.compareAndSet(this, buffer, nbuf)) { - // Can't replace buf if there was an async close. - // Note: This would need to be changed if fill() - // is ever made accessible to multiple threads. - // But for now, the only way CAS can fail is via close. - // assert buf == null; - throw new IOException("Stream closed"); - } buffer = nbuf; } count = pos; @@ -465,13 +446,12 @@ public void close() throws IOException { byte[] buffer; while ( (buffer = buf) != null) { - if (bufUpdater.compareAndSet(this, buffer, null)) { - InputStream input = in; - in = null; - if (input != null) - input.close(); - return; - } + InputStream input = in; + buf = null; + in = null; + if (input != null) + input.close(); + return; // Else retry in case a new buf was CASed in fill() } } diff -r 804f6f982f4e -r c794024954b5 rt/emul/compact/src/main/java/java/io/FileDescriptor.java --- a/rt/emul/compact/src/main/java/java/io/FileDescriptor.java Thu Oct 03 15:51:55 2013 +0200 +++ b/rt/emul/compact/src/main/java/java/io/FileDescriptor.java Thu Oct 03 17:36:44 2013 +0200 @@ -134,36 +134,6 @@ */ public native void sync() throws SyncFailedException; - /* This routine initializes JNI field offsets for the class */ - private static native void initIDs(); - - static { - initIDs(); - } - - // Set up JavaIOFileDescriptorAccess in SharedSecrets - static { - sun.misc.SharedSecrets.setJavaIOFileDescriptorAccess( - new sun.misc.JavaIOFileDescriptorAccess() { - public void set(FileDescriptor obj, int fd) { - obj.fd = fd; - } - - public int get(FileDescriptor obj) { - return obj.fd; - } - - public void setHandle(FileDescriptor obj, long handle) { - throw new UnsupportedOperationException(); - } - - public long getHandle(FileDescriptor obj) { - throw new UnsupportedOperationException(); - } - } - ); - } - // package private methods used by FIS, FOS and RAF int incrementAndGetUseCount() { diff -r 804f6f982f4e -r c794024954b5 rt/emul/compact/src/main/java/java/io/FileInputStream.java --- a/rt/emul/compact/src/main/java/java/io/FileInputStream.java Thu Oct 03 15:51:55 2013 +0200 +++ b/rt/emul/compact/src/main/java/java/io/FileInputStream.java Thu Oct 03 17:36:44 2013 +0200 @@ -25,8 +25,6 @@ package java.io; -import java.nio.channels.FileChannel; -import sun.nio.ch.FileChannelImpl; /** @@ -51,7 +49,7 @@ /* File Descriptor - handle to the open file */ private final FileDescriptor fd; - private FileChannel channel = null; +// private FileChannel channel = null; private final Object closeLock = new Object(); private volatile boolean closed = false; @@ -125,17 +123,7 @@ * @see java.lang.SecurityManager#checkRead(java.lang.String) */ public FileInputStream(File file) throws FileNotFoundException { - String name = (file != null ? file.getPath() : null); - SecurityManager security = System.getSecurityManager(); - if (security != null) { - security.checkRead(name); - } - if (name == null) { - throw new NullPointerException(); - } - fd = new FileDescriptor(); - fd.incrementAndGetUseCount(); - open(name); + throw new SecurityException(); } /** @@ -163,21 +151,7 @@ * @see SecurityManager#checkRead(java.io.FileDescriptor) */ public FileInputStream(FileDescriptor fdObj) { - SecurityManager security = System.getSecurityManager(); - if (fdObj == null) { - throw new NullPointerException(); - } - if (security != null) { - security.checkRead(fdObj); - } - fd = fdObj; - - /* - * FileDescriptor is being shared by streams. - * Ensure that it's GC'ed only when all the streams/channels are done - * using it. - */ - fd.incrementAndGetUseCount(); + throw new SecurityException(); } /** @@ -303,15 +277,15 @@ } closed = true; } - if (channel != null) { - /* - * Decrement the FD use count associated with the channel - * The use count is incremented whenever a new channel - * is obtained from this stream. - */ - fd.decrementAndGetUseCount(); - channel.close(); - } +// if (channel != null) { +// /* +// * Decrement the FD use count associated with the channel +// * The use count is incremented whenever a new channel +// * is obtained from this stream. +// */ +// fd.decrementAndGetUseCount(); +// channel.close(); +// } /* * Decrement the FD use count associated with this stream @@ -358,21 +332,21 @@ * @since 1.4 * @spec JSR-51 */ - public FileChannel getChannel() { - synchronized (this) { - if (channel == null) { - channel = FileChannelImpl.open(fd, true, false, this); - - /* - * Increment fd's use count. Invoking the channel's close() - * method will result in decrementing the use count set for - * the channel. - */ - fd.incrementAndGetUseCount(); - } - return channel; - } - } +// public FileChannel getChannel() { +// synchronized (this) { +// if (channel == null) { +// channel = FileChannelImpl.open(fd, true, false, this); +// +// /* +// * Increment fd's use count. Invoking the channel's close() +// * method will result in decrementing the use count set for +// * the channel. +// */ +// fd.incrementAndGetUseCount(); +// } +// return channel; +// } +// } private static native void initIDs(); diff -r 804f6f982f4e -r c794024954b5 rt/emul/compact/src/main/java/java/io/FileOutputStream.java --- a/rt/emul/compact/src/main/java/java/io/FileOutputStream.java Thu Oct 03 15:51:55 2013 +0200 +++ b/rt/emul/compact/src/main/java/java/io/FileOutputStream.java Thu Oct 03 17:36:44 2013 +0200 @@ -25,8 +25,6 @@ package java.io; -import java.nio.channels.FileChannel; -import sun.nio.ch.FileChannelImpl; /** @@ -65,7 +63,7 @@ /** * The associated channel, initalized lazily. */ - private FileChannel channel; +// private FileChannel channel; private final Object closeLock = new Object(); private volatile boolean closed = false; @@ -197,19 +195,7 @@ public FileOutputStream(File file, boolean append) throws FileNotFoundException { - String name = (file != null ? file.getPath() : null); - SecurityManager security = System.getSecurityManager(); - if (security != null) { - security.checkWrite(name); - } - if (name == null) { - throw new NullPointerException(); - } - this.fd = new FileDescriptor(); - this.append = append; - - fd.incrementAndGetUseCount(); - open(name, append); + throw new SecurityException(); } /** @@ -236,22 +222,7 @@ * @see java.lang.SecurityManager#checkWrite(java.io.FileDescriptor) */ public FileOutputStream(FileDescriptor fdObj) { - SecurityManager security = System.getSecurityManager(); - if (fdObj == null) { - throw new NullPointerException(); - } - if (security != null) { - security.checkWrite(fdObj); - } - this.fd = fdObj; - this.append = false; - - /* - * FileDescriptor is being shared by streams. - * Ensure that it's GC'ed only when all the streams/channels are done - * using it. - */ - fd.incrementAndGetUseCount(); + throw new SecurityException(); } /** @@ -338,16 +309,16 @@ } closed = true; } - - if (channel != null) { - /* - * Decrement FD use count associated with the channel - * The use count is incremented whenever a new channel - * is obtained from this stream. - */ - fd.decrementAndGetUseCount(); - channel.close(); - } +// +// if (channel != null) { +// /* +// * Decrement FD use count associated with the channel +// * The use count is incremented whenever a new channel +// * is obtained from this stream. +// */ +// fd.decrementAndGetUseCount(); +// channel.close(); +// } /* * Decrement FD use count associated with this stream @@ -395,21 +366,21 @@ * @since 1.4 * @spec JSR-51 */ - public FileChannel getChannel() { - synchronized (this) { - if (channel == null) { - channel = FileChannelImpl.open(fd, false, true, append, this); - - /* - * Increment fd's use count. Invoking the channel's close() - * method will result in decrementing the use count set for - * the channel. - */ - fd.incrementAndGetUseCount(); - } - return channel; - } - } +// public FileChannel getChannel() { +// synchronized (this) { +// if (channel == null) { +// channel = FileChannelImpl.open(fd, false, true, append, this); +// +// /* +// * Increment fd's use count. Invoking the channel's close() +// * method will result in decrementing the use count set for +// * the channel. +// */ +// fd.incrementAndGetUseCount(); +// } +// return channel; +// } +// } /** * Cleans up the connection to the file, and ensures that the diff -r 804f6f982f4e -r c794024954b5 rt/emul/compact/src/main/java/java/nio/charset/CharsetDecoder.java --- a/rt/emul/compact/src/main/java/java/nio/charset/CharsetDecoder.java Thu Oct 03 15:51:55 2013 +0200 +++ b/rt/emul/compact/src/main/java/java/nio/charset/CharsetDecoder.java Thu Oct 03 17:36:44 2013 +0200 @@ -1,26 +1,26 @@ /* - * Copyright (c) 2000, 2008, Oracle and/or its affiliates. All rights reserved. - * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * + * This code 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. * + * This code 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 in the LICENSE file that + * accompanied this code). * + * 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. */ // -- This file was mechanically generated: Do not edit! -- // diff -r 804f6f982f4e -r c794024954b5 rt/emul/compact/src/main/java/java/nio/charset/CharsetEncoder.java --- a/rt/emul/compact/src/main/java/java/nio/charset/CharsetEncoder.java Thu Oct 03 15:51:55 2013 +0200 +++ b/rt/emul/compact/src/main/java/java/nio/charset/CharsetEncoder.java Thu Oct 03 17:36:44 2013 +0200 @@ -1,26 +1,26 @@ /* - * Copyright (c) 2000, 2008, Oracle and/or its affiliates. All rights reserved. - * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * + * This code 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. * + * This code 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 in the LICENSE file that + * accompanied this code). * + * 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. */ // -- This file was mechanically generated: Do not edit! -- // diff -r 804f6f982f4e -r c794024954b5 rt/emul/compact/src/main/java/java/util/Locale.java --- a/rt/emul/compact/src/main/java/java/util/Locale.java Thu Oct 03 15:51:55 2013 +0200 +++ b/rt/emul/compact/src/main/java/java/util/Locale.java Thu Oct 03 17:36:44 2013 +0200 @@ -514,6 +514,15 @@ private static final int DISPLAY_COUNTRY = 1; private static final int DISPLAY_VARIANT = 2; private static final int DISPLAY_SCRIPT = 3; + + static Locale getInstance(String language, String script, String region, String v, Object object) { + return new Locale(language, script, region); + } + + static Locale getInstance(String no, String no0, String ny) { + return new Locale(no, no0, ny); + } + private String language; private String country; private String variant; @@ -629,6 +638,26 @@ } /** + * Gets the current value of the default locale for the specified Category + * for this instance of the Java Virtual Machine. + *

+ * The Java Virtual Machine sets the default locale during startup based + * on the host environment. It is used by many locale-sensitive methods + * if no locale is explicitly specified. It can be changed using the + * setDefault(Locale.Category, Locale) method. + * + * @param category - the specified category to get the default locale + * @throws NullPointerException - if category is null + * @return the default locale for the specified Category for this instance + * of the Java Virtual Machine + * @see #setDefault(Locale.Category, Locale) + * @since 1.7 + */ + public static Locale getDefault(Locale.Category category) { + return Locale.US; + } + + /** * Sets the default locale for this instance of the Java Virtual Machine. * This does not affect the host locale. *

@@ -938,5 +967,46 @@ return true; } + /** + * Enum for locale categories. These locale categories are used to get/set + * the default locale for the specific functionality represented by the + * category. + * + * @see #getDefault(Locale.Category) + * @see #setDefault(Locale.Category, Locale) + * @since 1.7 + */ + public enum Category { + + /** + * Category used to represent the default locale for + * displaying user interfaces. + */ + DISPLAY("user.language.display", + "user.script.display", + "user.country.display", + "user.variant.display"), + + /** + * Category used to represent the default locale for + * formatting dates, numbers, and/or currencies. + */ + FORMAT("user.language.format", + "user.script.format", + "user.country.format", + "user.variant.format"); + + Category(String languageKey, String scriptKey, String countryKey, String variantKey) { + this.languageKey = languageKey; + this.scriptKey = scriptKey; + this.countryKey = countryKey; + this.variantKey = variantKey; + } + + final String languageKey; + final String scriptKey; + final String countryKey; + final String variantKey; + } } diff -r 804f6f982f4e -r c794024954b5 rt/emul/compact/src/main/java/java/util/Properties.java --- a/rt/emul/compact/src/main/java/java/util/Properties.java Thu Oct 03 15:51:55 2013 +0200 +++ b/rt/emul/compact/src/main/java/java/util/Properties.java Thu Oct 03 17:36:44 2013 +0200 @@ -861,12 +861,11 @@ * @since 1.5 */ public synchronized void loadFromXML(InputStream in) - throws IOException, InvalidPropertiesFormatException + throws IOException { if (in == null) throw new NullPointerException(); - XMLUtils.load(this, in); - in.close(); + throw new IOException(); } /** @@ -933,7 +932,7 @@ { if (os == null) throw new NullPointerException(); - XMLUtils.save(this, os, comment, encoding); + throw new IOException(); } /** diff -r 804f6f982f4e -r c794024954b5 rt/emul/compact/src/main/java/java/util/PropertyResourceBundle.java --- a/rt/emul/compact/src/main/java/java/util/PropertyResourceBundle.java Thu Oct 03 15:51:55 2013 +0200 +++ b/rt/emul/compact/src/main/java/java/util/PropertyResourceBundle.java Thu Oct 03 17:36:44 2013 +0200 @@ -42,7 +42,6 @@ import java.io.InputStream; import java.io.Reader; import java.io.IOException; -import sun.util.ResourceBundleEnumeration; /** * PropertyResourceBundle is a concrete subclass of @@ -187,4 +186,57 @@ // ==================privates==================== private Map lookup; + + + /** + * Implements an Enumeration that combines elements from a Set and + * an Enumeration. Used by ListResourceBundle and PropertyResourceBundle. + */ + static class ResourceBundleEnumeration implements Enumeration { + + Set set; + Iterator iterator; + Enumeration enumeration; // may remain null + + /** + * Constructs a resource bundle enumeration. + * @param set an set providing some elements of the enumeration + * @param enumeration an enumeration providing more elements of the enumeration. + * enumeration may be null. + */ + public ResourceBundleEnumeration(Set set, Enumeration enumeration) { + this.set = set; + this.iterator = set.iterator(); + this.enumeration = enumeration; + } + + String next = null; + + public boolean hasMoreElements() { + if (next == null) { + if (iterator.hasNext()) { + next = iterator.next(); + } else if (enumeration != null) { + while (next == null && enumeration.hasMoreElements()) { + next = enumeration.nextElement(); + if (set.contains(next)) { + next = null; + } + } + } + } + return next != null; + } + + public String nextElement() { + if (hasMoreElements()) { + String result = next; + next = null; + return result; + } else { + throw new NoSuchElementException(); + } + } + } + } diff -r 804f6f982f4e -r c794024954b5 rt/emul/compact/src/main/java/java/util/ResourceBundle.java --- a/rt/emul/compact/src/main/java/java/util/ResourceBundle.java Thu Oct 03 15:51:55 2013 +0200 +++ b/rt/emul/compact/src/main/java/java/util/ResourceBundle.java Thu Oct 03 17:36:44 2013 +0200 @@ -45,19 +45,7 @@ import java.lang.ref.ReferenceQueue; import java.lang.ref.SoftReference; import java.lang.ref.WeakReference; -import java.net.JarURLConnection; import java.net.URL; -import java.net.URLConnection; -import java.security.AccessController; -import java.security.PrivilegedAction; -import java.security.PrivilegedActionException; -import java.security.PrivilegedExceptionAction; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; -import java.util.jar.JarEntry; - -import sun.util.locale.BaseLocale; -import sun.util.locale.LocaleObjectCache; /** @@ -288,8 +276,8 @@ * This variable would be better named "cache", but we keep the old * name for compatibility with some workarounds for bug 4212439. */ - private static final ConcurrentMap cacheList - = new ConcurrentHashMap<>(INITIAL_CACHE_SIZE); + private static final Map cacheList + = new HashMap<>(INITIAL_CACHE_SIZE); /** * Queue for reference objects referring to class loaders or bundles. @@ -410,65 +398,6 @@ return locale; } - /* - * Automatic determination of the ClassLoader to be used to load - * resources on behalf of the client. N.B. The client is getLoader's - * caller's caller. - */ - private static ClassLoader getLoader() { - Class[] stack = getClassContext(); - /* Magic number 2 identifies our caller's caller */ - Class c = stack[2]; - ClassLoader cl = (c == null) ? null : c.getClassLoader(); - if (cl == null) { - // When the caller's loader is the boot class loader, cl is null - // here. In that case, ClassLoader.getSystemClassLoader() may - // return the same class loader that the application is - // using. We therefore use a wrapper ClassLoader to create a - // separate scope for bundles loaded on behalf of the Java - // runtime so that these bundles cannot be returned from the - // cache to the application (5048280). - cl = RBClassLoader.INSTANCE; - } - return cl; - } - - private static native Class[] getClassContext(); - - /** - * A wrapper of ClassLoader.getSystemClassLoader(). - */ - private static class RBClassLoader extends ClassLoader { - private static final RBClassLoader INSTANCE = AccessController.doPrivileged( - new PrivilegedAction() { - public RBClassLoader run() { - return new RBClassLoader(); - } - }); - private static final ClassLoader loader = ClassLoader.getSystemClassLoader(); - - private RBClassLoader() { - } - public Class loadClass(String name) throws ClassNotFoundException { - if (loader != null) { - return loader.loadClass(name); - } - return Class.forName(name); - } - public URL getResource(String name) { - if (loader != null) { - return loader.getResource(name); - } - return ClassLoader.getSystemResource(name); - } - public InputStream getResourceAsStream(String name) { - if (loader != null) { - return loader.getResourceAsStream(name); - } - return ClassLoader.getSystemResourceAsStream(name); - } - } - /** * Sets the parent bundle of this bundle. * The parent bundle is searched by {@link #getObject getObject} @@ -492,7 +421,6 @@ // These three are the actual keys for lookup in Map. private String name; private Locale locale; - private LoaderReference loaderRef; // bundle format which is necessary for calling // Control.needsReload(). @@ -515,14 +443,9 @@ // of this instance. private int hashCodeCache; - CacheKey(String baseName, Locale locale, ClassLoader loader) { + CacheKey(String baseName, Locale locale) { this.name = baseName; this.locale = locale; - if (loader == null) { - this.loaderRef = null; - } else { - loaderRef = new LoaderReference(loader, referenceQueue, this); - } calculateHashCode(); } @@ -550,10 +473,6 @@ return this; } - ClassLoader getLoader() { - return (loaderRef != null) ? loaderRef.get() : null; - } - public boolean equals(Object other) { if (this == other) { return true; @@ -572,17 +491,7 @@ if (!locale.equals(otherEntry.locale)) { return false; } - //are refs (both non-null) or (both null)? - if (loaderRef == null) { - return otherEntry.loaderRef == null; - } - ClassLoader loader = loaderRef.get(); - return (otherEntry.loaderRef != null) - // with a null reference we can no longer find - // out which class loader was referenced; so - // treat it as unequal - && (loader != null) - && (loader == otherEntry.loaderRef.get()); + return true; } catch (NullPointerException e) { } catch (ClassCastException e) { } @@ -596,19 +505,11 @@ private void calculateHashCode() { hashCodeCache = name.hashCode() << 3; hashCodeCache ^= locale.hashCode(); - ClassLoader loader = getLoader(); - if (loader != null) { - hashCodeCache ^= loader.hashCode(); - } } public Object clone() { try { CacheKey clone = (CacheKey) super.clone(); - if (loaderRef != null) { - clone.loaderRef = new LoaderReference(loaderRef.get(), - referenceQueue, clone); - } // Clear the reference to a Throwable clone.cause = null; return clone; @@ -651,7 +552,7 @@ l = "\"\""; } } - return "CacheKey[" + name + ", lc=" + l + ", ldr=" + getLoader() + return "CacheKey[" + name + ", lc=" + l + "(format=" + format + ")]"; } } @@ -665,25 +566,6 @@ } /** - * References to class loaders are weak references, so that they can be - * garbage collected when nobody else is using them. The ResourceBundle - * class has no reason to keep class loaders alive. - */ - private static final class LoaderReference extends WeakReference - implements CacheKeyReference { - private CacheKey cacheKey; - - LoaderReference(ClassLoader referent, ReferenceQueue q, CacheKey key) { - super(referent, q); - cacheKey = key; - } - - public CacheKey getCacheKey() { - return cacheKey; - } - } - - /** * References to bundles are soft references so that they can be garbage * collected when they have no hard references. */ @@ -722,8 +604,6 @@ public static final ResourceBundle getBundle(String baseName) { return getBundleImpl(baseName, Locale.getDefault(), - /* must determine loader here, else we break stack invariant */ - getLoader(), Control.INSTANCE); } @@ -765,7 +645,6 @@ Control control) { return getBundleImpl(baseName, Locale.getDefault(), /* must determine loader here, else we break stack invariant */ - getLoader(), control); } @@ -795,7 +674,6 @@ { return getBundleImpl(baseName, locale, /* must determine loader here, else we break stack invariant */ - getLoader(), Control.INSTANCE); } @@ -840,7 +718,6 @@ Control control) { return getBundleImpl(baseName, targetLocale, /* must determine loader here, else we break stack invariant */ - getLoader(), control); } @@ -1025,7 +902,7 @@ if (loader == null) { throw new NullPointerException(); } - return getBundleImpl(baseName, locale, loader, Control.INSTANCE); + return getBundleImpl(baseName, locale, Control.INSTANCE); } /** @@ -1243,11 +1120,11 @@ if (loader == null || control == null) { throw new NullPointerException(); } - return getBundleImpl(baseName, targetLocale, loader, control); + return getBundleImpl(baseName, targetLocale, control); } private static ResourceBundle getBundleImpl(String baseName, Locale locale, - ClassLoader loader, Control control) { + Control control) { if (locale == null || control == null) { throw new NullPointerException(); } @@ -1256,7 +1133,7 @@ // name and loader will never change during the bundle loading // process. We have to make sure that the locale is set before // using it as a cache key. - CacheKey cacheKey = new CacheKey(baseName, locale, loader); + CacheKey cacheKey = new CacheKey(baseName, locale); ResourceBundle bundle = null; // Quick lookup of the cache. @@ -1388,7 +1265,7 @@ // the same bundles having different parents. BundleReference bundleRef = cacheList.get(cacheKey); if (bundleRef != null && bundleRef.get() == bundle) { - cacheList.remove(cacheKey, bundleRef); + cacheList.remove(cacheKey); } } } @@ -1434,7 +1311,7 @@ String format = formats.get(i); try { bundle = control.newBundle(cacheKey.getName(), targetLocale, format, - cacheKey.getLoader(), reload); + null, reload); } catch (LinkageError error) { // We need to handle the LinkageError case due to // inconsistent case-sensitivity in ClassLoader. @@ -1562,7 +1439,7 @@ assert bundle != NONEXISTENT_BUNDLE; bundle.expired = true; bundle.cacheKey = null; - cacheList.remove(cacheKey, bundleRef); + cacheList.remove(cacheKey); bundle = null; } else { CacheKey key = bundleRef.getCacheKey(); @@ -1581,7 +1458,7 @@ bundle.expired = control.needsReload(key.getName(), key.getLocale(), key.getFormat(), - key.getLoader(), + null, bundle, key.loadTime); } catch (Exception e) { @@ -1593,7 +1470,7 @@ // return the bundle with the expired flag // on. bundle.cacheKey = null; - cacheList.remove(cacheKey, bundleRef); + cacheList.remove(cacheKey); } else { // Update the expiration control info. and reuse // the same bundle instance @@ -1603,7 +1480,7 @@ } } else { // We just remove NONEXISTENT_BUNDLE from the cache. - cacheList.remove(cacheKey, bundleRef); + cacheList.remove(cacheKey); bundle = null; } } @@ -1630,7 +1507,7 @@ bundle.cacheKey = key; // Put the bundle in the cache if it's not been in the cache. - BundleReference result = cacheList.putIfAbsent(key, bundleRef); + BundleReference result = cacheList.put(key, bundleRef); // If someone else has put the same bundle in the cache before // us and it has not expired, we should use the one in the cache. @@ -1677,7 +1554,7 @@ * @see ResourceBundle.Control#getTimeToLive(String,Locale) */ public static final void clearCache() { - clearCache(getLoader()); + clearCache(null); } /** @@ -1695,9 +1572,7 @@ } Set set = cacheList.keySet(); for (CacheKey key : set) { - if (key.getLoader() == loader) { - set.remove(key); - } + set.remove(key); } } @@ -2300,13 +2175,25 @@ if (baseName == null) { throw new NullPointerException(); } - return new ArrayList<>(CANDIDATES_CACHE.get(locale.getBaseLocale())); + return new ArrayList<>(CANDIDATES_CACHE.get(locale)); } private static final CandidateListCache CANDIDATES_CACHE = new CandidateListCache(); - private static class CandidateListCache extends LocaleObjectCache> { - protected List createObject(BaseLocale base) { + private static class CandidateListCache { + private Locale prevQuery; + private List prevResult; + + public List get(Locale l) { + if (prevQuery == l) { + return prevResult; + } + prevResult = createObject(l); + prevQuery = l; + return prevResult; + } + + protected List createObject(Locale base) { String language = base.getLanguage(); String script = base.getScript(); String region = base.getRegion(); @@ -2563,7 +2450,9 @@ if (format.equals("java.class")) { try { Class bundleClass - = (Class)loader.loadClass(bundleName); + = (Class)(loader != null ? + loader.loadClass(bundleName) : + Class.forName(bundleName)); // If the class isn't a ResourceBundle subclass, throw a // ClassCastException. @@ -2579,39 +2468,15 @@ final String resourceName = toResourceName(bundleName, "properties"); final ClassLoader classLoader = loader; final boolean reloadFlag = reload; - InputStream stream = null; - try { - stream = AccessController.doPrivileged( - new PrivilegedExceptionAction() { - public InputStream run() throws IOException { - InputStream is = null; - if (reloadFlag) { - URL url = classLoader.getResource(resourceName); - if (url != null) { - URLConnection connection = url.openConnection(); - if (connection != null) { - // Disable caches to get fresh data for - // reloading. - connection.setUseCaches(false); - is = connection.getInputStream(); - } - } - } else { - is = classLoader.getResourceAsStream(resourceName); - } - return is; - } - }); - } catch (PrivilegedActionException e) { - throw (IOException) e.getException(); - } + InputStream stream = classLoader != null ? classLoader.getResourceAsStream(resourceName) : + ResourceBundle.class.getResourceAsStream("/" + resourceName); if (stream != null) { try { bundle = new PropertyResourceBundle(stream); } finally { stream.close(); } - } + } } else { throw new IllegalArgumentException("unknown format: " + format); } @@ -2730,6 +2595,7 @@ } boolean result = false; try { +/* String resourceName = toResourceName(toBundleName(baseName, locale), format); URL url = loader.getResource(resourceName); if (url != null) { @@ -2752,6 +2618,7 @@ } result = lastModified >= loadTime; } + */ } catch (NullPointerException npe) { throw npe; } catch (Exception e) { diff -r 804f6f982f4e -r c794024954b5 rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/ResourceBundleTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/ResourceBundleTest.java Thu Oct 03 17:36:44 2013 +0200 @@ -0,0 +1,46 @@ +/** + * Back 2 Browser Bytecode Translator + * Copyright (C) 2012 Jaroslav Tulach + * + * 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, version 2 of the License. + * + * 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. Look for COPYING file in the top folder. + * If not, see http://opensource.org/licenses/GPL-2.0. + */ +package org.apidesign.bck2brwsr.tck; + +import java.io.InputStream; +import java.net.URL; +import java.util.ResourceBundle; +import org.apidesign.bck2brwsr.vmtest.Compare; +import org.apidesign.bck2brwsr.vmtest.VMTest; +import org.testng.annotations.Factory; + +/** + * + * @author Jaroslav Tulach + */ +public class ResourceBundleTest { + + @Compare public String readFromBundle() throws Exception { + ResourceBundle b = ResourceBundle.getBundle("org/apidesign/bck2brwsr/tck/Bundle"); + return b.getString("KEY"); + } + + @Compare public String toURIFromURL() throws Exception { + URL u = new URL("http://apidesign.org"); + return u.toURI().toString(); + } + + @Factory public static Object[] create() { + return VMTest.create(ResourceBundleTest.class); + } +} diff -r 804f6f982f4e -r c794024954b5 rt/emul/compact/src/test/resources/org/apidesign/bck2brwsr/tck/Bundle.properties --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rt/emul/compact/src/test/resources/org/apidesign/bck2brwsr/tck/Bundle.properties Thu Oct 03 17:36:44 2013 +0200 @@ -0,0 +1,2 @@ +KEY=Value +