1.1 --- a/rt/emul/compact/src/main/java/java/util/ResourceBundle.java Thu Oct 03 15:40:35 2013 +0200
1.2 +++ b/rt/emul/compact/src/main/java/java/util/ResourceBundle.java Thu Oct 03 17:36:44 2013 +0200
1.3 @@ -45,19 +45,7 @@
1.4 import java.lang.ref.ReferenceQueue;
1.5 import java.lang.ref.SoftReference;
1.6 import java.lang.ref.WeakReference;
1.7 -import java.net.JarURLConnection;
1.8 import java.net.URL;
1.9 -import java.net.URLConnection;
1.10 -import java.security.AccessController;
1.11 -import java.security.PrivilegedAction;
1.12 -import java.security.PrivilegedActionException;
1.13 -import java.security.PrivilegedExceptionAction;
1.14 -import java.util.concurrent.ConcurrentHashMap;
1.15 -import java.util.concurrent.ConcurrentMap;
1.16 -import java.util.jar.JarEntry;
1.17 -
1.18 -import sun.util.locale.BaseLocale;
1.19 -import sun.util.locale.LocaleObjectCache;
1.20
1.21
1.22 /**
1.23 @@ -288,8 +276,8 @@
1.24 * This variable would be better named "cache", but we keep the old
1.25 * name for compatibility with some workarounds for bug 4212439.
1.26 */
1.27 - private static final ConcurrentMap<CacheKey, BundleReference> cacheList
1.28 - = new ConcurrentHashMap<>(INITIAL_CACHE_SIZE);
1.29 + private static final Map<CacheKey, BundleReference> cacheList
1.30 + = new HashMap<>(INITIAL_CACHE_SIZE);
1.31
1.32 /**
1.33 * Queue for reference objects referring to class loaders or bundles.
1.34 @@ -410,65 +398,6 @@
1.35 return locale;
1.36 }
1.37
1.38 - /*
1.39 - * Automatic determination of the ClassLoader to be used to load
1.40 - * resources on behalf of the client. N.B. The client is getLoader's
1.41 - * caller's caller.
1.42 - */
1.43 - private static ClassLoader getLoader() {
1.44 - Class[] stack = getClassContext();
1.45 - /* Magic number 2 identifies our caller's caller */
1.46 - Class c = stack[2];
1.47 - ClassLoader cl = (c == null) ? null : c.getClassLoader();
1.48 - if (cl == null) {
1.49 - // When the caller's loader is the boot class loader, cl is null
1.50 - // here. In that case, ClassLoader.getSystemClassLoader() may
1.51 - // return the same class loader that the application is
1.52 - // using. We therefore use a wrapper ClassLoader to create a
1.53 - // separate scope for bundles loaded on behalf of the Java
1.54 - // runtime so that these bundles cannot be returned from the
1.55 - // cache to the application (5048280).
1.56 - cl = RBClassLoader.INSTANCE;
1.57 - }
1.58 - return cl;
1.59 - }
1.60 -
1.61 - private static native Class[] getClassContext();
1.62 -
1.63 - /**
1.64 - * A wrapper of ClassLoader.getSystemClassLoader().
1.65 - */
1.66 - private static class RBClassLoader extends ClassLoader {
1.67 - private static final RBClassLoader INSTANCE = AccessController.doPrivileged(
1.68 - new PrivilegedAction<RBClassLoader>() {
1.69 - public RBClassLoader run() {
1.70 - return new RBClassLoader();
1.71 - }
1.72 - });
1.73 - private static final ClassLoader loader = ClassLoader.getSystemClassLoader();
1.74 -
1.75 - private RBClassLoader() {
1.76 - }
1.77 - public Class<?> loadClass(String name) throws ClassNotFoundException {
1.78 - if (loader != null) {
1.79 - return loader.loadClass(name);
1.80 - }
1.81 - return Class.forName(name);
1.82 - }
1.83 - public URL getResource(String name) {
1.84 - if (loader != null) {
1.85 - return loader.getResource(name);
1.86 - }
1.87 - return ClassLoader.getSystemResource(name);
1.88 - }
1.89 - public InputStream getResourceAsStream(String name) {
1.90 - if (loader != null) {
1.91 - return loader.getResourceAsStream(name);
1.92 - }
1.93 - return ClassLoader.getSystemResourceAsStream(name);
1.94 - }
1.95 - }
1.96 -
1.97 /**
1.98 * Sets the parent bundle of this bundle.
1.99 * The parent bundle is searched by {@link #getObject getObject}
1.100 @@ -492,7 +421,6 @@
1.101 // These three are the actual keys for lookup in Map.
1.102 private String name;
1.103 private Locale locale;
1.104 - private LoaderReference loaderRef;
1.105
1.106 // bundle format which is necessary for calling
1.107 // Control.needsReload().
1.108 @@ -515,14 +443,9 @@
1.109 // of this instance.
1.110 private int hashCodeCache;
1.111
1.112 - CacheKey(String baseName, Locale locale, ClassLoader loader) {
1.113 + CacheKey(String baseName, Locale locale) {
1.114 this.name = baseName;
1.115 this.locale = locale;
1.116 - if (loader == null) {
1.117 - this.loaderRef = null;
1.118 - } else {
1.119 - loaderRef = new LoaderReference(loader, referenceQueue, this);
1.120 - }
1.121 calculateHashCode();
1.122 }
1.123
1.124 @@ -550,10 +473,6 @@
1.125 return this;
1.126 }
1.127
1.128 - ClassLoader getLoader() {
1.129 - return (loaderRef != null) ? loaderRef.get() : null;
1.130 - }
1.131 -
1.132 public boolean equals(Object other) {
1.133 if (this == other) {
1.134 return true;
1.135 @@ -572,17 +491,7 @@
1.136 if (!locale.equals(otherEntry.locale)) {
1.137 return false;
1.138 }
1.139 - //are refs (both non-null) or (both null)?
1.140 - if (loaderRef == null) {
1.141 - return otherEntry.loaderRef == null;
1.142 - }
1.143 - ClassLoader loader = loaderRef.get();
1.144 - return (otherEntry.loaderRef != null)
1.145 - // with a null reference we can no longer find
1.146 - // out which class loader was referenced; so
1.147 - // treat it as unequal
1.148 - && (loader != null)
1.149 - && (loader == otherEntry.loaderRef.get());
1.150 + return true;
1.151 } catch (NullPointerException e) {
1.152 } catch (ClassCastException e) {
1.153 }
1.154 @@ -596,19 +505,11 @@
1.155 private void calculateHashCode() {
1.156 hashCodeCache = name.hashCode() << 3;
1.157 hashCodeCache ^= locale.hashCode();
1.158 - ClassLoader loader = getLoader();
1.159 - if (loader != null) {
1.160 - hashCodeCache ^= loader.hashCode();
1.161 - }
1.162 }
1.163
1.164 public Object clone() {
1.165 try {
1.166 CacheKey clone = (CacheKey) super.clone();
1.167 - if (loaderRef != null) {
1.168 - clone.loaderRef = new LoaderReference(loaderRef.get(),
1.169 - referenceQueue, clone);
1.170 - }
1.171 // Clear the reference to a Throwable
1.172 clone.cause = null;
1.173 return clone;
1.174 @@ -651,7 +552,7 @@
1.175 l = "\"\"";
1.176 }
1.177 }
1.178 - return "CacheKey[" + name + ", lc=" + l + ", ldr=" + getLoader()
1.179 + return "CacheKey[" + name + ", lc=" + l
1.180 + "(format=" + format + ")]";
1.181 }
1.182 }
1.183 @@ -665,25 +566,6 @@
1.184 }
1.185
1.186 /**
1.187 - * References to class loaders are weak references, so that they can be
1.188 - * garbage collected when nobody else is using them. The ResourceBundle
1.189 - * class has no reason to keep class loaders alive.
1.190 - */
1.191 - private static final class LoaderReference extends WeakReference<ClassLoader>
1.192 - implements CacheKeyReference {
1.193 - private CacheKey cacheKey;
1.194 -
1.195 - LoaderReference(ClassLoader referent, ReferenceQueue q, CacheKey key) {
1.196 - super(referent, q);
1.197 - cacheKey = key;
1.198 - }
1.199 -
1.200 - public CacheKey getCacheKey() {
1.201 - return cacheKey;
1.202 - }
1.203 - }
1.204 -
1.205 - /**
1.206 * References to bundles are soft references so that they can be garbage
1.207 * collected when they have no hard references.
1.208 */
1.209 @@ -722,8 +604,6 @@
1.210 public static final ResourceBundle getBundle(String baseName)
1.211 {
1.212 return getBundleImpl(baseName, Locale.getDefault(),
1.213 - /* must determine loader here, else we break stack invariant */
1.214 - getLoader(),
1.215 Control.INSTANCE);
1.216 }
1.217
1.218 @@ -765,7 +645,6 @@
1.219 Control control) {
1.220 return getBundleImpl(baseName, Locale.getDefault(),
1.221 /* must determine loader here, else we break stack invariant */
1.222 - getLoader(),
1.223 control);
1.224 }
1.225
1.226 @@ -795,7 +674,6 @@
1.227 {
1.228 return getBundleImpl(baseName, locale,
1.229 /* must determine loader here, else we break stack invariant */
1.230 - getLoader(),
1.231 Control.INSTANCE);
1.232 }
1.233
1.234 @@ -840,7 +718,6 @@
1.235 Control control) {
1.236 return getBundleImpl(baseName, targetLocale,
1.237 /* must determine loader here, else we break stack invariant */
1.238 - getLoader(),
1.239 control);
1.240 }
1.241
1.242 @@ -1025,7 +902,7 @@
1.243 if (loader == null) {
1.244 throw new NullPointerException();
1.245 }
1.246 - return getBundleImpl(baseName, locale, loader, Control.INSTANCE);
1.247 + return getBundleImpl(baseName, locale, Control.INSTANCE);
1.248 }
1.249
1.250 /**
1.251 @@ -1243,11 +1120,11 @@
1.252 if (loader == null || control == null) {
1.253 throw new NullPointerException();
1.254 }
1.255 - return getBundleImpl(baseName, targetLocale, loader, control);
1.256 + return getBundleImpl(baseName, targetLocale, control);
1.257 }
1.258
1.259 private static ResourceBundle getBundleImpl(String baseName, Locale locale,
1.260 - ClassLoader loader, Control control) {
1.261 + Control control) {
1.262 if (locale == null || control == null) {
1.263 throw new NullPointerException();
1.264 }
1.265 @@ -1256,7 +1133,7 @@
1.266 // name and loader will never change during the bundle loading
1.267 // process. We have to make sure that the locale is set before
1.268 // using it as a cache key.
1.269 - CacheKey cacheKey = new CacheKey(baseName, locale, loader);
1.270 + CacheKey cacheKey = new CacheKey(baseName, locale);
1.271 ResourceBundle bundle = null;
1.272
1.273 // Quick lookup of the cache.
1.274 @@ -1388,7 +1265,7 @@
1.275 // the same bundles having different parents.
1.276 BundleReference bundleRef = cacheList.get(cacheKey);
1.277 if (bundleRef != null && bundleRef.get() == bundle) {
1.278 - cacheList.remove(cacheKey, bundleRef);
1.279 + cacheList.remove(cacheKey);
1.280 }
1.281 }
1.282 }
1.283 @@ -1434,7 +1311,7 @@
1.284 String format = formats.get(i);
1.285 try {
1.286 bundle = control.newBundle(cacheKey.getName(), targetLocale, format,
1.287 - cacheKey.getLoader(), reload);
1.288 + null, reload);
1.289 } catch (LinkageError error) {
1.290 // We need to handle the LinkageError case due to
1.291 // inconsistent case-sensitivity in ClassLoader.
1.292 @@ -1562,7 +1439,7 @@
1.293 assert bundle != NONEXISTENT_BUNDLE;
1.294 bundle.expired = true;
1.295 bundle.cacheKey = null;
1.296 - cacheList.remove(cacheKey, bundleRef);
1.297 + cacheList.remove(cacheKey);
1.298 bundle = null;
1.299 } else {
1.300 CacheKey key = bundleRef.getCacheKey();
1.301 @@ -1581,7 +1458,7 @@
1.302 bundle.expired = control.needsReload(key.getName(),
1.303 key.getLocale(),
1.304 key.getFormat(),
1.305 - key.getLoader(),
1.306 + null,
1.307 bundle,
1.308 key.loadTime);
1.309 } catch (Exception e) {
1.310 @@ -1593,7 +1470,7 @@
1.311 // return the bundle with the expired flag
1.312 // on.
1.313 bundle.cacheKey = null;
1.314 - cacheList.remove(cacheKey, bundleRef);
1.315 + cacheList.remove(cacheKey);
1.316 } else {
1.317 // Update the expiration control info. and reuse
1.318 // the same bundle instance
1.319 @@ -1603,7 +1480,7 @@
1.320 }
1.321 } else {
1.322 // We just remove NONEXISTENT_BUNDLE from the cache.
1.323 - cacheList.remove(cacheKey, bundleRef);
1.324 + cacheList.remove(cacheKey);
1.325 bundle = null;
1.326 }
1.327 }
1.328 @@ -1630,7 +1507,7 @@
1.329 bundle.cacheKey = key;
1.330
1.331 // Put the bundle in the cache if it's not been in the cache.
1.332 - BundleReference result = cacheList.putIfAbsent(key, bundleRef);
1.333 + BundleReference result = cacheList.put(key, bundleRef);
1.334
1.335 // If someone else has put the same bundle in the cache before
1.336 // us and it has not expired, we should use the one in the cache.
1.337 @@ -1677,7 +1554,7 @@
1.338 * @see ResourceBundle.Control#getTimeToLive(String,Locale)
1.339 */
1.340 public static final void clearCache() {
1.341 - clearCache(getLoader());
1.342 + clearCache(null);
1.343 }
1.344
1.345 /**
1.346 @@ -1695,9 +1572,7 @@
1.347 }
1.348 Set<CacheKey> set = cacheList.keySet();
1.349 for (CacheKey key : set) {
1.350 - if (key.getLoader() == loader) {
1.351 - set.remove(key);
1.352 - }
1.353 + set.remove(key);
1.354 }
1.355 }
1.356
1.357 @@ -2300,13 +2175,25 @@
1.358 if (baseName == null) {
1.359 throw new NullPointerException();
1.360 }
1.361 - return new ArrayList<>(CANDIDATES_CACHE.get(locale.getBaseLocale()));
1.362 + return new ArrayList<>(CANDIDATES_CACHE.get(locale));
1.363 }
1.364
1.365 private static final CandidateListCache CANDIDATES_CACHE = new CandidateListCache();
1.366
1.367 - private static class CandidateListCache extends LocaleObjectCache<BaseLocale, List<Locale>> {
1.368 - protected List<Locale> createObject(BaseLocale base) {
1.369 + private static class CandidateListCache {
1.370 + private Locale prevQuery;
1.371 + private List<Locale> prevResult;
1.372 +
1.373 + public List<Locale> get(Locale l) {
1.374 + if (prevQuery == l) {
1.375 + return prevResult;
1.376 + }
1.377 + prevResult = createObject(l);
1.378 + prevQuery = l;
1.379 + return prevResult;
1.380 + }
1.381 +
1.382 + protected List<Locale> createObject(Locale base) {
1.383 String language = base.getLanguage();
1.384 String script = base.getScript();
1.385 String region = base.getRegion();
1.386 @@ -2563,7 +2450,9 @@
1.387 if (format.equals("java.class")) {
1.388 try {
1.389 Class<? extends ResourceBundle> bundleClass
1.390 - = (Class<? extends ResourceBundle>)loader.loadClass(bundleName);
1.391 + = (Class<? extends ResourceBundle>)(loader != null ?
1.392 + loader.loadClass(bundleName) :
1.393 + Class.forName(bundleName));
1.394
1.395 // If the class isn't a ResourceBundle subclass, throw a
1.396 // ClassCastException.
1.397 @@ -2579,39 +2468,15 @@
1.398 final String resourceName = toResourceName(bundleName, "properties");
1.399 final ClassLoader classLoader = loader;
1.400 final boolean reloadFlag = reload;
1.401 - InputStream stream = null;
1.402 - try {
1.403 - stream = AccessController.doPrivileged(
1.404 - new PrivilegedExceptionAction<InputStream>() {
1.405 - public InputStream run() throws IOException {
1.406 - InputStream is = null;
1.407 - if (reloadFlag) {
1.408 - URL url = classLoader.getResource(resourceName);
1.409 - if (url != null) {
1.410 - URLConnection connection = url.openConnection();
1.411 - if (connection != null) {
1.412 - // Disable caches to get fresh data for
1.413 - // reloading.
1.414 - connection.setUseCaches(false);
1.415 - is = connection.getInputStream();
1.416 - }
1.417 - }
1.418 - } else {
1.419 - is = classLoader.getResourceAsStream(resourceName);
1.420 - }
1.421 - return is;
1.422 - }
1.423 - });
1.424 - } catch (PrivilegedActionException e) {
1.425 - throw (IOException) e.getException();
1.426 - }
1.427 + InputStream stream = classLoader != null ? classLoader.getResourceAsStream(resourceName) :
1.428 + ResourceBundle.class.getResourceAsStream("/" + resourceName);
1.429 if (stream != null) {
1.430 try {
1.431 bundle = new PropertyResourceBundle(stream);
1.432 } finally {
1.433 stream.close();
1.434 }
1.435 - }
1.436 + }
1.437 } else {
1.438 throw new IllegalArgumentException("unknown format: " + format);
1.439 }
1.440 @@ -2730,6 +2595,7 @@
1.441 }
1.442 boolean result = false;
1.443 try {
1.444 +/*
1.445 String resourceName = toResourceName(toBundleName(baseName, locale), format);
1.446 URL url = loader.getResource(resourceName);
1.447 if (url != null) {
1.448 @@ -2752,6 +2618,7 @@
1.449 }
1.450 result = lastModified >= loadTime;
1.451 }
1.452 + */
1.453 } catch (NullPointerException npe) {
1.454 throw npe;
1.455 } catch (Exception e) {